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

先来看个图:


【Android ListView】解决使用onMeasure处理高度问题后复用问题_第1张图片
device-2017-11-29-103650.png

遇上这种需求在我还是小白的时候做法是这样的:

 

        

            
                
            

            
        

    

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那样使用。
见识不多,能力不足,待优化的地方还很多。

你可能感兴趣的:(【Android ListView】解决使用onMeasure处理高度问题后复用问题)