Horizo​​ntalScrollView中的捕捉效果

时间:2018-03-28 05:55:36

标签: java android performance horizontal-scrolling horizontalscrollview

我想在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
  5. 我的用例: 我有一个HorizontalScrollView附加到Recyclerview(垂直)的适配器,所以snapHelper可以垂直完成,但我不知道如何使它成为水平。

1 个答案:

答案 0 :(得分:2)

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来捕捉fling操作并在那里做同样的事情。