安卓Listview隐藏列的实现

      笔者在安卓也是个小白,站在巨人的肩膀上实现了一个Listview,但因为列过多,需要对某些列可以隐藏,于是研究了一下,发现资料比较少,所以有了这篇文章记录一下。

     首先讲一下,我的Listview的实现方式:

     使用adapter管理数据源和数据的刷新。

    public ListTestAutoUpAdapter(Context ctx, List<TestAutoUpDetail> list, RelativeLayout head,boolean[] colsState) {
        this.mContext = ctx;
        this.autoUpDetailList = list;
        this.mHead = head;
        this.mInflater = LayoutInflater.from(mContext);
        widthArray = new int[]{60,120,60,60,60,60
        ,60,80,80,80,80,300};
        if(colsState == null || colsState.length != 12){
            colHideState = new boolean[]{true,true,true,true,true,true,true,true,true,true,true,true};
        }else{
            colHideState =  colsState;
        }
        Log.d("------", "ListTestAutoUpAdapter: 重新创建");
//        hideHeader();

    }
    public View getView(int i, View convertView, ViewGroup viewGroup) {
        ViewHolder holder;
//        Log.d("------", "getView: "+i);
        if(convertView == null){
            //从布局文件item_grid生成转换视图对象
            convertView = mInflater.inflate(R.layout.item_test_autoup, viewGroup, false);
            holder = new ViewHolder();
            CustomHScrollView scrollView =  convertView.findViewById(R.id.h_scrollView);
            holder.scrollView = scrollView;

            //获取布局文件的控件
            holder.tv_id = convertView.findViewById(R.id.tv_id);
            holder.tv_record_id = convertView.findViewById(R.id.tv_record_id);
            holder.tv_created_time = convertView.findViewById(R.id.tv_created_time);
            holder.tv_test_context = convertView.findViewById(R.id.tv_test_context);

            holder.llItemList = convertView.findViewById(R.id.ll_item_list);
            saveLayoutToHolder(holder,convertView);
            //将视图持有者保存到转换视图中
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        //设置控件的数据
        TestAutoUpDetail testAutoUpDetail = autoUpDetailList.get(i);
        holder.tv_id.setText(testAutoUpDetail.id+"");
        holder.tv_record_id.setText(testAutoUpDetail.test_record_id+"");
        holder.tv_created_time.setText(testAutoUpDetail.getCreatedTimeStr());
        holder.tv_test_context.setText(testAutoUpDetail.test_context);
        //传入的mHead头布局里获取滚动区域,支持该区域的滚动
        CustomHScrollView headSrcrollView =  mHead.findViewById(R.id.h_scrollView);
        //获取标题里面的父布局,然后同时设置父布局和子布局的显示隐藏状态
        hideCols(getHeaderLayoutItems(headSrcrollView),holder);

        headSrcrollView.AddOnScrollChangedListener(new OnScrollChangedListenerImp(holder.scrollView));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            holder.scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
                @Override
                public void onScrollChange(View view, int i, int i1, int i2, int i3) {
                    headSrcrollView.smoothScrollTo(i, i1);
                }
            });
        }
        holder.tv_id.setOnClickListener(new MyOnClickListener(i));
        holder.llItemList.setOnClickListener(new MyOnClickListener(i));
        return convertView;
    }
  private void saveLayoutToHolder(ViewHolder holder,View convertView) {
        holder.llItems = new LinearLayout[12];
        int a = 0;
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item1);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item2);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item3);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item4);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item5);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item6);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item7);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item8);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item9);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item10);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item11);
        holder.llItems[a++] = convertView.findViewById(R.id.ll_item12);
    }
  private LinearLayout[] getHeaderLayoutItems(CustomHScrollView headSrcrollView) {
        LinearLayout[] llItems = new LinearLayout[12];
        int a = 0;
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item1);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item2);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item3);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item4);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item5);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item6);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item7);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item8);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item9);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item10);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item11);
        llItems[a++] = headSrcrollView.findViewById(R.id.ll_item12);
        return llItems;
    }


    public void hideCols(LinearLayout[] headerLayouts,ViewHolder holder){
        int len = colHideState.length;
        int headerLen = headerLayouts.length;
        if(holder == null || holder.llItems == null){
            return;
        }
        int lenContent = holder.llItems.length;
        if(len != 12 || headerLen != 12 || lenContent != 12){
            return;
        }
        for(int i=0;i<len;i++ ){
            if(colHideState[i]){
                headerLayouts[i].setVisibility(View.VISIBLE);
                holder.llItems[i].setVisibility(View.VISIBLE);
                //只设置父布局不可见,返回还是会留下一片空白。需要恢复期宽高
                headerLayouts[i].setLayoutParams(new LinearLayout.LayoutParams(widthArray[i],35));
            }else{
                headerLayouts[i].setVisibility(View.GONE);
                holder.llItems[i].setVisibility(View.GONE);
                //只设置父布局不可见,返回还是会留下一片空白。通过人为设置其宽高为0强制父布局刷新界面可真正隐藏
                headerLayouts[i].setLayoutParams(new LinearLayout.LayoutParams(0,0));
            }
        }
    }

布局是自定义的item_test_autoup.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="horizontal"
    android:padding="5dp" >
    <!--android:descendantFocusability="blocksDescendants"  避免无法获取焦点-->
    <TextView android:id="@+id/tv_id"
        android:layout_marginTop="1dp"
        android:layout_width="50dp"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:layout_weight="1"
        android:layout_height="@dimen/item_height"
        android:gravity="center"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="@dimen/font_default_dp_size"
        android:textColor="@color/black"
        android:ellipsize="end"
        android:text="序号" />

    <com.hope.iotloramonitor.CustomHScrolView.InterceptScrollLinearLayout
        android:id="@+id/scroollContainter"
        android:layout_width="fill_parent"
        android:layout_height="@dimen/item_height"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/tv_id"
        android:focusable="false" >

        <com.hope.iotloramonitor.CustomHScrolView.CustomHScrollView
            android:id="@+id/h_scrollView"
            android:layout_width="fill_parent"
            android:layout_height="@dimen/item_height"
            android:focusable="false"
            android:scrollbars="none" >

            <LinearLayout
                android:id="@+id/ll_item_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:focusable="false"
                android:orientation="horizontal" >

                <LinearLayout
                    android:id="@+id/ll_item1"
                    android:layout_width="60dp"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_gravity="center"
                    android:orientation="vertical" >
                    <TextView android:id="@+id/tv_record_id"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="2dp"
                        android:layout_marginRight="2dp"
                        android:text="记录id"
                        android:gravity="center"
                        android:textSize="@dimen/font_default_dp_size"
                        android:textColor="@color/black"
                        android:textAppearance="?android:attr/textAppearanceMedium"
                        />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/ll_item2"
                    android:layout_width="120dp"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_gravity="center"
                    android:orientation="vertical" >
                    <TextView android:id="@+id/tv_created_time"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="2dp"
                        android:layout_marginRight="2dp"
                        android:gravity="center"
                        android:textSize="@dimen/font_default_dp_size"
                        android:textColor="@color/black"
                        android:textAppearance="?android:attr/textAppearanceMedium"
                        android:text="创建时间" />
                </LinearLayout>


                 //...省略的代码  

                <LinearLayout
                    android:id="@+id/ll_item12"
                    android:layout_width="300dp"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_gravity="center"
                    android:orientation="vertical" >

                    <TextView android:id="@+id/tv_test_context"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="2dp"
                        android:layout_marginRight="2dp"
                        android:textAppearance="?android:attr/textAppearanceMedium"
                        android:gravity="center"
                        android:textSize="@dimen/font_default_dp_size"
                        android:textColor="@color/black"
                        android:text="测试内容"/>
                </LinearLayout>
            </LinearLayout>
        </com.hope.iotloramonitor.CustomHScrolView.CustomHScrollView>
    </com.hope.iotloramonitor.CustomHScrolView.InterceptScrollLinearLayout>

</RelativeLayout>

然后我的Listview携带标题的后在主界面的格式是这样的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/content_test_table"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
    <include layout="@layout/layout_page_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <include
        android:id="@+id/head_layout"
        layout="@layout/item_test_autoup"
        />
    <com.hope.iotloramonitor.InScrollView.InScrollView
        android:id="@+id/list_view"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:minHeight="100dp"
        android:layout_weight="10"
        android:cacheColorHint="@android:color/transparent"
        android:dividerHeight="1dp"
        android:divider="@color/black">
    </com.hope.iotloramonitor.InScrollView.InScrollView>

</LinearLayout>

就是下面这样:大家可以忽略其他不相干的布局。主要是看我的listview标题也是用的item_test_autoup.xml

接下来就直奔主题了,根据我查阅的资料,我自己的实现方式是:

1、item_test_autoup.xml里面,listview的每个子控件Textview需要增加一个父布局Linelayout,在adapter的getview里获取每个item的父LineLayout,将其存到viewholder里,然后将这些列的显示隐藏数组传递过来,然后将对应的列显示隐藏。

2、通过传递进来的mHeader标题布局(其实子控件还是item_test_autoup.xml,只是布局的对象不同),获取每个标题对应的父布局Linelaout,然后通过设置父控件View.GONE,可隐藏标题。

以上实现后,已经隐藏了标题和列表了,但是,标题每次变更后经常会保留一片空白,感觉就是一个安卓的bug,因为我明明设置了wrapcontent和view.gone的,但是安卓在重新绘制的时候就是不重新计算标题的宽高,导致我滚动标题的时候,发现列表和标题对不齐。解决办法就是在设置标题的View.GONE后,同时设置其宽高为0,强制其重新计算宽高。当然可见的时候需要还原其原本的宽高,所以在构建adapter里需要初始化一个所有列的宽高进来。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值