CollapsingToolbarLayout doesn't recognize scroll fling

后端 未结 6 965
野趣味
野趣味 2020-12-02 07:08

I have created a simple CollapsingToolbarLayout and it works like a charm. My problem is, that if I try to use a fling scroll on the nestedscrollvie

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-02 07:43

    I know this question was asked over a year ago but this issue still doesn't seem to be resolved in the Support/Design libraries. You can star this issue so it moves farther up in the priority queue.

    That said, I tried most of the posted solutions for this, including the one by patrick-iv with no success. The only way I was able to get to work was to mimic the fling and call it programmatically if a certain set of conditions were detected in onPreNestedScroll(). In the few hours of my debugging I noticed that the onNestedFling() was never called on an upward (scroll down) fling and seemed to be consumed prematurely. I can't say with 100% certainty this will work for 100% of implementations but it works well enough for my uses so I ended up settling for this, even though it's pretty hacky and definitely not what I wanted to do.

    public class NestedScrollViewBehavior extends AppBarLayout.Behavior {
    
        // Lower value means fling action is more easily triggered
        static final int MIN_DY_DELTA = 4;
        // Lower values mean less velocity, higher means higher velocity
        static final int FLING_FACTOR = 20;
    
        int mTotalDy;
        int mPreviousDy;
        WeakReference mPreScrollChildRef;
    
        @Override
        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
                                      View target, int dx, int dy, int[] consumed) {
            super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
            // Reset the total fling delta distance if the user starts scrolling back up
            if(dy < 0) {
                mTotalDy = 0;
            }
            // Only track move distance if the movement is positive (since the bug is only present
            // in upward flings), equal to the consumed value and the move distance is greater
            // than the minimum difference value
            if(dy > 0 && consumed[1] == dy && MIN_DY_DELTA < Math.abs(mPreviousDy - dy)) {
                mPreScrollChildRef = new WeakReference<>(child);
                mTotalDy += dy * FLING_FACTOR;
            }
            mPreviousDy = dy;
        }
    
        @Override
        public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child,
                                           View directTargetChild, View target, int nestedScrollAxes) {
            // Stop any previous fling animations that may be running
            onNestedFling(parent, child, target, 0, 0, false);
            return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
        }
    
        @Override
        public void onStopNestedScroll(CoordinatorLayout parent, AppBarLayout abl, View target) {
            if(mTotalDy > 0 && mPreScrollChildRef != null && mPreScrollChildRef.get() != null) {
                // Programmatically trigger fling if all conditions are met
                onNestedFling(parent, mPreScrollChildRef.get(), target, 0, mTotalDy, false);
                mTotalDy = 0;
                mPreviousDy = 0;
                mPreScrollChildRef = null;
            }
            super.onStopNestedScroll(parent, abl, target);
        }
    }
    

    And apply it to the AppBar

    AppBarLayout scrollView = (AppBarLayout)findViewById(R.id.appbar);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams)scrollView.getLayoutParams();
    params.setBehavior(new NestedScrollViewBehavior());
    

    CheeseSquare demo: Before After

提交回复
热议问题