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

android 自定义表格

程序员文章站 2023-01-06 09:06:46
本文通过scrollview 嵌套 listview来实现滚动表格功能。 实现效果如下图: 如上图所示实现功能如下: 1、列表头 和 数据 可以左右滑动,方便超出屏幕数据查看。 2、行表头 和 数...

本文通过scrollview 嵌套 listview来实现滚动表格功能。
实现效果如下图:
android 自定义表格

如上图所示实现功能如下:
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 就是尺寸根据子节点的实际大小来确定最终大小,因此需要不停的来结算子节点的尺寸,如果涉及到大数据,就涉及到性能性问题。