您的位置:首页 > 其它

ScrollView嵌套ListView,GridView,ViewPager,以及这些控件自动滚动到底部问题的解决

2016-06-06 16:20 513 查看
一、在ScrollView中嵌套ListView,有两张方法

第一种是自定义View,继承ListView代码如下:

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import android.content.Context;  

import android.util.AttributeSet;  

import android.widget.ListView;  

  

public class MyListView extends ListView {  

  

    public MyListView(Context context) {  

        super(context);  

    }  

    public MyListView(Context context, AttributeSet attrs, int defStyle) {  

        super(context, attrs, defStyle);  

    }  

    public MyListView(Context context, AttributeSet attrs) {  

        super(context, attrs);  

    }  

    @Override  

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  

         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,    

                 MeasureSpec.AT_MOST);      

        super.onMeasure(widthMeasureSpec, expandSpec);  

    }  

  

}  

第二种

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import android.view.View;  

import android.view.ViewGroup;  

import android.widget.ListAdapter;  

import android.widget.ListView;  

  

public class Utility {  

    public static void setListViewHeightBasedOnChildren(ListView listView) {  

        ListAdapter listAdapter = listView.getAdapter();  

        if (listAdapter == null) {  

            // pre-condition  

            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);  

    }  

}  

第二种在setAdapter之后调用Utility.setListViewHeightBasedOnChildren(listview)这个方法,有些资料说只能item的根布局要LinearLayout,但是我的跟布局为RelativeLayout也可以的。

这两种都可以,但是在有些情况下中能用第一种,比如你显示ListView是一个ListFragment就只能用第二种方法了。

二、在ScrollView中嵌套GridView

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import android.content.Context;  

import android.util.AttributeSet;  

import android.widget.GridView;  

  

public class NoScrollGridView extends GridView {    

        

    public NoScrollGridView(Context context) {    

        super(context);    

            

    }    

    

    public NoScrollGridView(Context context, AttributeSet attrs) {    

        super(context, attrs);    

    }    

        

    @Override    

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    

        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);    

        super.onMeasure(widthMeasureSpec, expandSpec);    

    }    

    

}    

二、在ScrollView中嵌套ViewPager,也有两张方法

第一种自定义ScrollView

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import android.content.Context;  

import android.util.AttributeSet;  

import android.view.MotionEvent;  

import android.widget.ScrollView;  

  

/** 

 * 能够兼容ViewPager的ScrollView 

 *  

 * @Description: 解决了ViewPager在ScrollView中的滑动反弹问题 

 */  

public class ScrollViewExtend extends ScrollView {  

    // 滑动距离及坐标  

    private float xDistance, yDistance, xLast, yLast;  

  

    public ScrollViewExtend(Context context, AttributeSet attrs) {  

        super(context, attrs);  

    }  

  

    @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);  

    }  

}  

第二种是自定义ViewPager

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import android.content.Context;  

import android.graphics.PointF;  

import android.support.v4.view.ViewPager;  

import android.util.AttributeSet;  

import android.view.MotionEvent;  

  

/** 

 * 嵌套在ScrollView中的ViewPager,解决冲突 

 * @author m3 

 * 

 */  

public class ChildViewPager extends ViewPager {  

    /** 触摸时按下的点 **/  

    PointF downP = new PointF();  

    /** 触摸时当前的点 **/  

    PointF curP = new PointF();  

    OnSingleTouchListener onSingleTouchListener;  

  

    public ChildViewPager(Context context, AttributeSet attrs) {  

        super(context, attrs);  

        // TODO Auto-generated constructor stub  

    }  

  

    public ChildViewPager(Context context) {  

        super(context);  

        // TODO Auto-generated constructor stub  

    }  

  

    @Override  

    public boolean onInterceptTouchEvent(MotionEvent arg0) {  

        // TODO Auto-generated method stub  

        // 当拦截触摸事件到达此位置的时候,返回true,  

        // 说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent  

        return true;  

    }  

  

    @Override  

    public boolean onTouchEvent(MotionEvent arg0) {  

        // TODO Auto-generated method stub  

        // 每次进行onTouch事件都记录当前的按下的坐标  

        curP.x = arg0.getX();  

        curP.y = arg0.getY();  

  

        if (arg0.getAction() == MotionEvent.ACTION_DOWN) {  

            // 记录按下时候的坐标  

            // 切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变  

            downP.x = arg0.getX();  

            downP.y = arg0.getY();  

            // 此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰  

            getParent().requestDisallowInterceptTouchEvent(true);  

        }  

  

        if (arg0.getAction() == MotionEvent.ACTION_MOVE) {  

            // 此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰  

            getParent().requestDisallowInterceptTouchEvent(true);  

        }  

  

        if (arg0.getAction() == MotionEvent.ACTION_UP) {  

            // 在up时判断是否按下和松手的坐标为一个点  

            // 如果是一个点,将执行点击事件,这是我自己写的点击事件,而不是onclick  

            if (downP.x == curP.x && downP.y == curP.y) {  

                onSingleTouch();  

                return true;  

            }  

        }  

  

        return super.onTouchEvent(arg0);  

    }  

  

    /** 

     * 单击 

     */  

    public void onSingleTouch() {  

        if (onSingleTouchListener != null) {  

  

            onSingleTouchListener.onSingleTouch();  

        }  

    }  

  

    /** 

     * 创建点击事件接口 

     *  

     * @author wanpg 

     *  

     */  

    public interface OnSingleTouchListener {  

        public void onSingleTouch();  

    }  

  

    public void setOnSingleTouchListener(  

            OnSingleTouchListener onSingleTouchListener) {  

        this.onSingleTouchListener = onSingleTouchListener;  

    }  

  

}  

第二个问题在ScrollView嵌套ListView,GridView,如果这些子控件很长超出了屏幕的高度,那么ScrollView会自动滚到底部,但是我们需要默认在顶部,我们要在ListView和GridView上面的view中加入,一下代码即可解决:

[java] view plain copy 在CODE上查看代码片派生到我的代码片
adb2

view.setFocusable(true);  

view.setFocusableInTouchMode(true);  

view.requestFocus();  

这段代码在初始化的时候就让该界面的顶部的某一个控件获得焦点,滚动条自然就显示到顶部了,顺便附一下我找到答案的地方http://blog.csdn.net/studyalllife/article/details/42970975这上面写的很混乱,大家可以参考一下,大功告成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: