在Android开发中,有时根据需要,会在ScrollView中添加GridView,这问题也纠结了好一会,网上查的也对不上,如:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:descendantFocusability="afterDescendants"
android:id="@+id/scrollView">
<LinearLayout
android:id="@+id/pictrue_layout"
android:orientation="vertical"
android:gravity="center_horizontal"
android:descendantFocusability="afterDescendants"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</GridView>
</LinearLayout>
</ScrollView>
但是在运行以后,发现GridView不能正常滑动,也就是不能根据手势进行滑动了,导致这个问题的原因,在android开发中,程序运行以后;在接收到事件,那么Activity会把接收到的事件优先分发到最上层的View中,在上面的代码中,分发的顺序就是ScollView,如果ScollView没有接收,那么下一个分发的是LinearLayout,只有当上层的所有View都不接收事件时,最下层的View才能接收到事件。上面的GridView不能接收就是因为事件被ScrollView接收了。
解决的办法是让上面的所有的View将事件优先分发到最下层的View,由于上面的LinearLayout不处理事件,所以我们只要将ScrollView的事件优先分发到GridView即可,处理方法就是重写ScrollView里面的部分事件处理方法,方法说明如下:
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
由此我们只需要重写onInterceptTouchEvent(MotionEvent ev)方法即可,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,如果子View返回false,那么在递归返回到最上层的View自行处理,最后会丢弃改事件。同时在创建GridView的时候,让起其能直接获得焦点效果会好点。
解决代码是:
<com.x.BaseScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:descendantFocusability="afterDescendants"
android:id="@+id/scrollView">
<LinearLayout
android:id="@+id/pictrue_layout"
android:orientation="vertical"
android:gravity="center_horizontal"
android:descendantFocusability="afterDescendants"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true">
</GridView>
</LinearLayout>
</com.x.BaseScrollView>
重写ScrollView:
/**
* Created by lingo on 14-12-1.
*/
public class BaseScrollView extends ScrollView{
public BaseScrollView(Context context) {
super(context);
}
public BaseScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
这样GridView就能在ScrollView里面进行滑动了,当然了如果在GridView处于全屏状态下,那么ScrollView就永远接收不到滑动事件,所以根据具体的情况处理。