ScrollView触摸处理中的HorizontalScrollView

乔尔

我有一个ScrollView围绕着我的整个布局,因此整个屏幕都是可滚动的。我在此ScrollView中拥有的第一个元素是Horizo​​ntalScrollView块,该块具有可以水平滚动的功能。我已在水平滚动视图中添加了ontouchlistener来处理触摸事件,并强制视图“捕捉”到ACTION_UP事件上最接近的图像。

因此,我想要的效果就像普通的android主屏幕,您可以在其中滚动到另一屏幕,并且在松开手指时可以捕捉到一个屏幕。

除一个问题外,所有其他方法都很好用:我需要几乎完全水平地从左向右滑动才能使ACTION_UP注册。如果我至少在垂直方向上滑动(我想很多人在左右滑动时会在手机上这样做),那么我会收到ACTION_CANCEL而不是ACTION_UP。我的理论是,这是因为horizo​​ntalscrollview在scrollview内,并且scrollview劫持了垂直触摸以允许垂直滚动。

如何仅从水平滚动视图中禁用滚动视图的触摸事件,但仍允许在滚动视图中的其他位置进行正常的垂直滚动?

这是我的代码示例:

   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);
            title.setTag(items.get(i).GetLinkURL());
            TextView date = (TextView) featureLayout.findViewById(R.id.featuredate);
            header.setText("FEATURED");
            Image cachedImage = new Image(this.getContext(), items.get(i).GetImageURL());
            image.setImageDrawable(cachedImage.getImage());
            title.setText(items.get(i).GetTitle());
            date.setText(items.get(i).GetDate());
            internalWrapper.addView(featureLayout);
        }
        gestureDetector = new GestureDetector(new MyGestureDetector());
        setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (gestureDetector.onTouchEvent(event)) {
                    return true;
                }
                else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL ){
                    int scrollX = getScrollX();
                    int featureWidth = getMeasuredWidth();
                    activeFeature = ((scrollX + (featureWidth/2))/featureWidth);
                    int scrollTo = activeFeature*featureWidth;
                    smoothScrollTo(scrollTo, 0);
                    return true;
                }
                else{
                    return false;
                }
            }
        });
    }

    class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            try {
                //right to left 
                if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    activeFeature = (activeFeature < (items.size() - 1))? activeFeature + 1:items.size() -1;
                    smoothScrollTo(activeFeature*getMeasuredWidth(), 0);
                    return true;
                }  
                //left to right
                else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    activeFeature = (activeFeature > 0)? activeFeature - 1:0;
                    smoothScrollTo(activeFeature*getMeasuredWidth(), 0);
                    return true;
                }
            } catch (Exception e) {
                // nothing
            }
            return false;
        }
    }
}
乔尔

更新:我想通了。在我的ScrollView上,我需要重写onInterceptTouchEvent方法以仅在Y动作大于X动作时拦截触摸事件。似乎ScrollView的默认行为是在有任何Y运动时都拦截触摸事件。因此,有了此修复程序,如果用户有意在Y方向上滚动并且在这种情况下将ACTION_CANCEL传递给子级,则ScrollView将仅拦截该事件。

这是我的Scroll View类的代码,其中包含Horizo​​ntalScrollView:

public class CustomScrollView extends ScrollView {
    private GestureDetector mGestureDetector;

    public CustomScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(context, new YScrollDetector());
        setFadingEdgeLength(0);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev);
    }

    // Return false if we're scrolling in the x direction  
    class YScrollDetector extends SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {             
            return Math.abs(distanceY) > Math.abs(distanceX);
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

HorizontalScrollView中的ListView和ScrollView中的HorizontalScrollView

在UiCollectionView中处理触摸?

Android:ScrollView内的HorizontalScrollView

处理UICollectionViewCell中的scrollview大小

试图了解Android中触摸处理的逻辑

触摸android.gesture.GestureOverlayView时阻止ScrollView中的滚动

以编程方式将自定义视图放入ScrollView(或HorizontalScrollView)中(无滚动)

滚动时具有 HorizontalScrollview 的 Scrollview 滞后

HorizontalScrollView中的捕捉效果

ViewPager中HorizontalScrollView的操作

在 Kotlin 中同时处理按钮单击和按钮触摸

处理Recyclerview中项目的触摸事件-Android

在UILabel中处理触摸事件并将其连接到IBAction

在Android中的多个视图上同时进行触摸事件处理

在android中处理多点触摸,例如Pinch In和Pinch Out

Objective-C中基于触摸的图像处理

可可触摸框架中的Pod处理-设备出现错误

如何在Xamarin中处理FlexLayout的触摸事件

滚动行为:ViewPager 中的 HorizontalScrollView

HorizontalScrollView中的可点击图像

HorizontalScrollView中的SortableTableView不断增长

在右侧的HorizontalScrollView中设置TextView

iOS:识别 UI scrollView 上的触摸

Swift:无法触摸scrollView上的画布视图

如何在 Jetpack Compose 的同一活动中处理多个触摸事件?

处理驻留在父视图控制器(ios)中的按钮的触摸

在SwiftUI中,有什么方法可以处理和/或区分Apple Pencil和直接触摸?

如何在Swift UIKit Map组件的SwiftUI中处理触摸手势?

如何处理blackberry10中的自定义控件的触摸事件