欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中使用ListView绘制自定义表格技巧分享

程序员文章站 2023-11-04 14:32:52
先上一下可以实现的效果图  要实现的效果有几方面 1、列不固定:可以根据数据源的不同生成不同的列数 2、表格内容可以根据数据源的定义合并列 3、要填写的单元格可以...
先上一下可以实现的效果图
Android中使用ListView绘制自定义表格技巧分享 
要实现的效果有几方面
1、列不固定:可以根据数据源的不同生成不同的列数
2、表格内容可以根据数据源的定义合并列
3、要填写的单元格可以选择自定义键盘还是系统键盘
奔着这三点,做了个简单的实现,把源码贴一下(因为该点是主界面中的一部分,不便于放整个demo)
自定义适配器,callbackinterface是自定义的回调接口,这里定义回调是因为数据输入时需要及时保存
复制代码 代码如下:

public class sitedetailviewadapter extends baseadapter implements callbackinterface{
private context context;
private layoutinflater inflater;
private arraylist<hashmap<string,object>> lists;
private keyboard keyboard = null;//自定义键盘
private listview listview = null;
private boolean isreadonly = false;//是否是浏览状态
private string[] arrcelltype = null;
private int[] arrheadwidth = null;//每列宽度

public sitedetailviewadapter(context context, arraylist<hashmap<string,object>> lists
,keyboard keyboard,listview listview,boolean isreadonly
,int[] arrheadwidth) {
super();
this.context = context;
this.lists = lists;
inflater = layoutinflater.from(context);
this.keyboard = keyboard;
this.listview = listview;
this.isreadonly = isreadonly;
this.arrheadwidth = arrheadwidth;
this.listview.setadapter(this);
}
@override
public int getcount() {
// todo auto-generated method stub
return lists.size();
}
@override
public object getitem(int arg0) {
// todo auto-generated method stub
return arg0;
}
@override
public long getitemid(int arg0) {
// todo auto-generated method stub
return arg0;
}
@override
public view getview(int index, view view, viewgroup arg2) {
hashmap map = lists.get(index);
string type = (string)map.get("rowtype");

arraylist<itemcell> itemcells = new arraylist();
//string cellvalue,string cellkey,long celltype,int cellinrow,int cellspan
itemcell itemcellxuhao = new itemcell((index+1)+"","-1",1,-1,1);
itemcells.add(itemcellxuhao);
for(int i=0;i<map.size()-1;i++){
itemcell itemcell = (itemcell)map.get(i+"");
itemcells.add(itemcell);
}
//性能优化后需要放开注释danielinbiti
if(view == null||view!=null&&!((listitemcustom)view.gettag()).gettype().equals(type)){
view = inflater.inflate(r.layout.customel_list_item, null);
listitemcustom itemcustom = (listitemcustom)view.findviewbyid(r.id.custome_item);
itemcustom.builditem(type, context, isreadonly,arrheadwidth,itemcells,index
,this.listview,this.keyboard,this);
view.settag(itemcustom);
}else{
listitemcustom itemcustom = (listitemcustom)view.gettag();
itemcustom.refreshdata(itemcells,index);
}
if(index%2 == 0){
view.setbackgroundcolor(color.argb(250 , 255 , 255 , 255 ));
}else{
view.setbackgroundcolor(color.argb(250 , 224 , 243 , 250 ));
}
return view;
}
@override
public boolean exectuemethod(object params) {
string[] arr = (string[])params;
hashmap map = lists.get(integer.parseint(arr[0]));
itemcell itemcell = (itemcell)map.get(arr[1]);
itemcell.setcellvalue(arr[2]);
itemcell.setischange(true);
return false;
}

listview每行的布局,内部代码是有冗余的,因为是demo,所以先以效果未准,未进行代码重构,注意不能往listitemcustom中传入每行的map来进行值得获取或者输入更新等操作,因为map是按地址方式,再结合listview的绘制方式,最终的map不是你想象的map。
复制代码 代码如下:

public class listitemcustom extends linearlayout{
public listitemcustom(context context){
super(context);
}
public listitemcustom(context context, attributeset attrs) {
super(context, attrs);
}
private string type = "-1";
private context context = null;
private boolean isread = false;
private int[] headwidtharr = null;
private listview listview = null;
private keyboard keyboard = null;
private int ordernum = -1;
private arraylist<view> viewlist = new arraylist();
private int rownum = -1;
private callbackinterface callback = null;
public void builditem(string type,context context,boolean isread,int[] headwidtharr
,arraylist<itemcell> itemcells,int rownum
,listview listview,keyboard keyboard,callbackinterface callback){
this.context = context;
this.isread = isread;
this.headwidtharr = headwidtharr;
this.setorientation(linearlayout.vertical);
this.rownum = rownum;
this.listview = listview;
this.keyboard = keyboard;
this.callback = callback;
this.type = type;
this.setlayoutparams(new linearlayout.layoutparams(layoutparams.match_parent,45));

this.addcell(itemcells);
}
public void refreshdata(arraylist<itemcell> itemcells,int rownum){
this.rownum = rownum;
this.refreshcells(itemcells);
}
private void refreshcells(arraylist<itemcell> itemcells){
for(int i=0;i<itemcells.size();i++){
itemcell itemcell = itemcells.get(i);
if(itemcell.getcelltype()==itemcellvaluetype.value_none){
textview view = (textview)viewlist.get(i);
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
}else if(itemcell.getcelltype()==itemcellvaluetype.value_number){
edittext view= (edittext)viewlist.get(i);
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
//view.settext(itemcell.getcellid()+"");
//view.settag(itemcell.getcellkey()+"");
this.seteditview(view,itemcell.getcellkey());
this.setonkeyborad(view, itemcell.getcellinrow());
}else if(itemcell.getcelltype()==itemcellvaluetype.value_string){
edittext view= (edittext)viewlist.get(i);
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
//view.settext(itemcell.getcellid()+"");
//view.settag(itemcell.getcellkey()+"");
this.seteditview(view,itemcell.getcellkey());
}
}
}
private int getcellwidth(int cellstart,int cellend){
int width = 0;
for(int i=cellstart;i<cellend;i++){
width = this.headwidtharr[i] + width;
}
return width;
}
private void addcell(arraylist<itemcell> itemcells){
linearlayout secondlayout = new linearlayout(context);
secondlayout.setorientation(linearlayout.horizontal);
secondlayout.setlayoutparams(new linearlayout.layoutparams(layoutparams.match_parent,layoutparams.wrap_content));
this.addview(secondlayout);
int cellindex = 0;
for(int i=0;i<itemcells.size();i++){
itemcell itemcell = itemcells.get(i);
int endindex = cellindex+itemcell.getcellspan();
int width = getcellwidth(cellindex,endindex);
cellindex = endindex;
if(itemcell.getcelltype()==itemcellvaluetype.value_none){
textview view = (textview)getreadview();
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
view.setwidth(width);
secondlayout.addview(view);
viewlist.add(view);
}else if(itemcell.getcelltype()==itemcellvaluetype.value_number){
edittext view= (edittext)getinputview();
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
view.setwidth(width);
//view.settext(itemcell.getcellid()+"");
//view.settag(itemcell.getcellkey()+"");
this.seteditview(view,itemcell.getcellkey());
this.setonkeyborad(view, itemcell.getcellinrow());
secondlayout.addview(view);
viewlist.add(view);
}else if(itemcell.getcelltype()==itemcellvaluetype.value_string){
edittext view= (edittext)getinputview();
view.setid(itemcell.getcellid());
view.settext(itemcell.getcellvalue());
view.setwidth(width);
//view.settext(itemcell.getcellid()+"");
//view.settag(itemcell.getcellkey()+"");
this.seteditview(view,itemcell.getcellkey());
secondlayout.addview(view);
viewlist.add(view);
}
if(i!=itemcells.size()-1){
linearlayout v_line = (linearlayout)getverticalline();
v_line.setlayoutparams(new linearlayout.layoutparams(layoutparams.wrap_content,layoutparams.wrap_content));
secondlayout.addview(v_line);
}
}
}
private view getverticalline(){
return layoutinflater.from(context).inflate(r.layout.atom_line_v_view, null);
}
private view getreadview(){
return (view)layoutinflater.from(context).inflate(r.layout.atom_text_view, null);
}
private view getinputview(){
return (view)layoutinflater.from(context).inflate(r.layout.atom_edttxt_view, null);
}
private void setonkeyborad(edittext edttext1,int index){
if(!this.isread){
onlistentext(edttext1,this.listview,index);
}
}
private void onlistentext(edittext edttext,listview listview,int index){
final listview lsv = listview;
final int idx = index;
edttext.setonfocuschangelistener(new onfocuschangelistener(){
@override
public void onfocuschange(view arg0, boolean arg1) {
if(arg1){
int[] y = getypos(lsv,idx);
keyboard.show((edittext)arg0,y[0],y[1]);
}
}
});
}
private int[] getypos(listview listview,int index){
int[] yposarr = new int[2];
rect r = new rect();
listview.getchildat(0).getglobalvisiblerect(r);
int first = listview.getfirstvisibleposition();
yposarr[1] = (index-first+1)*r.height()+listview.gettop();
yposarr[0] = (index-first)*r.height()+listview.gettop();
return yposarr;
}
private void seteditview(edittext edttext1,final string key){
if(this.isread){
edttext1.setenabled(false);
}else{
edttext1.addtextchangedlistener(new textwatcher() {
@override
public void aftertextchanged(editable arg0) {
string[] arr = new string[3];
arr[0] = rownum+"";
arr[1] = key;
arr[2] = arg0.tostring();
callback.exectuemethod(arr);
// itemcell itemcell = (itemcell)datamap.get(key);
// itemcell.setcellvalue(arg0.tostring());
// itemcell.setischange(true);
}

@override
public void beforetextchanged(charsequence arg0, int arg1, int arg2,
int arg3) {

}

@override
public void ontextchanged(charsequence arg0, int arg1, int arg2,
int arg3) {

}
});
}
}
public string gettype(){
return this.type;
}
}

复制代码 代码如下:

public class itemcell {
private string cellvalue = "";
private int cellspan = 1;
private string cellkey = "";
private int cellinrow = 0;
private long celltype = itemcellvaluetype.value_none;
private int colnum = 0;
private int rowtype = 0;
private int cellid = -1;
private boolean isvaluefromtable = false;

private boolean ischange = false;
public itemcell(string cellvalue,string cellkey,long celltype,int cellinrow,int cellspan){
this.cellvalue = cellvalue;
this.celltype = celltype;
this.cellspan = cellspan;
this.cellkey = cellkey;
this.cellinrow = cellinrow;
}
public itemcell(string cellvalue,string cellkey,long celltype,int cellinrow){
this(cellvalue,cellkey,celltype,cellinrow,1);
}
public void setcolnum(int colnum){
this.colnum = colnum;
}
public int getcolnum(){
return this.colnum;
}
public void setrowtype(int rowtype){
this.rowtype = rowtype;
}
public int getrowtype(){
return this.rowtype;
}
public string getcellvalue(){
return cellvalue;
}
public void setcellvalue(string value){
this.cellvalue = value;
}
public long getcelltype(){
return celltype;
}
public int getcellspan(){
return cellspan;
}
public string getcellkey(){
return cellkey;
}
public int getcellinrow(){
return cellinrow;
}
public void setischange(boolean ischange){
this.ischange = ischange;
}
public boolean getischange(){
return this.ischange;
}
public int getcellid() {
return cellid;
}
public void setcellid(int cellid) {
this.cellid = cellid;
}
public boolean isvaluefromtable() {
return isvaluefromtable;
}
public void setvaluefromtable(boolean isvaluefromtable) {
this.isvaluefromtable = isvaluefromtable;
}
}

custome_list_item.xml文件
复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:id="@+id/test_dajej"
android:background="#ffffff">
<srit.collection.widget.costomtable.listitemcustom android:id="@+id/custome_item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</linearlayout>

以上是核心的文件内容。有了列合并,行合并也不远了。可以在自定义的布局中多加个linearlayout来实现行合并。