recyclerview scroll android-recyclerview floating-action-button android-coordinatorlayout

Ocultar FloatingActionButton en scroll de RecyclerView



hide floating action button on scroll recyclerview (9)

// lv = ListView

lv.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { fab.setVisibility(view.getFirstVisiblePosition() == 0 ? View.VISIBLE : View.INVISIBLE); } });

Quiero ocultar / mostrar FloatingActionButton en el desplazamiento de RecyclerView .

XML :

<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview_eventlist" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_createevent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/fab_margin" app:layout_anchor="@id/recyclerview_eventlist" app:layout_anchorGravity="bottom|right|end" app:layout_behavior="com.eventizon.behavior.ScrollAwareFABBehavior" android:src="@drawable/ic_edit" app:backgroundTint="@color/custom_color_1" app:borderWidth="0dp" /> </android.support.design.widget.CoordinatorLayout>

DrawerLayout es el diseño principal de este diseño.

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { private static final String TAG = "ScrollAwareFABBehavior"; public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); Log.e(TAG,"ScrollAwareFABBehavior"); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { // TODO Auto-generated method stub super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); Log.e(TAG,"onNestedScroll called"); if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { Log.e(TAG,"child.hide()"); child.hide(); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { Log.e(TAG,"child.show()"); child.show(); } }

}

Usó este comportamiento de diseño para FloatingActionButton . Cuando veo logcat solo se llama al constructor. onNestedScroll() no se llama cuando onNestedScroll() la lista.


Así es como lo hice. ¡Esto funciona para mi! Si no sabe cómo implementarlo, puede ver los detalles en este enlace https://guides.codepath.com/android/floating-action-buttons

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { public ScrollAwareFABBehavior(Context context, AttributeSet attributeSet){ super(); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { child.hide(); } else if (dyConsumed < 0 && child.getVisibility() == View.GONE) { child.show(); } } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; } }


Esto debería funcionar para usted:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx,int dy){ super.onScrolled(recyclerView, dx, dy); if (dy >0) { // Scroll Down if (fab.isShown()) { fab.hide(); } } else if (dy <0) { // Scroll Up if (!fab.isShown()) { fab.show(); } } } });


He creado un RecyclerView personalizado que tiene OnUpDownScrollListener , OnLeftRightScrollListener listo:

Código:

MBRecyclerView.java

public class MBRecyclerView extends RecyclerView { private OnScrollListener wrappedUpDownScrollListener; private OnScrollListener wrappedLeftRightScrollListener; public MBRecyclerView(Context context) { super(context); init(); } public MBRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public MBRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { } // region Scrolling Listener for Up, Down, Left and Right public void setOnUpDownScrollListener(final OnUpDownScrollListener onUpDownScrollListener) { if (wrappedUpDownScrollListener == null) { wrappedUpDownScrollListener = getWrappedUpDownScrollListener(onUpDownScrollListener); addOnScrollListener(wrappedUpDownScrollListener); } } public void removeOnUpDownScrollListener() { if (wrappedUpDownScrollListener != null) { removeOnScrollListener(wrappedUpDownScrollListener); wrappedUpDownScrollListener = null; } } public void setLeftOnRightScrollListener(final OnLeftRightScrollListener onLeftRightScrollListener) { if (wrappedLeftRightScrollListener == null) { wrappedLeftRightScrollListener = getWrappedLeftRightScrollListener(onLeftRightScrollListener); addOnScrollListener(wrappedLeftRightScrollListener); } } public void removeOnLeftRightScrollListener() { if (wrappedLeftRightScrollListener != null) { removeOnScrollListener(wrappedLeftRightScrollListener); wrappedLeftRightScrollListener = null; } } private OnScrollListener getWrappedUpDownScrollListener(final OnUpDownScrollListener onUpDownScrollListener) { return new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (onUpDownScrollListener != null) { // Negative to check scrolling up, positive to check scrolling down if (!recyclerView.canScrollVertically(-1)) { onUpDownScrollListener.onScrolledToTop(); } else if (!recyclerView.canScrollVertically(1)) { onUpDownScrollListener.onScrolledToBottom(); } if (dy > 0) { onUpDownScrollListener.onScrollDown(dy); } else if (dy < 0) { onUpDownScrollListener.onScrollUp(dy); } } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (onUpDownScrollListener != null) { onUpDownScrollListener.onScrollStopped(); } } } }; } private OnScrollListener getWrappedLeftRightScrollListener(final OnLeftRightScrollListener onLeftRightScrollListener) { return new OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (onLeftRightScrollListener != null) { // Negative to check scrolling left, positive to check scrolling right if (!recyclerView.canScrollHorizontally(-1)) { onLeftRightScrollListener.onScrolledToMostLeft(); } else if (!recyclerView.canScrollVertically(1)) { onLeftRightScrollListener.onScrolledToMostRight(); } if (dy > 0) { onLeftRightScrollListener.onScrollRight(dx); } else if (dy < 0) { onLeftRightScrollListener.onScrollLeft(dx); } } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (onLeftRightScrollListener != null) { onLeftRightScrollListener.onScrollStopped(); } } } }; } public abstract class OnUpDownScrollListener { public void onScrollUp(int dy) {} public void onScrollDown(int dy) {} public void onScrolledToTop() {} public void onScrolledToBottom() {} public void onScrollStopped() {} } public abstract class OnLeftRightScrollListener { public void onScrollLeft(int dx) {} public void onScrollRight(int dx) {} public void onScrolledToMostRight() {} public void onScrolledToMostLeft() {} public void onScrollStopped() {} } // endregion }

Uso (UpDownScrollListener):

mbRecyclerView.setOnUpDownScrollListener(new MBRecyclerView.OnUpDownScrollListener() { @Override public void onScrollUp(int dy) { // show } @Override public void onScrollDown(int dy) { // hide } // aditional functions: public void onScrolledToTop() {} public void onScrolledToBottom() {} public void onScrollStopped() {} });

De forma similar, puede manejar el desplazamiento hacia la izquierda y hacia la derecha configurando

setOnLeftRightScrollListener

Espero que pueda ayudar a alguien :)


La solución está en: FAB oculta pero no muestra

El problema es que Android 25.0.x + establece la vista en GONE y es por eso que el oyente no informa los cambios.


La solución más fácil:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy > 0 ||dy<0 && fab.isShown()) { fab.hide(); } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { fab.show(); } super.onScrollStateChanged(recyclerView, newState); } });


Ok, esto es lo que necesitas:

Primero, dado que su FAB depende de RecyclerView , agregue lo siguiente a su clase de comportamiento:

@Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) { if(dependency instanceof RecyclerView) return true; return false; }

A continuación, para recibir llamadas onNestedScroll() , debe sobrescribir esto:

public boolean onStartNestedScroll(CoordinatorLayout parent, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) { //predict whether you will need to react to the RecyclerView''s scroll; //if yes, return true, otherwise return false to avoid future calls //of onNestedScroll() return true; }

¡Buena suerte!

Actualizar

Aquí es cómo debe verse su ScrollAwareFABBehavior :

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { private static final String TAG = "ScrollAwareFABBehavior"; public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } public boolean onStartNestedScroll(CoordinatorLayout parent, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) { return true; } @Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) { if(dependency instanceof RecyclerView) return true; return false; } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { // TODO Auto-generated method stub super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { child.hide(); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { child.show(); } } }

Además, se probó usando com.android.support:design:23.0.1


Prueba esto

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //Customize your if statement if (recyclerView.computeVerticalScrollOffset() > recyclerView.getHeight() * 2) { if (!fab.isShown()) { fab.show(); } } else { fab.hide(); } } });

disfrutar.


Usé esto en el método onBindViewHolder de RecyclerView.Adapter para establecer el margen inferior del último elemento de la lista en 72dp para que se desplace arriba del botón de acción flotante.

Esto no requiere una entrada ficticia en la lista.

@Override public void onBindViewHolder(ViewHolder holder, int position) { // other binding code goes here. if (position + 1 == getItemCount()) { // set bottom margin to 72dp. setBottomMargin(holder.itemView, (int) (72 * Resources.getSystem().getDisplayMetrics().density)); } else { // reset bottom margin back to zero. (your value may be different) setBottomMargin(holder.itemView, 0); } } public static void setBottomMargin(View view, int bottomMargin) { if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, bottomMargin); view.requestLayout(); } }