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メニューを作成したいと思います。
スクロールによる自動非表示を持つ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はこのパターンをサポートしていません。それを実現するには、カスタムコードを実装する必要があります。
あなたはそれを達成することができます
これが私のコードです。
ステップ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と同じコードを使用します。
ありがとうございました。
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>