当我们向上和向下滚动recyclerView

时间:2017-07-12 10:09:38

标签: android

我想在向下滚动时隐藏视图组,并在recyclerview向上滚动时显示视图。

这是我的代码,其中rvSearchItemsRecyclerviewrlSearchRelative Layout,我想要隐藏和显示:

rvSearchItems.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if (dy >= 0) {
            if (rlSearch.getVisibility() != View.GONE)
                rlSearch.setVisibility(View.GONE);
        } else if(dy<-5) {
            if (rlSearch.getVisibility() != View.VISIBLE)
                rlSearch.setVisibility(View.VISIBLE);
        }
    }
});

这里的主要问题是当我们快速滚动时它工作正常。如果我们慢慢滚动它会多次晃动。

2 个答案:

答案 0 :(得分:2)

我利用coordinateLayout来实现此行为

而不是LinerLayout我希望在CardView滚动时显示/隐藏recyclerView(您可以在案例中使用任何ViewGroup

基本上,这些答案是使用FAB中描述的AppBarLayoutimport android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.ViewCompat; import android.support.v7.widget.CardView; import android.util.AttributeSet; import android.view.View; import java.util.List; public class CardViewAwareScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior { int mAnimState = ANIM_STATE_NONE; static final int ANIM_STATE_NONE = 0; static final int ANIM_STATE_HIDING = 1; static final int ANIM_STATE_SHOWING = 2; static final int SHOW_HIDE_ANIM_DURATION = 200; public CardViewAwareScrollingViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return super.layoutDependsOn(parent, child, dependency) || dependency instanceof CardView; } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final View child, final View directTargetChild, final View target, final int nestedScrollAxes) { // Ensure we react to vertical scrolling return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final View child, final View target, final int dxConsumed, final int dyConsumed, final int dxUnconsumed, final int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0) { // User scrolled down -> hide the CardView List<View> dependencies = coordinatorLayout.getDependencies(child); for (View view : dependencies) { if (view instanceof CardView) { hide( ((CardView) view)); } } } else if (dyConsumed < 0) { // User scrolled up -> show the CardView List<View> dependencies = coordinatorLayout.getDependencies(child); for (View view : dependencies) { if (view instanceof CardView) { show((CardView) view); } } } } void show(final View mView) { if (isOrWillBeShown(mView)) { // We either are or will soon be visible, skip the call return; } mView.animate().cancel(); if (shouldAnimateVisibilityChange(mView)) { mAnimState = ANIM_STATE_SHOWING; if (mView.getVisibility() != View.VISIBLE) { // If the view isn't visible currently, we'll animate it from a single pixel mView.setAlpha(0f); mView.setScaleY(0f); mView.setScaleX(0f); } mView.animate() .scaleX(1f) .scaleY(1f) .alpha(1f) .setDuration(SHOW_HIDE_ANIM_DURATION) // .setInterpolator(AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { // mView.internalSetVisibility(View.VISIBLE, false); mView.setVisibility(View.VISIBLE); } @Override public void onAnimationEnd(Animator animation) { mAnimState = ANIM_STATE_NONE; } }); } else { // mView.internalSetVisibility(View.VISIBLE, fromUser); mView.setVisibility(View.VISIBLE); mView.setAlpha(1f); mView.setScaleY(1f); mView.setScaleX(1f); } } void hide(final View mView) { if (isOrWillBeHidden(mView)) { // We either are or will soon be hidden, skip the call return; } mView.animate().cancel(); if (shouldAnimateVisibilityChange(mView)) { mAnimState = ANIM_STATE_HIDING; mView.animate() .scaleX(0f) .scaleY(0f) .alpha(0f) .setDuration(SHOW_HIDE_ANIM_DURATION) // .setInterpolator(AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR) .setListener(new AnimatorListenerAdapter() { private boolean mCancelled; @Override public void onAnimationStart(Animator animation) { // mView.internalSetVisibility(View.VISIBLE, fromUser); mView.setVisibility(View.VISIBLE); mCancelled = false; } @Override public void onAnimationCancel(Animator animation) { mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { mAnimState = ANIM_STATE_NONE; if (!mCancelled) { // mView.internalSetVisibility(fromUser ? View.GONE : View.INVISIBLE, // fromUser); mView.setVisibility(View.GONE); // if (listener != null) { // listener.onHidden(); // } } } }); } else { // If the view isn't laid out, or we're in the editor, don't run the animation // mView.internalSetVisibility(true ? View.GONE : View.INVISIBLE, fromUser); mView.setOverScrollMode(View.GONE); // if (listener != null) { // listener.onHidden(); // } } } boolean isOrWillBeShown(View mView) { if (mView.getVisibility() != View.VISIBLE) { // If we not currently visible, return true if we're animating to be shown return mAnimState == ANIM_STATE_SHOWING; } else { // Otherwise if we're visible, return true if we're not animating to be hidden return mAnimState != ANIM_STATE_HIDING; } } private boolean shouldAnimateVisibilityChange(View mView) { return ViewCompat.isLaidOut(mView) && !mView.isInEditMode(); } boolean isOrWillBeHidden(View mView) { if (mView.getVisibility() == View.VISIBLE) { // If we currently visible, return true if we're animating to be hidden return mAnimState == ANIM_STATE_HIDING; } else { // Otherwise if we're not visible, return true if we're not animating to be shown return mAnimState != ANIM_STATE_SHOWING; } } } 行为Iin Lake来实现的。{3}}

CardViewAwareScrollingViewBehavior :: *

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.widget.CardView;
import android.util.AttributeSet;

@CoordinatorLayout.DefaultBehavior(CardViewAwareScrollingViewBehavior.class)
public class CustomerCardView extends CardView {

    public CustomerCardView(Context context) {
        super(context);
    }

    public CustomerCardView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomerCardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


}

使用CardViewAwareScrollingViewBehavior :: *

的CustomerCardView
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:titleTextColor="@android:color/white">
        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

</android.support.design.widget.CoordinatorLayout>

并在xml中使用此customCardView,如下所示

<强> main.xml中

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="prathap.recyclerviewsample.adapters.UI.CardViewAwareScrollingViewBehavior"
    tools:context="prathap.recyclerviewsample.MainActivity"
    tools:showIn="@layout/acitivity_main">

<!--this is out custom Cardview with custom behaviour -->

    <prathap.recyclerviewsample.CustomViews.CustomerCardView
        android:id="@+id/card_"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher"/>

    </prathap.recyclerviewsample.CustomViews.CustomerCardView>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="prathap.recyclerviewsample.adapters.UI.CardViewAwareScrollingViewBehavior"
        />
</android.support.design.widget.CoordinatorLayout>

content_main.xml ,它包含在 main.xml

Options -MultiViews
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule     ^page/([A-Za-z0-9-_\-]+)/?$    page.php?opt=$1    [L]

有了这个,我们在recyclelerView向上滚动时显示CardView,并在recycleView向下滚动时显示。

这是我的样本截屏视频

FAB Behavior

答案 1 :(得分:1)

这是我为 Kotlin 扩展 RecyclerView 类的代码。只需将其添加到您的项目中并在 Fragment 或 Activity 中使用,如下所示:

myRecyclerView.addOnScrollHiddenView(myAnyHiddenView, resources.dpToPx(myValuedp))

........

 fun RecyclerView.addOnScrollHiddenView(
    hiddenView: View,
    translationX: Float = 0F,
    translationY: Float = 0F,
    duration: Long = 200L
) {
    var isViewShown = true
    this.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            when{
                dy> 0 && isViewShown -> {
                    isViewShown = false
                    hiddenView.animate()
                        .translationX(translationX)
                        .translationY(translationY)
                        .duration = duration
                }
                dy < 0 && !isViewShown ->{
                    isViewShown = true
                    hiddenView.animate()
                        .translationX(0f)
                        .translationY(0f)
                        .duration = duration
                }
            }
        }
    })
}