【问题标题】:HideBottomViewOnScrollBehavior not working on recyclerview item expand/collapseHideBottomViewOnScrollBehavior 不适用于 recyclerview 项目展开/折叠
【发布时间】:2020-11-13 06:48:20
【问题描述】:

我试图在向下滚动时隐藏文本视图并在向上滚动时显示,如果我有一个像 10 或 15 这样的项目,它可以正常工作,但如果我有更少的项目,它就不能正常工作

recyclerview 中,我有展开/折叠功能,所以有时不一样

textview 有时不隐藏/不可见我不明白我将此行添加到我想在滚动时隐藏/显示的视图中

app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"

XML

<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/lnMain"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/bg"
        tools:context=".tab.history.view.HistoryFragment">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/mAppBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:elevation="0dp">

            <RelativeLayout
                android:id="@+id/lnActionBar"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                android:background="@color/colorPrimary">

                <TextView
                    android:id="@+id/tvtitle"
                    style="@style/fontMedium"
                    android:layout_width="wrap_content"
                    android:layout_height="?android:attr/actionBarSize"
                    android:layout_centerHorizontal="true"
                    android:gravity="center_vertical"
                    android:text="@string/beacon"
                    android:textColor="@color/white"
                    android:textSize="@dimen/header_font_size" />

            </RelativeLayout>

        </com.google.android.material.appbar.AppBarLayout>

       
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvBeacon"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:overScrollMode="never"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:paddingBottom="@dimen/_40sdp"
        android:scrollbars="none"
        android:visibility="visible"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        tools:itemCount="10"
        tools:listitem="@layout/raw_beacon" />

<TextView
            android:id="@+id/btnBack"
            style="@style/fontBold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="@dimen/_10sdp"
            android:layout_marginBottom="@dimen/_20sdp"
            android:background="@drawable/background_button_yellow_20dp"
            android:contentDescription="@string/back_button"
            android:drawableStart="@drawable/ic_back"
            android:layout_gravity="bottom|center_horizontal"
            android:drawablePadding="@dimen/_5sdp"
            android:gravity="center"
            android:padding="@dimen/_10sdp"
            android:text="@string/back_to_search"
            android:textColor="@color/white"
            android:textSize="@dimen/button_font_size"
            android:visibility="@{!isScanning ? View.VISIBLE: View.GONE}"
            app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

这是我到目前为止所做的,但不是每次都有效

注意:- 请不要我有一个 recyclerview 项目,它会在点击时展开,因此滚动和文本视图必须按照该项目行事

任何帮助都将受到高度评价

【问题讨论】:

    标签: android android-recyclerview scrollview onscrollchanged


    【解决方案1】:

    我不知道为什么HideBottomViewOnScrollBehavior 不适合你

    app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
    

    可能是因为你有一个展开/折叠功能,因为你只有在屏幕上只有 recyclerview,所以你也可以通过添加自定义 ScrollListener 来执行此任务

    MyRecyclerScroll 类

    public abstract class MyRecyclerScroll extends RecyclerView.OnScrollListener {
        private static final float HIDE_THRESHOLD = 100;
        private static final float SHOW_THRESHOLD = 50;
    
        int scrollDist = 0;
        private boolean isVisible = true;
    
        //    We dont use this method because its action is called per pixel value change
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
    
            //  Check scrolled distance against the minimum
            if (isVisible && scrollDist > HIDE_THRESHOLD) {
                //  Hide fab & reset scrollDist
                hide();
                scrollDist = 0;
                isVisible = false;
            }
            //  -MINIMUM because scrolling up gives - dy values
            else if (!isVisible && scrollDist < -SHOW_THRESHOLD) {
                //  Show fab & reset scrollDist
                show();
    
                scrollDist = 0;
                isVisible = true;
            }
    
            //  Whether we scroll up or down, calculate scroll distance
            if ((isVisible && dy > 0) || (!isVisible && dy < 0)) {
                scrollDist += dy;
            }
    
        }
    
    
        public abstract void show();
    
        public abstract void hide();
    }
    

    活动/片段

    binding.rvBeacon.addOnScrollListener(object : MyRecyclerScroll() {
                override fun show() {
                    binding.btnBack.animate().translationY(0f).setInterpolator(DecelerateInterpolator(2f)).start()
                }
    
                override fun hide() {
                    binding.btnBack.animate().translationY(binding.btnBack.getHeight() + 60f)
                        .setInterpolator(AccelerateInterpolator(2f)).start()
                }
            })
    

    您可以根据需要更改动画、延迟和边距

    更多详情请参考blog

    注意:如果你的recyclerview在scrollview里面,它不会起作用

    【讨论】:

    • 记住它只适用于recyclerview,如果你的recyclerview在scrollview里面就不行
    【解决方案2】:

    如何自定义行为?

    例如。

    public class QuickReturnFooterBehavior extends CoordinatorLayout.Behavior<View> {
    
        private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
        private static final long ANIMATION_DURATION = 200;
    
        private int dyDirectionSum;
        private boolean isShowing;
        private boolean isHiding;
        private boolean isNeedOption = true;
    
        public boolean isNeedOption() {
            return isNeedOption;
        }
    
        public void setNeedOption(boolean needOption) {
            isNeedOption = needOption;
        }
    
        public QuickReturnFooterBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
            return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
        }
    
        @Override
        public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
            // scroll chhange up and down
            if (isNeedOption) {
                showView(child);
            } else {
                if (dy > 0 && dyDirectionSum < 0
                        || dy < 0 && dyDirectionSum > 0) {
                    child.animate().cancel();
                    dyDirectionSum = 0;
                }
    
                dyDirectionSum += dy;
    
                if (dyDirectionSum > child.getHeight()) {
                    hideView(child);
                } else if (dyDirectionSum < -child.getHeight()) {
                    showView(child);
                }
    
            }
    
        }
    
        private void hideView(final View view) {
            if (isHiding || view.getVisibility() != View.VISIBLE) {
                return;
            }
    
            ViewPropertyAnimator animator = view.animate()
                    .translationY(view.getHeight())
                    .setInterpolator(INTERPOLATOR)
                    .setDuration(ANIMATION_DURATION);
    
            animator.setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animator) {
                    isHiding = true;
                }
    
                @Override
                public void onAnimationEnd(Animator animator) {
                    isHiding = false;
                    view.setVisibility(View.INVISIBLE);
                }
    
                @Override
                public void onAnimationCancel(Animator animator) {
                    // show when cancle
                    isHiding = false;
                    showView(view);
                }
    
                @Override
                public void onAnimationRepeat(Animator animator) {
                    // no-op
                }
            });
    
            animator.start();
        }
    
        private void showView(final View view) {
            if (isShowing || view.getVisibility() == View.VISIBLE) {
                return;
            }
            ViewPropertyAnimator animator = view.animate()
                    .translationY(0)
                    .setInterpolator(INTERPOLATOR)
                    .setDuration(ANIMATION_DURATION);
    
            animator.setListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animator) {
                    isShowing = true;
                    view.setVisibility(View.VISIBLE);
                }
    
                @Override
                public void onAnimationEnd(Animator animator) {
                    isShowing = false;
                }
    
                @Override
                public void onAnimationCancel(Animator animator) {
                    // show when cancle
                    isShowing = false;
                    hideView(view);
                }
    
                @Override
                public void onAnimationRepeat(Animator animator) {
                    // no-op
                }
            });
    
            animator.start();
        }
    }
    

    更新:检查可以滚动行为

    child.canScrollVertically(1)  // "Top of list"
    child.canScrollVertically(-1)  // "End of list"
    

    **更新:添加 setter 和 getter **

    private boolean isNeedOption = true;
    

    【讨论】:

    • 请在我的片段/活动中添加如何使用它
    • app:layout_behavior="your.package.here.HideBottomViewOnScrollBehavior" 像这样
    • 兄弟这是工作,但如果我的所有 recyclerview 项目折叠,它还会在上下滑动时显示/隐藏按钮,如果所有 recyclerview 项目都合适,我不会隐藏/显示在屏幕中
    • 您是否希望在 recyclerview 折叠时滚动始终显示,并且仅在 recyclerview 使用时才隐藏?
    • 是的,所以如果您在需要时控制它(RecyclerView 滚动监听器),它将起作用
    猜你喜欢
    • 2015-01-28
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 2019-02-06
    相关资源
    最近更新 更多