Меню и Autohide FloatingActionButton из библиотеки поддержки Android Design

Я использую библиотеку поддержки Android Design, и я хочу, чтобы FloatingActionButton имел AutoHide с помощью прокрутки,

Мой макет:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/LargeText" /> </ScrollView> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchorGravity="bottom|right|end" app:layout_anchor="@id/scrollView" android:src="@drawable/abc_btn_rating_star_off_mtrl_alpha" /> </android.support.design.widget.CoordinatorLayout> 

FloatingActionButton всегда показывает, когда вы прокручиваете текст, я хочу, чтобы он скрывал его при прокрутке текста.

И я хочу иметь меню FloatingActionButton, нажав на FloatingActionButton, например:

Введите описание изображения здесь

Solutions Collecting From Web of "Меню и Autohide FloatingActionButton из библиотеки поддержки Android Design"

FloatingActionButton, которые имеют AutoHide путем прокрутки,

Вы должны использовать android.support.v4.widget.NestedScrollView вместо ScrollView . Вы не можете использовать ScrollView. Вы должны использовать NestedScrollView или представление, которое реализует интерфейс NestedScrollingChild, например RecyclerView.

Чтобы достичь такого рода шаблонов, вы должны реализовать свое пользовательское Behavior . Существует хороший код, отправленный Googler, который скрывает FAB, когда пользователь прокручивается вниз и показывает его при прокрутке назад. Повторяет ту же анимацию, что и FloatingActionButton.Behavior использует для скрытия / отображения FAB в ответ на выход AppBarLayout / ввод.

ОБНОВЛЕНО 18/07/2015

С помощью 22.2.1 вы можете просто добавить код, указанный ниже, используя предварительно созданные анимации. Просто используйте класс, подобный этому: (исходный источник здесь )

 public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton 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 FloatingActionButton 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 && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB child.hide(); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB child.show(); } } } 

Затем вы можете применить это поведение к своему FAB, используя:

 <android.support.design.widget.FloatingActionButton android:id="@+id/fab" app:layout_behavior="com.support.android.designlibdemo.ScrollAwareFABBehavior" /> 

С Design 22.2.0 : вы должны использовать такой класс: (исходный источник здесь )

 public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); private boolean mIsAnimatingOut = false; public ScrollAwareFABBehavior(Context context, AttributeSet attrs) { super(); } @Override public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton 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 FloatingActionButton 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 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB animateOut(child); } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB animateIn(child); } } // Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits private void animateOut(final FloatingActionButton button) { if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer() .setListener(new ViewPropertyAnimatorListener() { public void onAnimationStart(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = true; } public void onAnimationCancel(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; } public void onAnimationEnd(View view) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; view.setVisibility(View.GONE); } }).start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out); anim.setInterpolator(INTERPOLATOR); anim.setDuration(200L); anim.setAnimationListener(new Animation.AnimationListener() { public void onAnimationStart(Animation animation) { ScrollAwareFABBehavior.this.mIsAnimatingOut = true; } public void onAnimationEnd(Animation animation) { ScrollAwareFABBehavior.this.mIsAnimatingOut = false; button.setVisibility(View.GONE); } @Override public void onAnimationRepeat(final Animation animation) { } }); button.startAnimation(anim); } } // Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters private void animateIn(FloatingActionButton button) { button.setVisibility(View.VISIBLE); if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).scaleX(1.0F).scaleY(1.0F).alpha(1.0F) .setInterpolator(INTERPOLATOR).withLayer().setListener(null) .start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in); anim.setDuration(200L); anim.setInterpolator(INTERPOLATOR); button.startAnimation(anim); } } } 

Затем вы можете применить это поведение к своему FAB, используя:

 <android.support.design.widget.FloatingActionButton android:id="@+id/fab" app:layout_behavior="com.support.android.designlibdemo.ScrollAwareFABBehavior" /> 

Конечно, вы можете изменить этот код, чтобы получить свой любимый шаблон.

И я хочу иметь меню FloatingActionButton, нажав на FloatingActionButton, например:

В настоящее время оригинальный FAB не поддерживает эту модель. Для этого вам нужно реализовать собственный код.

Вы можете добиться этого

Вот мой код.

Шаг 1:

Сначала создайте Getter of FloatingActionMenu, чтобы вы могли называть его из другого действия или из фрагмента, в котором используется ваш recycleview

 public FloatingActionMenu getFloatingActionMenu() { return fabMenu; } 

Шаг 2:

Вызов под строкой от другого действия или от фрагмента

  FloatingActionMenu fabMenu=((MainActivity)getActivity()).getFloatingActionMenu(); 

Шаг 3:

Теперь Check wheather recycleview прокручивается или не зависит от позиции «dy». Здесь я использовал анимацию fabMenu

 Animation FabMenu_fadOut = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_out); Animation FabMenu_fadIn = AnimationUtils.loadAnimation(getActivity(), R.anim.abc_grow_fade_in); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 0 && floatingActionButton.isShown()) { //fabMenu.startAnimation(FabMenu_fadIn); fabMenu.setVisibility(View.GONE); } if (dy < 0 && !floatingActionButton.isShown()) { // fabMenu.startAnimation(FabMenu_fadOut); fabMenu.setVisibility(View.VISIBLE); } } }); 

Примечание. Если вы хотите скрыть FloatingActionButton на прокрутке, используйте тот же код, что и в FloatingActionMenu.

Спасибо.

Используя это, вы можете реализовать меню плавающих действий.

Что касается анимации для меню плавающих действий, вы можете создать класс ScrollAwareFloatingActionMenuBehaviour:

 public class ScrollAwareFloatingActionMenuBehaviour extends CoordinatorLayout.Behavior<FloatingActionsMenu> { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); private boolean mIsAnimatingOut = false; private boolean mIsAnimatingIn = false; public ScrollAwareFloatingActionMenuBehaviour(Context context, AttributeSet attrs) { } @Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionsMenu child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View directTargetChild, View target, int nestedScrollAxes) { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 10 && !this.mIsAnimatingOut && !this.mIsAnimatingIn && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB animateOut(child); } else if (dyConsumed < -10 && !this.mIsAnimatingOut && !this.mIsAnimatingIn && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB animateIn(child); } } // Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits private void animateOut(final FloatingActionsMenu button) { if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).translationYBy(200F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer() .setListener(new ViewPropertyAnimatorListener() { public void onAnimationStart(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = true; } public void onAnimationCancel(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; } public void onAnimationEnd(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; view.setVisibility(View.GONE); } }).start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.design_fab_out); anim.setInterpolator(INTERPOLATOR); anim.setDuration(200L); anim.setAnimationListener(new Animation.AnimationListener() { public void onAnimationStart(Animation animation) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = true; } public void onAnimationEnd(Animation animation) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingOut = false; button.setVisibility(View.GONE); } @Override public void onAnimationRepeat(final Animation animation) { } }); button.startAnimation(anim); } } // Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters private void animateIn(FloatingActionsMenu button) { button.setVisibility(View.VISIBLE); if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).translationYBy(-200F).alpha(1.0F) .setInterpolator(INTERPOLATOR).withLayer().setListener(new ViewPropertyAnimatorListener() { @Override public void onAnimationStart(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = true; } @Override public void onAnimationEnd(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = false; } @Override public void onAnimationCancel(View view) { ScrollAwareFloatingActionMenuBehaviour.this.mIsAnimatingIn = false; } }) .start(); } else { Animation anim = AnimationUtils.loadAnimation(button.getContext(), android.support.design.R.anim.design_fab_in); anim.setDuration(200L); anim.setInterpolator(INTERPOLATOR); button.startAnimation(anim); } } } 

Обратите внимание, что R.anim.fab_in и R.anim.fab_out заменяются соответственно на R.anim.design_fab_in и R.anim.design_fab_out.

Используйте его в xml:

 <com.getbase.floatingactionbutton.FloatingActionsMenu xmlns:fab="http://schemas.android.com/apk/res-auto" android:id="@+id/fab_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" fab:fab_addButtonColorNormal="@color/colorAccent" fab:fab_addButtonColorPressed="@color/colorAccentLight" fab:fab_addButtonPlusIconColor="@android:color/white" app:layout_behavior="com.example.widgets.behaviour.ScrollAwareFloatingActionMenuBehaviour" fab:fab_labelStyle="@style/menu_labels_style" fab:fab_labelsPosition="left"> <com.getbase.floatingactionbutton.FloatingActionButton android:id="@+id/fab_share" android:layout_width="wrap_content" android:layout_height="wrap_content" fab:fab_colorNormal="@color/fab_normal_blue" fab:fab_colorPressed="@color/fab_normal_blue_pressed" fab:fab_icon="@drawable/ic_social_share" fab:fab_title="@string/fab_menu_group_chat" /> </com.getbase.floatingactionbutton.FloatingActionsMenu>