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;
};
}