滚动视图触摸处理中的HorizontalScrollView

滚动视图触摸处理中的HorizontalScrollView

我有一个滚动视图围绕我的整个布局,使整个屏幕是可滚动的。我在这个ScrollView中拥有的第一个元素是HorizontalScrollView块,它具有可以水平滚动的功能。我在水平滚动视图中添加了一个ontouch侦听器,以处理触摸事件,并强制视图“快照”到action_up事件上最接近的图像。

所以我想要的效果就像股票Android的主屏幕,你可以从一个屏幕滚动到另一个屏幕,当你举起手指的时候它会点击到一个屏幕上。

这一切都很好,除了一个问题:我需要从左到右滑动几乎完全水平,一个action_up永远注册。如果我最不垂直地滑动(我认为很多人倾向于在手机上来回滑动),我将收到action_Cancel而不是action_up。我的理论是,这是因为水平滚动视图在滚动视图中,而滚动视图正在劫持垂直触摸以允许垂直滚动。

如何从水平滚动视图中禁用滚动视图的触摸事件,但仍然允许在滚动视图的其他地方正常垂直滚动?

下面是我的代码示例:

public class HomeFeatureLayout extends HorizontalScrollView {private ArrayList<ListItem> items = null;
private GestureDetector gestureDetector;View.OnTouchListener gestureListener;private static final int SWIPE_MIN_DISTANCE = 5;
private static final int SWIPE_THRESHOLD_VELOCITY = 300;private int activeFeature = 0;
public HomeFeatureLayout(Context context, ArrayList<ListItem> items){
    super(context);
    setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    setFadingEdgeLength(0);
    this.setHorizontalScrollBarEnabled(false);
    this.setVerticalScrollBarEnabled(false);
    LinearLayout internalWrapper = new LinearLayout(context);
    internalWrapper.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    internalWrapper.setOrientation(LinearLayout.HORIZONTAL);
    addView(internalWrapper);
    this.items = items;
    for(int i = 0; i< items.size();i++){
        LinearLayout featureLayout = (LinearLayout) View.inflate(this.getContext(),R.layout.homefeature,null);
        TextView header = (TextView) featureLayout.findViewById(R.id.featureheader);
        ImageView image = (ImageView) featureLayout.findViewById(R.id.featureimage);
        TextView title = (TextView) featureLayout.findViewById(R.id.featuretitle);
森林海
浏览 564回答 3
3回答

叮当猫咪

我想明白了。在我的ScrollView上,我需要覆盖onInterceptTouchEvent方法,以便只在Y运动大于X运动时拦截触摸事件。ScrollView的默认行为似乎是在有Y运动时拦截触摸事件。因此,通过修复,ScrollView只会在用户有意向Y方向滚动,并且在这种情况下将action_Cancel传递给子用户时,才会拦截该事件。下面是包含HorizontalScrollView的滚动视图类的代码:public&nbsp;class&nbsp;CustomScrollView&nbsp;extends&nbsp;ScrollView&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;GestureDetector&nbsp;mGestureDetector; &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;CustomScrollView(Context&nbsp;context,&nbsp;AttributeSet&nbsp;attrs)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(context,&nbsp;attrs); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mGestureDetector&nbsp;=&nbsp;new&nbsp;GestureDetector(context,&nbsp;new&nbsp;YScrollDetector()); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setFadingEdgeLength(0); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;onInterceptTouchEvent(MotionEvent&nbsp;ev)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;super.onInterceptTouchEvent(ev)&nbsp;&&&nbsp;mGestureDetector.onTouchEvent(ev); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Return&nbsp;false&nbsp;if&nbsp;we're&nbsp;scrolling&nbsp;in&nbsp;the&nbsp;x&nbsp;direction&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;YScrollDetector&nbsp;extends&nbsp;SimpleOnGestureListener&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;boolean&nbsp;onScroll(MotionEvent&nbsp;e1,&nbsp;MotionEvent&nbsp;e2,&nbsp;float&nbsp;distanceX,&nbsp;float&nbsp;distanceY)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Math.abs(distanceY)&nbsp;>&nbsp;Math.abs(distanceX); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}

慕无忌1623718

我简化了代码(不需要GestureDetector)达到同样的效果:public class VerticalScrollView extends ScrollView {     private float xDistance, yDistance, lastX, lastY;     public VerticalScrollView(Context context, AttributeSet attrs) {         super(context, attrs);     }     @Override     public boolean onInterceptTouchEvent(MotionEvent ev) {         switch (ev.getAction()) {             case MotionEvent.ACTION_DOWN:                 xDistance = yDistance = 0f;                 lastX = ev.getX();                 lastY = ev.getY();                 break;             case MotionEvent.ACTION_MOVE:                 final float curX = ev.getX();                 final float curY = ev.getY();                 xDistance += Math.abs(curX - lastX);                 yDistance += Math.abs(curY - lastY);                 lastX = curX;                 lastY = curY;                 if(xDistance > yDistance)                     return false;         }         return super.onInterceptTouchEvent(ev);     }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Android