ScrollViewネストListView,GridView,ViewPager,およびこれらのコントロールが自動的に最後までスクロールする問題の解決


GoogleはScrollViewにスクロール可能なメニューを入れることをお勧めしません.例えば、ListView、GridView、ViewPagerなどのコントロールを置くのはお勧めしません.できるだけ両者をネストさせないでください.しかし、時にはこの需要があります.それが合理的かどうかにかかわらず.もし直接ScrollViewの中でネストするならばただ1行だけ現れて、それからその中で転がって、このようによくなくて、下は私の整理で、みんなに役に立つことを望んで、私もネット上から抜粋して、もちろんいくつか私の自分のものに参加しました.
一、ScrollViewにListViewをネストするには、2つの方法がある
1つ目は、ListViewコードを継承するカスタムViewです.
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);
	}

}

第2種
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);
	}
}

2つ目はsetAdapterの後にUtilityを呼び出す.setListViewHeightBasedOnChildren(listview)という方法では、itemのルートレイアウトしかLinearLayoutにできないという資料もありますが、私のヒールレイアウトはRelativeLayoutでもいいです.どちらでもいいですが、場合によっては1つ目を使うことができます.例えば、ListViewがListFragmentであることを表示するには、2つ目の方法しか使えません.
二、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でネストする
ViewPager、2枚の方法もあります
最初のカスタム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);
	}
}

2つ目は、カスタムViewPager
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;
	}

}

2つ目の問題は、ScrollViewにListView、GridViewをネストします.これらのサブコントロールが画面の高さを超えている場合、ScrollViewは自動的に最後までスクロールしますが、デフォルトで上部にある必要があります.ListViewとGridViewの上のviewに追加し、コードを追加すると解決します.
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.requestFocus();

このコードは初期化時にそのインタフェースの上部のコントロールに焦点を当てさせ、スクロールバーは自然に上部に表示されます.ちなみに私が答えを見つけた場所を添付します.http://blog.csdn.net/studyalllife/article/details/42970975これは混乱しているので、参考にしてください.