您的位置:首页 > 其它

使用LinearLayout实现ListView,解决ListView和ScrollView滚动冲突

2015-10-26 17:49 549 查看

概述

我们常常会遇到一个ScrollView里面会嵌套ListView的情况,但往往你会发现,ListView和ScrollView的滚动时间会有冲突问题。那么如何解决呢?这是本文的意义所在。

使用LinearLayout实现ListView

自定义一个View,我这取名为LinearLayoutForListView。直接看代码:

public class LinearLayoutForListView extends LinearLayout {
private Adapter mAdapter;
private SparseArray<View> mViewHolders;
private AdapterDataSetObserver mDataSetObserver;
public LinearLayoutForListView(Context context) {
super(context);
}

public LinearLayoutForListView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public LinearLayoutForListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

private void bindView(){
setOrientation(LinearLayout.VERTICAL);
final int count = mAdapter.getCount();
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
mViewHolders = new SparseArray<View>(count);
for(int i = 0; i < count; i++){
View v = mAdapter.getView(i,null,null);
mViewHolders.put(i,v);
addView(v, layoutParams);
}
}

public void setAdapter(Adapter adapter){
mAdapter = adapter;
bindView();
}

public Adapter getAdapter(){
return mAdapter;
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
LogUtils.d("AdapterDataSetObserver.java", "onAttachedToWindow");
if(mAdapter != null && mDataSetObserver == null){
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if(mAdapter != null && mDataSetObserver != null){
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
LogUtils.d("AdapterDataSetObserver.java","onDetachedFromWindow");
}

private class AdapterDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
final int count = mAdapter.getCount();
for (int i = 0; i < count; i++){
mAdapter.getView(i,mViewHolders.get(i,null),null);
}
requestLayout();
LogUtils.d("AdapterDataSetObserver.java","onChanged");
}
}
}


首先,我们需要一个Adapter来填充数据,在setAdapter的时候去bindView添加Adapter的item view,这里使用一个ViewHolder去缓存item view。接着,我们需要注册一个DataSetObserver,当Adapter调用notifyDataSetChanged的时候更新列表,这里我们定义了一个内部类AdapterDataSetObserver,然后在onChanged通过ViewHolder从缓存里取出View,给adapter的getView去更新界面数据。至于,什么时候去注册这个DataSetObserver,什么时候取消注册,我们可以通过AbsListView源码中发现,它是在onAttachedToWindow注册,在onDetachedFromWindow取消注册。不足的是,这里的缓存并没有实现ListView里的RecycleBin。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息