ScrollView是帶有滾動事件的控件,與listView和GridView以及Viewpager嵌套使用時經(jīng)常會出現(xiàn)很多問題弧满。例如listView和GridView只能在ScrollView顯示一行等婆跑。所以Google是不推薦我們?nèi)プ鯯crollView內(nèi)嵌操作的,但是有的時候庭呜,需求需要~我們不得不這么使用滑进。所以接下來我給大家講一些基礎(chǔ)的解決沖突的辦法。
1.ScrollView嵌套ListView,有2種方法解決
1.1自定義View
public class ScrollListView extends ListView {
public ScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ScrollListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
1.2動態(tài)測量Listview的高度
/**
* 動態(tài)控制listView的高度
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
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);
}
2.ScrollView嵌套GridView,有2種方法解決---與ListView類似
2.1自定義View
public class ScrollGridView extends GridView {
public ScrollGridView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ScrollGridView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
2.2動態(tài)測量Gridview的高度
/**
* 動態(tài)控制gridview的高度
*/
public static void setGridViewHeightBasedOnChildren(GridView gridView, int number) {
//獲取listview的適配器
ListAdapter listAdapter = gridView.getAdapter();
int numCollumn = number;
//item的高度
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
if (i % numCollumn == 0) {
View listItem = listAdapter.getView(i, null, gridView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight;
gridView.setLayoutParams(params);
}
3.ScrollView嵌套ViewPager,有2種方法解決
3.1自定義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);
}
}
3.2自定義viewPager
public class MyViewPager extends ViewPager {
/**
* 觸摸時按下的點
**/
PointF downP = new PointF();
/**
* 觸摸時當前的點
**/
PointF curP = new PointF();
OnSingleTouchListener onSingleTouchListener;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
// 每次進行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現(xiàn)在進行的是本控件的操作,不要對我的操作進行干擾
getParent().requestDisallowInterceptTouchEvent(true);
}
if (arg0.getAction() == MotionEvent.ACTION_MOVE) {
// 此句代碼是為了通知他的父ViewPager現(xiàn)在進行的是本控件的操作数冬,不要對我的操作進行干擾
getParent().requestDisallowInterceptTouchEvent(true);
}
if (arg0.getAction() == MotionEvent.ACTION_UP) {
// 在up時判斷是否按下和松手的坐標為一個點
// 如果是一個點节槐,將執(zhí)行點擊事件,這是我自己寫的點擊事件,而不是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();
}
}
/**
* 創(chuàng)建點擊事件接口
*/
public interface OnSingleTouchListener {
public void onSingleTouch();
}
public void setOnSingleTouchListener(
OnSingleTouchListener onSingleTouchListener) {
this.onSingleTouchListener = onSingleTouchListener;
}
}
4.若嵌套的ListView和GridView的高度超出了ScrollView铜异,那么ScrollView會自動滑到底部地来。
那么我們只需要使用一個頂部控件主動獲取焦點便能解決這個問題。解決代碼如下熙掺。
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.requestFocus();
備注:自定義ListView的詳細介紹 傳送門