【Android|【Android ListView】解决使用onMeasure处理高度问题后复用问题

先来看个图:

【Android|【Android ListView】解决使用onMeasure处理高度问题后复用问题
文章图片
device-2017-11-29-103650.png 遇上这种需求在我还是小白的时候做法是这样的:


【【Android|【Android ListView】解决使用onMeasure处理高度问题后复用问题】emm,一切顺利 run。
惊喜的发现ListView显示的这是啥啊,后来才知道这是因为ListView跟ScrollView冲突的问题。
那么如何解决这个问题 方法1:在XML中写死
android:layout_width="match_parent" android:layout_height="120dp"

方法2:自定义ListView在onMeasure里面计算高度
关键代码:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }

第一种方法,显然适用性不高。
第二种方法,会让listview失去复用的机制,导致更新数据的时候卡顿。
那么问题来了,我怎么处理好呢?
其实ListView有这么一个方法
listView.addHeaderView(view);

把列表以上的控件,使用"View.inflate()",的方式,add到ListView上面,这样以来ListView就不会失去复用机制,上方的控件也能正常操作。需要注意的是,这样会使用上方的控件,其实就是ListView的item之一,下方列表在操作的时候,position需要 -1。
那么问题又来了,这么写的话,就需要把原本一个xml的方法拆成两个,上方控件也不能简单的findViewById。
为了解决这个问题,这里封装了一个ListHeadView,用来处理这个麻烦的操作。
此控件中已经处理了position的问题,代码如下,具体实现请看源码。
listHeadView.setOnItemClick(new ListHeadView.onItemClick() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) {} });

import android.content.Context; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.ListView; /** * 描述:简单实现ListViewHeadView * * @author songdehuai * @ClassName: com.songdehuai.headview.widget.ListHeadView * @date 2017/11/10 9:22 */ public class ListHeadView extends LinearLayout implements AdapterView.OnItemClickListener {private ListView mListView; private BaseAdapter mAdapter; public ListHeadView(Context context) throws Exception { this(context, null, -1); }public ListHeadView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, -1); }public ListHeadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }void initViews(Context context) { mListView = new ListView(context); ViewGroup.LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); mListView.setLayoutParams(layoutParams); mListView.setOnItemClickListener(this); }@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mAdapter != null) { try { View view = this.getChildAt(0); if (mListView.getHeaderViewsCount() == 0) { this.removeViewAt(0); mListView.addHeaderView(view); this.addView(mListView); } } catch (Exception e) { e.printStackTrace(); } } }public ListView listView() { return mListView; }public void setAdapter(BaseAdapter adapter) { initViews(getContext()); this.mAdapter = adapter; mListView.setAdapter(adapter); }private onItemClick mOnItemClick; public void setOnItemClick(onItemClick mOnItemClick) { this.mOnItemClick = mOnItemClick; }public interface onItemClick { void onItemClick(AdapterView parent, View view, int position, long id); }@Override public void onItemClick(AdapterView parent, View view, int position, long id) { position = position - 1; if (mOnItemClick != null) { mOnItemClick.onItemClick(parent, view, position, id); } } }

Github:https://github.com/songdehuai/HeadView
目前子View只能存在一个,就像ScrollView那样使用。
见识不多,能力不足,待优化的地方还很多。

    推荐阅读