【问题标题】:Snapping Effect in HorizontalScrollViewHorizo​​ntalScrollView 中的对齐效果
【发布时间】:2018-09-06 16:49:32
【问题描述】:

我想在HorizontalScrollView 中实现Snapping effect,即当用户水平滚动时,最显眼的项目(项目可见> 50%)来到中心。

我尝试使用

 hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
            @Override
            public void onScrollChanged() {
                int scrollX = hsv.getScrollX(); // For HorizontalScrollView
                Log.e("scrollX",String.valueOf(scrollX));
                // DO SOMETHING WITH THE SCROLL COORDINATES
            }
        });

但即使我们不触摸屏幕,该值也不是恒定的。

这里是 logcat 的一部分:

    03-28 11:11:22.116 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.133 26639-26639/package_name E/scrollX: 792
03-28 11:11:22.133 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.151 26639-26639/package_name E/scrollX: 795
03-28 11:11:22.151 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.166 26639-26639/package_name E/scrollX: 799
03-28 11:11:22.166 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.183 26639-26639/package_name E/scrollX: 801
03-28 11:11:22.183 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.199 26639-26639/package_name E/scrollX: 803
03-28 11:11:22.199 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.216 26639-26639/package_name E/scrollX: 804
03-28 11:11:22.216 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.233 26639-26639/package_name E/scrollX: 805
03-28 11:11:22.233 26639-26639/package_name E/scrollX: 0
03-28 11:11:22.249 26639-26639/package_name E/scrollX: 806
03-28 11:11:22.249 26639-26639/package_name E/scrollX: 0

现在我已经尝试了这些解决方案,I am not getting the pointI don't know to do it。请帮忙。

  1. HorizontalScrollView within ScrollView Touch Handling
  2. HorizontalScrollView with snapping effect
  3. Creating Custom Horizontal Scroll View With Snap or paging
  4. Creating a “Snapping” Horizontal Scroll View

我的用例: 我有一个 HorizontalScrollView 连接到 Recyclerview(Vertical) 的适配器,所以 snapHelper 可以垂直完成,但我不知道如何使它水平。

【问题讨论】:

    标签: java android performance horizontal-scrolling horizontalscrollview


    【解决方案1】:

    Here 是用于捕捉项目的自定义水平滚动视图的完整代码。

        public class HomeFeatureLayout extends HorizontalScrollView {
        private static final int SWIPE_MIN_DISTANCE = 5;
        private static final int SWIPE_THRESHOLD_VELOCITY = 300;
    
        private ArrayList mItems = null;
        private GestureDetector mGestureDetector;
        private int mActiveFeature = 0;
    
        public HomeFeatureLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public HomeFeatureLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public HomeFeatureLayout(Context context) {
            super(context);
        }
    
        public void setFeatureItems(ArrayList items){
            LinearLayout internalWrapper = new LinearLayout(getContext());
            internalWrapper.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
            internalWrapper.setOrientation(LinearLayout.HORIZONTAL);
            addView(internalWrapper);
            this.mItems = items;
            for(int i = 0; i< items.size();i++){
                LinearLayout featureLayout = (LinearLayout) View.inflate(this.getContext(),R.layout.homefeature,null);
                //...
              //Create the view for each screen in the scroll view
                //...
                internalWrapper.addView(featureLayout);
            }
            setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    //If the user swipes
                    if (mGestureDetector.onTouchEvent(event)) {
                        return true;
                    }
                    else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL ){
                        int scrollX = getScrollX();
                        int featureWidth = v.getMeasuredWidth();
                        mActiveFeature = ((scrollX + (featureWidth/2))/featureWidth);
                        int scrollTo = mActiveFeature*featureWidth;
                        smoothScrollTo(scrollTo, 0);
                        return true;
                    }
                    else{
                        return false;
                    }
                }
            });
            mGestureDetector = new GestureDetector(new MyGestureDetector());
        }
            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) {
                        int featureWidth = getMeasuredWidth();
                        mActiveFeature = (mActiveFeature < (mItems.size() - 1))? mActiveFeature + 1:mItems.size() -1;
                        smoothScrollTo(mActiveFeature*featureWidth, 0);
                        return true;
                    }
                    //left to right
                    else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                        int featureWidth = getMeasuredWidth();
                        mActiveFeature = (mActiveFeature > 0)? mActiveFeature - 1:0;
                        smoothScrollTo(mActiveFeature*featureWidth, 0);
                        return true;
                    }
                } catch (Exception e) {
                        Log.e("Fling", "There was an error processing the Fling event:" + e.getMessage());
                }
                return false;
            }
        }
    }
    

    此示例确实以编程方式添加视图并将它们称为Features。但是您可以简单地更改该行为并使用getChildrenCount() 而不是mItems.size() 等等。

    重要的部分是GestureDetectorTouchListener。在 TouchListener 中,您可以侦听 ACTION_UP,这是用户手指移开时(如滚动后),您可以根据滚动量及其位置计算出哪个视图是 active。您还可以添加一个 GestureDetector 来捕获投掷操作并在那里执行相同的操作。

    【讨论】:

    • 我应该附加哪个布局?
    • 您需要按照我所说的更改该部分,除非您在滚动视图中的所有视图都与示例相同。在示例中,//Create the view for each screen in the scroll view 部分是您为滚动视图初始化每个视图的地方,但这可能不是您的情况,因为您的滚动视图中可能已经有视图。在构造函数中添加setOnTouchListener 并使用我上面提出的建议使其与您的代码一起使用。
    • 嘿,我仍然无法弄清楚将其附加到我的布局的部分。你能帮忙吗?
    猜你喜欢
    • 2012-03-17
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2021-07-02
    相关资源
    最近更新 更多