android 自定义表格
本文通过scrollview 嵌套 listview来实现滚动表格功能。
实现效果如下图:
如上图所示实现功能如下:
1、列表头 和 数据 可以左右滑动,方便超出屏幕数据查看。
2、行表头 和 数据 可以上下滑动,方便超出屏幕数据查看。
3、左右滑动时 行表头固定,上下滑动时 列表头固定。
实现代码如下:
package com.uuch.android_zxinglibrary.tableview; /** * created by wangqiubo on 2018-02-05. */ import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.linearlayout; import android.widget.textview; import com.uuch.android_zxinglibrary.r; import java.util.arraylist; import java.util.list; public class tableactivity extends appcompatactivity { private noscrolllistview mleft; private leftadapter mleftadapter; private noscrolllistview mdata; private dataadapter mdataadapter; private synchorizontalscrollview mheaderhorizontal; private synchorizontalscrollview mdatahorizontal; private list mlistdata; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.list_row_main_layout); initview(); } private void initview(){ mleft = (noscrolllistview) findviewbyid(r.id.lv_left); mdata = (noscrolllistview) findviewbyid(r.id.lv_data); mdatahorizontal = (synchorizontalscrollview) findviewbyid(r.id.data_horizontal); mheaderhorizontal = (synchorizontalscrollview) findviewbyid(r.id.header_horizontal); mdatahorizontal.setscrollview(mheaderhorizontal); mheaderhorizontal.setscrollview(mdatahorizontal); mlistdata = new arraylist<>(); mlistdata.add("1"); mlistdata.add("2"); mlistdata.add("3"); mlistdata.add("4"); mlistdata.add("5"); mlistdata.add("6"); mlistdata.add("7"); mlistdata.add("8"); mlistdata.add("9"); mlistdata.add("10"); mlistdata.add("11"); mlistdata.add("12"); mlistdata.add("13"); mleftadapter= new leftadapter(); mleft.setadapter(mleftadapter); mdataadapter = new dataadapter(); mdata.setadapter(mdataadapter); } class leftadapter extends baseadapter { @override public int getcount() { return mlistdata.size(); } @override public object getitem(int position) { return mlistdata.get(position); } @override public long getitemid(int position) { return position; } @override public view getview(int position, view convertview, viewgroup parent) { viewholder holder = null; if (convertview == null) { holder = new viewholder(); convertview = layoutinflater.from(tableactivity.this).inflate(r.layout.table_column_left_layout, null); holder.tvleft = (textview) convertview.findviewbyid(r.id.tv_left); convertview.settag(holder); } else { holder = (viewholder) convertview.gettag(); } holder.tvleft.settext("第" + position + "行"); return convertview; } class viewholder { textview tvleft; } } class dataadapter extends baseadapter { @override public int getcount() { return mlistdata.size(); } @override public object getitem(int position) { return mlistdata.get(position); } @override public long getitemid(int position) { return position; } @override public view getview(int position, view convertview, viewgroup parent) { viewholder holder = null; if(convertview == null){ holder = new viewholder(); convertview = layoutinflater.from(tableactivity.this).inflate(r.layout.achievement_row_layout, null); holder.tvdata = (textview) convertview.findviewbyid(r.id.tv_data); holder.lincontent = (linearlayout) convertview.findviewbyid(r.id.lin_content); convertview.settag(holder); }else{ holder = (viewholder) convertview.gettag(); } return convertview; } class viewholder { textview tvdata; linearlayout lincontent; } } }
list_row_main_layout.xml
对以上代码进行讲解如下:
1、noscrolllistview的定义。
package com.uuch.android_zxinglibrary.tableview; import android.content.context; import android.util.attributeset; import android.widget.listview; /** * created by wangqiubo on 2018-02-05. */ public class noscrolllistview extends listview { public noscrolllistview(context context) { super(context); } public noscrolllistview(context context, attributeset attrs) { super(context, attrs); } public noscrolllistview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } /* *scrollview 中嵌套 listview 会发现有冲突,冲突问题就是无论怎么设置 listview 只显示一行 * 究其原因就是因为listview的父容器测量模式为unspecified的时候,listview的高度默认为一个item的高度 * 那么解决冲突,就需要重新设定listview的测量模式,因此,以下重写就是重写设置listview的测量模式为 most * unspecified 的值是0向左进位30,就是10 00000000000…(10后跟30个0) * exactly 的值是1向左进位30,就是01 00000000000…(01后跟30个0) * at_most 的值是2向左进位30,就是10 00000000000…(10后跟30个0) **/ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { int expandspec = measurespec.makemeasurespec(integer.max_value >> 2, measurespec.at_most); super.onmeasure(widthmeasurespec, expandspec); } }
当scrollview 中嵌套 listview 的时候,怎样解决 scrollview、listview 不会同时滚动呢?另外如果scrollview 中嵌套了 listview ,一般listview 只会显示一行。根据上面noscrolllistview 的定义,实现思想就是 让listview不能滚动,实现不滚动的原理就是把所有数据都在listview 展示出来。因此通过设置 at_most 模式,让所有子项都显示出来,那么listview就不再滚动,这样只有scrollview 可以滚动了。
2、synchorizontalscrollview,水平滚动定义。
package com.uuch.android_zxinglibrary.tableview; import android.content.context; import android.util.attributeset; import android.view.view; import android.widget.horizontalscrollview; /** /** * created by wangqiubo on 2018-02-05. */ public class synchorizontalscrollview extends horizontalscrollview { private view mview; public synchorizontalscrollview(context context) { super(context); } public synchorizontalscrollview(context context, attributeset attrs) { super(context, attrs); } public synchorizontalscrollview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } protected void onscrollchanged(int l, int t, int oldl, int oldt) { super.onscrollchanged(l, t, oldl, oldt); if (mview != null) { mview.scrollto(l, t); } } public void setscrollview(view view) { mview = view; } }
以上自定义水平滚动效果就是,当horizontalscrollview 滚动的时候,那么设置进来的mview 同步滚动,请查看 tableactivity 中的代码:
mdatahorizontal = (synchorizontalscrollview) findviewbyid(r.id.data_horizontal); mheaderhorizontal = (synchorizontalscrollview) findviewbyid(r.id.header_horizontal); mdatahorizontal.setscrollview(mheaderhorizontal); mheaderhorizontal.setscrollview(mdatahorizontal);
mdatahorizontal 为行数据,mheaderhorizontal 为 列表头,mdatahorizontal 中的同步滚动mview = mheaderhorizontal;mheaderhorizontal中的同步滚动控件mview = mdatahorizontal 。因此,就实现了行数据和列表头可以同时左右滚动。
以上自定义的滑动表格存在问题如下:
noscrolllistview是通过设置 at_most 模式来解决 scrollview 中嵌套 listview 的滑动冲突问题。at_most 就是尺寸根据子节点的实际大小来确定最终大小,因此需要不停的来结算子节点的尺寸,如果涉及到大数据,就涉及到性能性问题。