android Listview固定列头

Android Listview固定列头

背景

之前Listview列是通过把列名作为第一行的数据实现的,当Listview数据行超过一定高度时会出现滚动条,当滚动条向下滚动时作为列头的第一行就会向上滚动,最后看不见 ,影响用户体验,如何在向下滚动时固定列表不动呢?

在网上查阅相关资料有的通过监听滚动距离来实现,综合各种信息最后采用了单独控件做列头的方案,该方案不使用任何第三方控件,简单容易理解,独立于Listview,无论Listview向下滚动单独控件列头都不会跟着滚动,达到了固定列头的效果。

主要思路是title列和Listview行共享一个布局文件,只有共享同一个布局文件才能保证列头和行对齐,然后用HorizontalScrollView包裹起来,Listview渲染数据时,可以自定义行的style,以跟title样式区分。因为HorizontalScrollView只能包含一个控件,所以要先通过ConstraintLayout先将title列和Listview包裹起来,这里用HorizontalScrollView的目的是ListView列多的情况下通过左右滚动条可以浏览全部列的数据。

实现步骤:

1、activity布局文件 activity_barcode_check_doc_list_form.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".forms.warehouse.BarcodeCheckDocListForm">
   

    <HorizontalScrollView
        android:layout_width="fill_parent"
        android:layout_height="280dp"

        android:id="@+id/horizontalScrollView"

        tools:layout_constraintTop_creator="1"
        tools:layout_constraintBottom_creator="1"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="0dp"
        app:layout_constraintTop_toBottomOf="@+id/lblDocAmount"

        tools:layout_constraintLeft_creator="1"
        android:layout_marginBottom="20dp"
        app:layout_constraintLeft_toLeftOf="parent"
        >

        <android.support.constraint.ConstraintLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

        <!---固定列-->
        <include android:id="@+id/listview_title"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            layout="@layout/barcode_check_doc_list">
        </include>

        <ListView
            android:id="@+id/listView_Barcode"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/listview_title"
            android:layout_marginTop="40dp"
            android:choiceMode="singleChoice"
            tools:layout_constraintTop_creator="1"
            tools:layout_constraintRight_creator="1"
            tools:layout_constraintBottom_creator="1"
            tools:layout_constraintLeft_creator="1" />
        </android.support.constraint.ConstraintLayout>
    </HorizontalScrollView>

</android.support.constraint.ConstraintLayout>

2、title列和Listview行的布局文件 barcode_check_doc_list.xml

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/text_doc_no"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:gravity="center"
        android:paddingBottom="10dip"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:text="订单"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:textSize="15sp" />

    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

    <TextView
        android:id="@+id/text_check_type"
        android:layout_width="100dip"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:paddingBottom="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:textSize="15sp"
        android:gravity="center"
        android:text="盘点类型" />
    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

    <TextView
        android:id="@+id/text_cyc_sku_no_list"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:paddingBottom="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:textSize="15sp"
        android:gravity="center"
        android:text="待盘点产品" />
    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

    <TextView
        android:id="@+id/text_cyc_lot_no_list"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:paddingBottom="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:textSize="15sp"
        android:gravity="center"
        android:text="待盘点批号" />
    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>
    <TextView
        android:id="@+id/text_cyc_area_no_list"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:gravity="center"
        android:paddingBottom="10dip"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:text="待盘点库区"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:textSize="15sp" />

    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>
    <TextView
        android:id="@+id/text_act_qty"
        android:visibility="gone"
        android:layout_width="100dip"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:paddingBottom="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:textSize="15sp"
        android:gravity="center"
        android:text="实际数量" />

    <View
        android:visibility="gone"
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

    <TextView
        android:id="@+id/text_line_no"
        android:layout_width="150dip"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:paddingBottom="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:paddingTop="10dip"
        android:singleLine="true"
        android:textSize="15sp"
        android:gravity="center"
        android:text="行号" />

    <View
        android:layout_width="1.5dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

    <TextView
        android:id="@+id/text_doc_status"
        android:layout_width="0dip"
        android:visibility="gone"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingBottom="10dip"
        android:paddingTop="10dip"
        android:textColor="#ffffff"
        android:background="@color/colorPrimary"
        android:textSize="15sp"
        android:singleLine="true"
        android:text="订单状态" />

    <View
        android:visibility="gone"
        android:layout_width="1.50dip"
        android:layout_height="fill_parent"
        android:background="#B4B3B3"/>

</LinearLayout>

3、Listview数据源适配器类 TableAdapter_BarcodeCheckDocList

package com.qixuan.www.codeplusapp.adapters;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.qixuan.www.codeplusapp.R;
import com.qixuan.www.codeplusapp.common.CommonUtil;
import com.qixuan.www.codeplusapp.entity.BarcodeCheckDoc;
import com.qixuan.www.codeplusapp.entity.OutboundLPN;
import com.qixuan.www.codeplusapp.entity.ProduceJobDoc;

import java.util.List;

public class TableAdapter_BarcodeCheckDocList extends BaseAdapter {

    private ListView lv;
    private List<BarcodeCheckDoc> list;
    private LayoutInflater inflater;
    private int selectedItem = -1;
    public TableAdapter_BarcodeCheckDocList(Context context, ListView lv, List<BarcodeCheckDoc> list){
        this.list = list;
        this.lv=lv;
        inflater = LayoutInflater.from(context);
    }


    @Override
    public int getCount() {
        int ret = 0;
        if(list!=null){
            ret = list.size();
        }
        return ret;
    }

    public void setSelectedItem(int selectedItem) {
        this.selectedItem = selectedItem;
        this.notifyDataSetChanged(); //必须调养该方法,否则getView不会重新触发,背景色就不会改变
    }

    //设置行不可点击
    @Override
    public boolean isEnabled(int position) {
        return true;
    }
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        BarcodeCheckDoc goods = (BarcodeCheckDoc) this.getItem(position);

        ViewHolder viewHolder;

        if(convertView == null){

            viewHolder = new ViewHolder();

            convertView = inflater.inflate(R.layout.barcode_check_doc_list, null);

            viewHolder.doc_no = (TextView) convertView.findViewById(R.id.text_doc_no);
            viewHolder.line_no = (TextView) convertView.findViewById(R.id.text_line_no);
            viewHolder.check_type = (TextView) convertView.findViewById(R.id.text_check_type);
            viewHolder.cyc_sku_no_list = (TextView) convertView.findViewById(R.id.text_cyc_sku_no_list);
            viewHolder.cyc_lot_no_list = (TextView) convertView.findViewById(R.id.text_cyc_lot_no_list);
            viewHolder.cyc_area_no_list = (TextView) convertView.findViewById(R.id.text_cyc_area_no_list);
            viewHolder.act_qty = (TextView) convertView.findViewById(R.id.text_act_qty);
            viewHolder.doc_status = (TextView) convertView.findViewById(R.id.text_doc_status);

            //批量设置各列TextView背景颜色透明
            CommonUtil.ClearListViewOldRowBackgroundColor(viewHolder);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
        }

       //设置行新样式
        viewHolder.doc_no.setText(goods.doc_no);
        viewHolder.doc_no.setTextSize(13);
        viewHolder.line_no.setText(goods.line_no);
        viewHolder.line_no.setTextSize(13);
        viewHolder.check_type.setText(goods.check_type);
        viewHolder.check_type.setTextSize(13);
        viewHolder.cyc_sku_no_list.setText(goods.cyc_sku_no_list);
        viewHolder.cyc_sku_no_list.setTextSize(13);
        viewHolder.cyc_lot_no_list.setText(goods.cyc_lot_no_list);
        viewHolder.cyc_lot_no_list.setTextSize(13);
        viewHolder.cyc_area_no_list.setText(goods.cyc_area_no_list);
        viewHolder.cyc_area_no_list.setTextSize(13);
        viewHolder.act_qty.setText(goods.act_qty);
        viewHolder.act_qty.setTextSize(13);
        viewHolder.doc_status.setText(goods.doc_status);
        viewHolder.doc_status.setTextSize(13);


        if(this.lv.isItemChecked(position)) //选中行样式
        {
            convertView.setBackgroundColor(Color.BLUE);

            //设置选中行的字体颜色为白色
            viewHolder.doc_no.setTextColor(Color.WHITE);
            viewHolder.line_no.setTextColor(Color.WHITE);
            viewHolder.check_type.setTextColor(Color.WHITE);
            viewHolder.cyc_sku_no_list.setTextColor(Color.WHITE);
            viewHolder.cyc_lot_no_list.setTextColor(Color.WHITE);
            viewHolder.cyc_area_no_list.setTextColor(Color.WHITE);
            viewHolder.act_qty.setTextColor(Color.WHITE);
            viewHolder.doc_status.setTextColor(Color.WHITE);
        }
        else {//不选中样式
            convertView.setBackgroundColor(Color.parseColor("#CCCCCC"));
            //设置选中行的字体颜色为黑色
            viewHolder.doc_no.setTextColor(Color.BLACK);
            viewHolder.line_no.setTextColor(Color.BLACK);
            viewHolder.check_type.setTextColor(Color.BLACK);
            viewHolder.cyc_sku_no_list.setTextColor(Color.BLACK);
            viewHolder.cyc_lot_no_list.setTextColor(Color.BLACK);
            viewHolder.cyc_area_no_list.setTextColor(Color.BLACK);
            viewHolder.act_qty.setTextColor(Color.BLACK);
            viewHolder.doc_status.setTextColor(Color.BLACK);
        }
        return convertView;
    }

    public static class ViewHolder{
        //public TextView diyid;
        public TextView doc_no;
        public TextView line_no;
        public TextView check_type;
        public TextView cyc_sku_no_list;
        public TextView cyc_lot_no_list;
        public TextView cyc_area_no_list;
        public TextView act_qty;
        public TextView doc_status;

    }

}

4、Listview和数据源绑定

listView_Barcode.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);

        //添加数据行
        for(int i=0;i<10;i++) {
            li_docs_all.add(new BarcodeCheckDoc(Integer.toString(i), "00"+Integer.toString(i), "全盘", "ENA001"+Integer.toString(i), "Bat"+Integer.toString(i), "Area", "0", "盘点中"));
        }
        adapter = new TableAdapter_BarcodeCheckDocList(this,listView_Barcode, li_docs_all);

        listView_Barcode.setAdapter(adapter);

5、实体类 BarcodeCheckDoc

package com.qixuan.www.codeplusapp.entity;

import java.io.Serializable;

public class BarcodeCheckDoc implements Serializable {

    public String doc_no="";
    public String line_no="";
    public String check_type ="";
    public String cyc_sku_no_list ="";
    public String cyc_lot_no_list ="";
    public String cyc_area_no_list ="";
    public String act_qty="";
    public String doc_status="";

    public BarcodeCheckDoc(){
        super();};
    public BarcodeCheckDoc(String doc_no,String line_no,String check_type,String cyc_sku_no_list,String cyc_lot_no_list,String cyc_area_no_list,String act_qty,String doc_status){
        this.doc_no=doc_no;
        this.line_no=line_no;
        this.check_type=check_type;
        this.cyc_sku_no_list=cyc_sku_no_list;
        this.cyc_lot_no_list=cyc_lot_no_list;
        this.cyc_area_no_list=cyc_area_no_list;
        this.act_qty=act_qty;
        this.doc_status=doc_status;
    };
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Android中的ListView是一个常用的控件,用于展示数据列表,但是在数据非常长的情况下,用户在滚动ListView的时候发现,表头也会随着滚动消失,不再显示在顶部,这个体验并不好。 为了解决这个问题,我们可以通过自定义ListView的头部来实现表头的固定。具体实现如下: 1.在ListView布局文件中,添加一个LinearLayout布局,作为表头,同时将ListView的头部设为这个LinearLayout。 2.为该LinearLayout添加一个固定高度的属性,例如: android:layout_height="50dp"。这个高度取决于表头的高度。 3.在ListView布局文件中,为ListView添加下面的属性: android:scrollbars="none",这样就可以禁止滚动条的显示。 4.在Activity中,我们需要定义一个适配器继承自BaseAdapter类。在getView方法中,我们需要添加一段代码: if(position == 0){ headerView = convertView; convertView = null; } 这样,在ListView的第一个元素也就是表头处,我们就可以设置为固定不动的headerView。 5.最后,我们需要在Activity的onCreate方法中,为ListView设置adpter。 通过以上几个步骤,我们就可以实现ListView表头的固定。这样,当我们滚动ListView时,表头仍然保持在屏幕顶部,用户可以清晰地看到表头的信息。 ### 回答2: Android中的ListView是一个非常常用的控件,主要用于展示一系列数据。但是,在ListView展示大量数据时,往往需要我们实现固定列头的功能,以便用户更好地查看数据。下面,我将分享一下如何实现[ListView固定列头](https://blog.csdn.net/u010687392/article/details/78822213)的方法。 首先,我们可以使用两个ListView来实现这个功能。第一个ListView用于展示列头,第二个ListView用于展示数据。我们将第二个ListView的滚动事件监听器设置为:当滑动ListView时,首先将第二个ListView的内容向上滚动,然后将第一个ListView的内容向下滚动,以此来实现列头固定。但是,这种方法有一个问题,就是使用两个ListView会影响ListView的滑动效率。 另外,我们还可以通过自定义控件的方式实现固定列头。首先,我们要新建一个继承自ListView的类MyListView。然后,在这个类中,我们重写了onMeasure()方法,来计算出第一行item的高度,这个高度将会被用作上面那个固定列头的高度。并且在ListView中添加HeaderView,因为HeaderView不会随着滚动而滚动。接下来,我们将一个LinearLayout嵌套在MyListView中,用于显示固定列头。在LinearLayout中,我们将会创建一个子控件,用于展示每个列的列名,然后再创建一个HorizontalScrollView来放置起下面的ListView。在这个方法中,我们还需要重写onScrollChanged()方法,使得当下方的ListView滚动时,上方的列头也会跟着滚动。 以上两种方法,都可以实现ListView固定列头的效果。但是,为了不影响ListView的滑动效率以及为了加强代码复用性,我们建议使用自定义控件的方式实现固定列头。自定义控件的方式虽然复杂一些,但是这样做将会更加稳定和可扩展。 ### 回答3: 在Android中,ListView是一个常见的控件,用于在列表中显示数据。然而,在一些情况下,我们需要将ListView列头固定,使其在滚动时保持在屏幕顶部,以便用户在滚动后仍能了解列表内容。 首先,我们需要在ListView布局文件中添加一个Header View,用于显示列头,这可以使用ListView的addHeaderView()方法来实现。例如,我们可以在ListView的XML布局文件中添加以下代码: ```xml <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 添加Header视图 --> <LinearLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- 列头 --> <TextView android:id="@+id/textview_header_1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="列头1" /> <TextView android:id="@+id/textview_header_2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="列头2" /> <TextView android:id="@+id/textview_header_3" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="列头3" /> </LinearLayout> </ListView> ``` 接下来,在代码中使用ViewTreeObserver来监听ListView布局变化,并在布局完成后将Header View添加到ListView中。在onCreate()方法中添加以下代码: ```java final ListView listView = findViewById(R.id.listview); final LinearLayout headerView = findViewById(R.id.header); final TextView textViewHeader1 = findViewById(R.id.textview_header_1); final TextView textViewHeader2 = findViewById(R.id.textview_header_2); final TextView textViewHeader3 = findViewById(R.id.textview_header_3); // 监听布局变化 ViewTreeObserver vto = listView.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 移除监听 listView.getViewTreeObserver().removeOnGlobalLayoutListener(this); // 获取第一项的高度 int height = listView.getChildAt(0).getHeight(); // 将Header视图添加到ListView listView.addHeaderView(headerView); // 设置Header视图的高度 headerView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, height)); // 设置列头的宽度 textViewHeader1.setWidth(headerView.getWidth() / 3); textViewHeader2.setWidth(headerView.getWidth() / 3); textViewHeader3.setWidth(headerView.getWidth() / 3); } }); ``` 这个方法在ListView布局完成后被调用,它首先获取第一项的高度,并将Header View添加到ListView中。然后,将HeaderView的高度设置为第一项的高度。最后,设置列头的宽度以便它们与ListView中的条目对齐。 最后,在ListView中使用OnScrollListener监听滚动事件,并在滚动时调整Header View的位置,使其保持在ListView的顶部。在Activity中添加以下代码: ```java listView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // 获取Header View View headerView = listView.getChildAt(0); // 如果ListView的第一项可见,则将Header View添加到WindowManager中 if (listView.getFirstVisiblePosition() == 0) { headerView.setVisibility(View.VISIBLE); // 获取屏幕宽度 DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int screenWidth = metrics.widthPixels; // 调整Header View的位置 WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) headerView.getLayoutParams(); layoutParams.x = 0; layoutParams.y = 0; layoutParams.width = screenWidth; getWindowManager().updateViewLayout(headerView, layoutParams); } else { headerView.setVisibility(View.GONE); } } }); ``` 这个方法在滚动时被调用,它首先获取Header View。如果ListView的第一项可见,则将Header View 添加到WindowManager中,并将其调整到屏幕顶部。否则,将其隐藏。 综上所述,通过在布局文件中添加HeaderView,监听布局变化,设置列头宽度和高度,以及在滚动时调整Header View的位置,我们可以实现在Android中使ListView列头固定的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值