把自定义表格又改进了一下,可以支持行合并。表格分为简单和复杂两种模式
1、简单模式就是《Android中使用ListView绘制自定义表格(2)》描述的方式。不支持行合并
2、复杂模式支持行列合并
1、基于上回上传的代码,改动文件如下
package csdn.danielinbiti.custometableview.item; public class ItemCell { private String cellValue = "";//单元格的值 private int cellSpan = 1; //单元格跨列 private CellTypeEnum cellType = CellTypeEnum.LABEL; //单元格类型 private int colNum = 0; //单元格列号,从0开始 private int rowNum = 0;//从0开始,每个item都从0开始 private int rowSpan = 1;//单元格跨行 //private int rowType = 0; //行类型 private boolean isChange = false;//是否被编辑 public ItemCell(String cellValue,CellTypeEnum cellType,int cellSpan){ this.cellValue = cellValue; this.cellType = cellType; this.cellSpan = cellSpan; } public ItemCell(String cellValue, CellTypeEnum cellType){ this(cellValue,cellType,1); } 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 CellTypeEnum getCellType(){ return cellType; } public int getCellSpan(){ return cellSpan; } public void setIsChange(boolean isChange){ this.isChange = isChange; } public boolean getIsChange(){ return this.isChange; } //设置行列位置,列根据前面列+rowspan数字累加后的值,rownum每行都从0开始 public void setPos(int rowNum,int colNum,int rowSpan){ this.rowNum = rowNum; this.colNum = colNum; this.rowSpan = rowSpan; } public int getRowNum() { return rowNum; } public int getRowSpan() { return rowSpan; } public int getId(){ return this.rowNum * 10000 + this.rowSpan; } }
CustomeTableItem.java
package csdn.danielinbiti.custometableview.item; import java.util.ArrayList; import java.util.HashMap; import csdn.danielinbiti.custometableview.R; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.LinearLayout.LayoutParams; public class CustomeTableItem extends LinearLayout { private Context context = null; private boolean isRead = false;//是否只读 private ArrayList<View> viewList = new ArrayList();//行的表格列表 private HashMap<String,View> viewMap = new HashMap();//key为行列组合 private int[] headWidthArr = null;//表头的列宽设置 private String rowType = "0";//行的样式id private int rowHeight = 0; private boolean isSimple = true;//是否简单的行模式(没有行合并) public CustomeTableItem(Context context) { super(context); } public CustomeTableItem(Context context, AttributeSet attrs) { super(context, attrs); } public CustomeTableItem(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /* * rowType:行的样式,字符任意,相同样式的行不需要再创建了 * itemCells:单元格信息 * headWidthArr:每列宽度 * isRead:是否只读,如果是只读,则所有的输入都不生效 */ public void buildItem(Context context,String rowType,ArrayList<ItemCell> itemCells ,int[] headWidthArr,boolean isRead){ if(this.getTag()!=null && this.getTag() instanceof String && this.getTag().equals("2")){//设置成2为复杂的行合并 this.isSimple = false; } this.setOrientation(LinearLayout.VERTICAL);//第一层布局垂直 this.context = context; this.headWidthArr =headWidthArr.clone(); this.rowType = rowType; if(rowHeight==0){ rowHeight = Dp2Px(context,40); } if(isSimple){ this.addCell(itemCells); }else{ this.addCellR(itemCells); } } private void addCell(ArrayList<ItemCell> itemCells){ this.removeAllViews(); 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()==CellTypeEnum.STRING){ EditText view= (EditText)getInputView(); view.setText(itemCell.getCellValue()); view.setWidth(width); this.setEditView(view); secondLayout.addView(view); viewList.add(view); }else if(itemCell.getCellType()==CellTypeEnum.DIGIT){ EditText view= (EditText)getInputView(); view.setText(itemCell.getCellValue()); view.setWidth(width); this.setEditView(view); this.setOnKeyBorad(view); secondLayout.addView(view); viewList.add(view); }else if(itemCell.getCellType()==CellTypeEnum.LABEL){ TextView view = (TextView)getLabelView(); view.setText(itemCell.getCellValue()); view.setWidth(width); 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 void addCellR(ArrayList<ItemCell> itemCells){ this.removeAllViews(); RelativeLayout secondLayout = new RelativeLayout(context); //secondLayout.setOrientation(LinearLayout.HORIZONTAL); secondLayout.setLayoutParams(new RelativeLayout.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 = itemCell.getColNum()+itemCell.getCellSpan();//所占行数 int width = getCellWidth(itemCell.getColNum(),endIndex);//行宽度 int height = getCellHeight(itemCell.getRowSpan()); int left = this.getCellLeft(itemCell.getColNum()); int top = this.getCellTop(itemCell.getRowNum()); RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); rl.leftMargin = left; rl.topMargin = top; if(itemCell.getCellType()==CellTypeEnum.STRING){ EditText view= (EditText)getInputView(); view.setText(itemCell.getCellValue()); view.setWidth(width); view.setHeight(height); this.setEditView(view); secondLayout.addView(view,rl); viewMap.put(itemCell.getId()+"", view); }else if(itemCell.getCellType()==CellTypeEnum.DIGIT){ EditText view= (EditText)getInputView(); view.setText(itemCell.getCellValue()); view.setWidth(width); view.setHeight(height); this.setEditView(view); this.setOnKeyBorad(view); secondLayout.addView(view,rl); viewMap.put(itemCell.getId()+"", view); }else if(itemCell.getCellType()==CellTypeEnum.LABEL){ TextView view = (TextView)getLabelView(); view.setText(itemCell.getCellValue()); view.setWidth(width); view.setHeight(height); secondLayout.addView(view,rl); viewMap.put(itemCell.getId()+"", 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); // } } } public void refreshData(ArrayList<ItemCell> itemCells){ if(this.isSimple){ this.refreshDataSimple(itemCells); }else{ this.refreshDataR(itemCells); } } private void refreshDataSimple(ArrayList<ItemCell> itemCells){ for(int i=0;i<itemCells.size();i++){ ItemCell itemCell = itemCells.get(i); if(itemCell.getCellType()==CellTypeEnum.LABEL){ TextView view = (TextView)viewList.get(i); view.setText(itemCell.getCellValue()); }else if(itemCell.getCellType()==CellTypeEnum.DIGIT){ EditText view= (EditText)viewList.get(i); view.setText(itemCell.getCellValue()); this.setEditView(view); this.setOnKeyBorad(view); }else if(itemCell.getCellType()==CellTypeEnum.STRING){ EditText view= (EditText)viewList.get(i); view.setText(itemCell.getCellValue()); this.setEditView(view); } } } private void refreshDataR(ArrayList<ItemCell> itemCells){ for(int i=0;i<itemCells.size();i++){ ItemCell itemCell = itemCells.get(i); if(itemCell.getCellType()==CellTypeEnum.LABEL){ TextView view = (TextView)viewMap.get(itemCell.getId()+""); view.setText(itemCell.getCellValue()); }else if(itemCell.getCellType()==CellTypeEnum.DIGIT){ EditText view= (EditText)viewMap.get(itemCell.getId()+"");; view.setText(itemCell.getCellValue()); this.setEditView(view); this.setOnKeyBorad(view); }else if(itemCell.getCellType()==CellTypeEnum.STRING){ EditText view= (EditText)viewMap.get(itemCell.getId()+"");; view.setText(itemCell.getCellValue()); this.setEditView(view); } } } private View getVerticalLine(){ return LayoutInflater.from(context).inflate(R.layout.atom_line_v_view, null); } 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 int getCellLeft(int cellIndex){//从0开始编号 int left = 0; for(int i=0;i<cellIndex;i++){ left = this.headWidthArr[i] + left; } return left; } private int getCellTop(int rowNum){ //rowNum从0开始 return rowNum*this.rowHeight; } private int Dp2Px(Context context, float dp) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } private int getCellHeight(int rowSpan){ return rowSpan * this.rowHeight; } private View getLabelView(){ 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 setEditView(EditText edtText1){ if(this.isRead){ edtText1.setEnabled(false); }else{ } } private void setOnKeyBorad(EditText edtText1){ //数字键盘 if(!this.isRead){//非只读 } } public String getRowType() { return rowType; } }
2、简单模式和复杂模式可以通过布局文件配置。不进行设置默认是简单模式
<?xml version="1.0" encoding="utf-8"?> <csdn.danielinbiti.custometableview.item.CustomeTableItem android:id="@+id/custome_item" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:tag="1" android:gravity="center_vertical" />
android:tag="2"为复杂模式,不进行配置为简单模式
3、测试数据格式
private void testAddContentRows(HashMap contentMap){ HashMap rowMap1 = new HashMap(); lists.add(rowMap1); this.testAddRows(rowMap1, 1, "r1-1-1(1)", CellTypeEnum.LABEL,0,0,1); this.testAddRows(rowMap1, 1, "r1-2-1(1)", CellTypeEnum.LABEL,1,0,1); this.testAddRows(rowMap1, 1, "r1-1-2(1)", CellTypeEnum.STRING,0,1,2); this.testAddRows(rowMap1, 2, "r1-1-3(2)", CellTypeEnum.STRING,0,2,2); this.testAddRows(rowMap1, 1, "r1-1-4(1)", CellTypeEnum.DIGIT,0,4,2);//注意这个列号的标识,必须是前面列号+跨行数 rowMap1.put("rowtype", "css1");//表样标示放在内容添加后再添加 HashMap rowMap2 = new HashMap(); lists.add(rowMap2); this.testAddRows(rowMap2, 1, "r2-1-1(1)", CellTypeEnum.LABEL,0,0,1); this.testAddRows(rowMap2, 1, "r2-2-1(1)", CellTypeEnum.LABEL,1,0,1); this.testAddRows(rowMap2, 1, "r2-1-2(2)", CellTypeEnum.STRING,0,1,2); this.testAddRows(rowMap2, 2, "r2-1-3(1)", CellTypeEnum.STRING,0,2,1); this.testAddRows(rowMap2, 2, "r2-2-3(1)", CellTypeEnum.STRING,1,2,1); this.testAddRows(rowMap2, 1, "r2-1-4(1)", CellTypeEnum.DIGIT,0,4,2); rowMap2.put("rowtype", "css2");//表样标示放在内容添加后再添加 HashMap rowMap3 = new HashMap(); lists.add(rowMap3); this.testAddRows(rowMap3, 1, "r3-1-1(1)", CellTypeEnum.LABEL,0,0,1); this.testAddRows(rowMap3, 1, "r3-2-1(1)", CellTypeEnum.LABEL,1,0,1); this.testAddRows(rowMap3, 1, "r3-2-1(1)", CellTypeEnum.LABEL,2,0,1); this.testAddRows(rowMap3, 1, "r3-1-2(2)", CellTypeEnum.STRING,0,1,3); this.testAddRows(rowMap3, 2, "r3-1-3(1)", CellTypeEnum.STRING,0,2,1); this.testAddRows(rowMap3, 2, "r3-2-3(1)", CellTypeEnum.STRING,1,2,1); this.testAddRows(rowMap3, 2, "r3-2-3(1)", CellTypeEnum.STRING,2,2,1); this.testAddRows(rowMap3, 1, "r3-1-4(1)", CellTypeEnum.DIGIT,0,4,3); rowMap3.put("rowtype", "css3");//表样标示放在内容添加后再添加 HashMap rowMap4 = new HashMap(); lists.add(rowMap4); this.testAddRows(rowMap4, 1, "r4-1-1(1)", CellTypeEnum.LABEL,0,0,1); this.testAddRows(rowMap4, 1, "r4-2-1(1)", CellTypeEnum.LABEL,1,0,1); this.testAddRows(rowMap4, 1, "r4-2-1(1)", CellTypeEnum.LABEL,2,0,1); this.testAddRows(rowMap4, 1, "r4-1-2(2)", CellTypeEnum.STRING,0,1,3); this.testAddRows(rowMap4, 2, "r4-1-3(1)", CellTypeEnum.STRING,0,2,1); this.testAddRows(rowMap4, 2, "r4-2-3(1)", CellTypeEnum.STRING,1,2,1); this.testAddRows(rowMap4, 2, "r4-2-3(1)", CellTypeEnum.STRING,2,2,1); this.testAddRows(rowMap4, 1, "r4-1-4(1)", CellTypeEnum.DIGIT,0,4,3); rowMap4.put("rowtype", "css3");//表样标示放在内容添加后再添加 }
private void testAddRows(HashMap rowMap,int colSpan,String cellValue,CellTypeEnum cellType,int rowNum,int colNum,int rowSpan){ ItemCell itemCell = new ItemCell(cellValue,cellType,colSpan); itemCell.setPos(rowNum, colNum, rowSpan); rowMap.put(rowMap.size()+"", itemCell); }
//this.testAddContent(contentMap);//简单模式,原来的代码,改行替换成下面代码就可以 this.testAddContentRows(contentMap);//复杂模式
基于listview方式的动态布局已经实现了行列合并模式,基本也就告一段落了,希望能够给后面的人提供帮助。至于一些样式的设置,这里没有具体提供,包括数字输入时的数字键盘,输入改变时数据获取等方式都没有提供,这些只能使用的人自己根据需要进行加减了。
建议对于最好弄个简单的html之类的布局设计器,这样生成能够使用的数据相对比较好点,要不人工计算数据很容易出错。
源码参见自定义表格(2) ,改动的代码已经在上面都贴出来了。
时间: 2024-10-23 03:43:03