Google是不推荐在ScrollView 中放入一个可滚动的菜单的,比如放置一个ListView、GridView、ViewPager这些控件的,尽量不要让两者嵌套,但有时候还是有这个需求,先不管它合不合理。如果直接在ScrollView中嵌套只会出现一行,然后在其中滚动,这样不是很好,下面是我的整理,希望对大家有帮助,我也是从网上摘抄的,当然加入了一些我自己的东西。
一、在ScrollView中嵌套ListView,有两张方法
第一种是自定义View,继承ListView代码如下:
- 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);
- }
- }
- 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
- 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
- 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);
- }
- }
- 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;
- }
- }
- view.setFocusable(true);
- view.setFocusableInTouchMode(true);
- view.requestFocus();