ScrollViewネストListView,GridView,ViewPager,およびこれらのコントロールが自動的に最後までスクロールする問題の解決
6545 ワード
GoogleはScrollViewにスクロール可能なメニューを入れることをお勧めしません.例えば、ListView、GridView、ViewPagerなどのコントロールを置くのはお勧めしません.できるだけ両者をネストさせないでください.しかし、時にはこの需要があります.それが合理的かどうかにかかわらず.もし直接ScrollViewの中でネストするならばただ1行だけ現れて、それからその中で転がって、このようによくなくて、下は私の整理で、みんなに役に立つことを望んで、私もネット上から抜粋して、もちろんいくつか私の自分のものに参加しました.
一、ScrollViewにListViewをネストするには、2つの方法がある
1つ目は、ListViewコードを継承するカスタムViewです.
第2種
2つ目はsetAdapterの後にUtilityを呼び出す.setListViewHeightBasedOnChildren(listview)という方法では、itemのルートレイアウトしかLinearLayoutにできないという資料もありますが、私のヒールレイアウトはRelativeLayoutでもいいです.どちらでもいいですが、場合によっては1つ目を使うことができます.例えば、ListViewがListFragmentであることを表示するには、2つ目の方法しか使えません.
二、ScrollViewにGridViewをネストする
二、ScrollViewでネストする
ViewPager、2枚の方法もあります
最初のカスタムScrollView
2つ目は、カスタムViewPager
2つ目の問題は、ScrollViewにListView、GridViewをネストします.これらのサブコントロールが画面の高さを超えている場合、ScrollViewは自動的に最後までスクロールしますが、デフォルトで上部にある必要があります.ListViewとGridViewの上のviewに追加し、コードを追加すると解決します.
このコードは初期化時にそのインタフェースの上部のコントロールに焦点を当てさせ、スクロールバーは自然に上部に表示されます.ちなみに私が答えを見つけた場所を添付します.http://blog.csdn.net/studyalllife/article/details/42970975これは混乱しているので、参考にしてください.
一、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これは混乱しているので、参考にしてください.