web-dev-qa-db-ja.com

メニューとAndroidデザインサポートライブラリのFloatingActionButtonの自動非表示

Androidデザインサポートライブラリを使用していますが、スクロールによる自動非表示を備えたFloatingActionButtonが必要です。

私のレイアウトは:

<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メニューを作成したいと思います。

enter image description here

10
AliSh

スクロールによる自動非表示を持つFloatingActionButton、

ScrollViewの代わりにAndroid.support.v4.widget.NestedScrollViewを使用する必要があります。 ScrollViewは使用できません。 NestedScrollView、またはRecyclerViewなどのNestedScrollingChildインターフェイスを実装するビューを使用する必要があります。

この種のパターンを実現するには、カスタムBehaviorを実装する必要があります。 Google社員によって投稿されたNiceコードがあり、ユーザーが下にスクロールするとFABを非表示にし、上にスクロールするとFABを表示します。 FloatingActionButton.BehaviorがAppBarLayoutの終了/入力に反応してFABを非表示/表示するために使用するのと同じアニメーションを再利用します。

2015年7月18日更新

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はこのパターンをサポートしていません。それを実現するには、カスタムコードを実装する必要があります。

31

あなたはそれを達成することができます

これが私のコードです。

ステップ1:

まず、FloatingActionMenuのGetterを作成して、別のアクティビティから、またはrecycleviewが使用されているフラグメントから呼び出すことができるようにします。

public FloatingActionMenu getFloatingActionMenu() {
        return fabMenu;
    }

ステップ2:

別のアクティビティまたはフラグメントから以下の行を呼び出します

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

ステップ3:

ここで、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と同じコードを使用します。

ありがとうございました。

1
Ulearn

this を使用してフローティングアクションメニューを実装できます。

フローティングアクションメニューのアニメーションに関しては、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>
0
Noel Chew