Android 解决ScrollView嵌入ListView | GridView | ScrollView显示问题

一、ScrollView中嵌套ListView

ScrollView和ListView都是滚动结构,很明显如果在ScrollView中加入ListView,可以预见性的知道,肯定会有显示/滚动的问题,接下来就分享我在网上找到的方法(有2种方法);

M1、手动设置(计算)ListView的高度

/**
 * 动态设置ListView的高度
 * @param listView
 */
public static void setListViewHeightBasedOnChildren(ListView listView) { 
    if(listView == null) return;

    ListAdapter listAdapter = listView.getAdapter(); 
    if (listAdapter == null) { 
        return; 
    } 

    int totalHeight = 0; 
    for (int i = 0; i < listAdapter.getCount(); i++) { 
        View listItem = listAdapter.getView(i, null, listView); 
        listItem.measure(0, 0); 
        totalHeight += listItem.getMeasuredHeight(); 
    } 

    ViewGroup.LayoutParams params = listView.getLayoutParams(); 
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); 
    listView.setLayoutParams(params); 
}

上面这个方法很显然,就是设定ListView的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。
但是使用这个方法有个细节需要注意:Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的。

M2、自定义ListView,适应嵌入ScrollView中

public class ListViewForScrollView extends ListView {
    public ListViewForScrollView(Context context) {
        super(context);
    }

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

    public ListViewForScrollView(Context context, AttributeSet attrs,
        int defStyle) {
        super(context, attrs, defStyle);
    }
        
    @Override
    /**
     * 重写该方法,达到使ListView适应ScrollView的效果
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

其实,这个方法也就是重写onMeasure方法,重新计算ListView的高度,不过比第一个方法更加简单简洁;
同样,使用这个方法时,需要注意一点,默认scrollview会滚动到ListView的第一项,此时只需要让scrollview滚动到最顶端即可:

scrollview.smoothScrollTo(0, 0);

 

二、ScrollView中嵌套GridView
参考ScrollView中嵌套ListView的第二个实现方法,不过有一占小的区别;参见如下代码:

public class GridViewForScrollView extends GridView {   
private boolean haveScrollbar = true;
public GridViewForScrollView(Context context) { super(context); } public GridViewForScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public GridViewForScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 设置是否有ScrollBar,当要在ScollView中显示时,应当设置为false。 默认为 true * * @param haveScrollbars */ public void setHaveScrollbar(boolean haveScrollbar) { this.haveScrollbar = haveScrollbar; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (haveScrollbars == false) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }

 

三、ScrollView嵌套ScrollView

        parent.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                parent.requestDisallowInterceptTouchEvent(false);
                return false;
            }
        });
        child.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // 禁止parent view响应child view的触摸事件
                child.requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });

这个方法的核心在于:当触摸事件发生在child身上时,禁止parent view响应child view的触摸事件;

posted @ 2014-04-28 14:58  Livingstone  阅读(827)  评论(0编辑  收藏  举报