Android中Scrollview、ViewPager、ListView冲突问题 (亲测可用)

来源:互联网 发布:淘宝网折叠床单人价格 编辑:程序博客网 时间:2024/05/22 08:18
1、重写Scrollview
public class MyScrollView extends ScrollView {
private float xDistance, yDistance, xLast, yLast;

public MyScrollView(Context context) {
super(context);
}

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

public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();

xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;

if (xDistance > yDistance) {
return false;
}
}

return super.onInterceptTouchEvent(ev);
}

}
2、重写ListView
public class CustomListView extends ListView {

public CustomListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

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

public CustomListView(Context context) {
super(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
setMeasuredDimension(widthMeasureSpec, expandSpec);
super.onMeasure(widthMeasureSpec, expandSpec);
}

}


3、XML布局文件
<xxx.MyScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

                <android.support.v4.view.ViewPager
                    android:id="@+id/viewpager_layout"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
<xxx.CustomListView
                 android:id="@+id/listview"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:cacheColorHint="@color/transparent"
                android:descendantFocusability="blocksDescendants"
                 android:fastScrollEnabled="true"
                 android:focusable="true"
                 android:listSelector="@color/transparent"
                 android:scrollbars="none" />
        </LinearLayout>
        </LinearLayout>
</xxx.MyScrollView>

5、ListView外部加个LinearLayout的原由是因为时间久了,ListView不能响应滑动事件了。google原因如下:

只要是listview上下滑动卡顿,其主要原因是因为在listview填充适配器的时候。在重写的类BaseAdapter方法getView();被无限的循环的调用;这样消耗了大量的内存导致listview上下滑动的时候,出现了卡顿。原因就在于measure过程,ListView一般都会根据屏幕加载多个Item,而且也会同时显示这些已经加载过的若干组Item,而这些Item的父元素都是这个ListView。

通过Google的解释:View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。对于ListView,当然每一个Item都会被调用Measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。 根据我的经验,height和width最好都设置成fill_parent,这样能避免listview对getView的疯狂调用。 解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。 还有一点请注意,如果使用了上面的动态测量来设置listview的显示高度,并使用了fill_parent来设置了listview的属性,但是仍然不能停止adapter中getView()方法的疯狂调用;或者还伴有listview内容显示仍然不完全现象; 根据我自己的实践经验来讲,你可以这样做: 把listview放置在LinearLayout中,<LinearLayout中只存在一个listview>; 我推断是,当你通过动态测量加载的时候,ta需要一个独立的空间。

如此下来,基本上就解决了,放在ScrollView中时候listview滑动卡顿,显示不完全的现象。



0 0
原创粉丝点击