现在的位置: 首页 > 综合 > 正文

Android中使用ListView绘制自定义表格

2013年09月12日 ⁄ 综合 ⁄ 共 10011字 ⁄ 字号 评论关闭

先上一下可以实现的效果图 

要实现的效果有几方面

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来实现行合并。

抱歉!评论已关闭.