FloatingActionButton FAB 悬浮按钮

概述

浮动操作按钮 (简称 FAB) 是一个特殊的promoted(进阶)操作案例,因为一个浮动在UI之上的圆形图标而显得格外突出,同时它还具有动态的效果,比如变形、弹出、位移等。
  • 不是每个屏幕都需要浮动操作按钮,一个屏幕只推荐使用一个浮动操作按钮来增加其显著性,它应该只代表最常见的操作
  • 用浮动操作按钮进行积极的操作,如创建、收藏、分享、浏览和探索。避免用浮动操作按钮进行轻微破坏性操作。
  • 浮动操作按钮不包含 app 图标或状态栏通知。不要把证章或者其他元素层叠在浮动操作按钮上。
  • APP 主要操作的图案强制使用圆形图标。
  • 不要给浮动操作按钮额外的维度。
  • 在默认情况下,浮动操作按钮就像一块扩展的物体在屏幕上活动。在它里面的图标可能是活动的。

……里面列出了几十种使用规范,但是却没有一行代码

基本使用

继承关系
 
    
  1. public class FloatingActionButton extends VisibilityAwareImageButton
  2. class VisibilityAwareImageButton extends ImageButton
放置浮动操作按钮需要使用CoordinatorLayout。 CoordinatorLayout可以让一个元素浮动在另一个元素之上,还 帮助我们协调它所包含的子view之间的交互,比如当用户往下滚动一个页面,浮动操作按钮应该消失,一旦向上滚动,则重现。
另外,由于CoordinatorLayout 不支持 和ListView一起 工作 ,所以 需要用RecyclerView来替换ListViews。同时你还必须把RecyclerView升级到v22版本,之前的v21同样不支持与CoordinatorLayout一起工作。

案例:
 
    
  1. <android.support.design.widget.FloatingActionButton
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content"
  4. android:layout_margin="16dp"
  5. app:backgroundTint="#00f"
  6. app:layout_anchor="@id/app_bar"
  7. app:layout_anchorGravity="bottom|end"
  8. app:layout_behavior="com.example.administrator.myapplication.ScrollAwareFABBehavior"
  9. app:srcCompat="@android:drawable/ic_dialog_email"/>
其中:
  • app:backgroundTint:按钮的背景颜色,默认使用theme中colorAccent的颜色
  • app:layout_anchor:指定参照物
  • app:layout_anchorGravity:指定相对于参照物的位置
  • app:layout_behavior:设置FAB自定义显示隐藏动画效果
  • app:srcCompat或android:src:设置浮动按钮的图标
其他相关属性:
  • app:fabSize:按钮是正常大小还是小号 Size for the FAB. 
  • app:rippleColor点击的边缘阴影颜色,默认取的是theme中的colorControlHighlight
  • app:useCompatPadding:是否启用 Enable compat padding. 
  • app:borderWidth:边框宽度。通常设置为0,同时设置一个合理的margin(16dp),可以解决Android 5.X设备上阴影无法正常显示的问题
  • app:elevation:和立体感相关的属性,设置边缘阴影的宽度 Elevation value for the FAB
  • app:pressedTranslationZ:和立体感相关的属性,设置点击按钮时,按钮边缘阴影的宽度,通常设置比elevation的数值大

根据谷歌的设计规范,drawable的尺寸应该是24dp, 按钮应该处于屏幕的右下角,margin设置为16dp。

FAB与Snackbar

当Snackbar在显示的时候,往往出现在屏幕的底部。为了给Snackbar留出空间,浮动操作按钮需要向上移动。
只要使用 CoordinatorLayout作为基本布局,将自动产生向上移动的动画。 浮动操作按钮有一个 默认的 behavior 来检测Snackbar的添加并让按钮在Snackbar之上呈现上移与Snackbar等高的动画
 
    
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:fitsSystemWindows="true">
  7. <android.support.v4.widget.NestedScrollView
  8. android:id="@+id/nsv"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent"
  11. app:layout_behavior="@string/appbar_scrolling_view_behavior">
  12. <TextView
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:text="CoordinatorLayout \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n NestedScrollView"
  16. android:textSize="30sp"/>
  17. </android.support.v4.widget.NestedScrollView>
  18. <android.support.design.widget.FloatingActionButton
  19. android:id="@+id/fab"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_margin="16dp"
  23. app:backgroundTint="#00f"
  24. app:layout_anchor="@id/nsv"
  25. app:layout_anchorGravity="bottom|right|end"
  26. app:srcCompat="@android:drawable/ic_dialog_email"/>
  27. </android.support.design.widget.CoordinatorLayout>

显示与隐藏动画

FloatingActionButton的显示和隐藏有点让人困惑,可以找到多种实现方式,而且兼容包里的FloatingActionButton还不断的变化。
基本来说,如果是使用官方的FloatingActionButton,列表滚动时的显示与隐藏都是使用自定义 FloatingActionButton.Behavior来实现的。

NestedScrollView默认 app:layout_behavior为:
 
   
  1. app:layout_behavior="@string/appbar_scrolling_view_behavior"
 
   
  1. <string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>

动画模板

 
   
  1. /**
  2. * Fab在滚动时候的显示与隐藏,直接借用了FloatingActionButton内置的动画效果,仅仅是在条件恰当的时候调用hide()和show()方法
  3. */
  4. public class ScrollAwareFABBehaviorDefault extends FloatingActionButton.Behavior {
  5. public ScrollAwareFABBehaviorDefault(Context context, AttributeSet attrs) {
  6. super();
  7. }
  8. @Override
  9. public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
  10. View directTargetChild, View target, int nestedScrollAxes) {
  11. // Ensure we react to vertical scrolling
  12. return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
  13. || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
  14. }
  15. @Override
  16. public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target,
  17. int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
  18. super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
  19. if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {// User scrolled down and the FAB is currently visible
  20. child.hide();//如果要自定义动画效果,就在这里重新定义隐藏时的动画
  21. Snackbar.make(coordinatorLayout, "隐藏", Snackbar.LENGTH_SHORT).show();
  22. } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {// User scrolled up and the FAB is currently not visible
  23. child.show();
  24. Snackbar.make(coordinatorLayout, "显示", Snackbar.LENGTH_SHORT).show();
  25. }
  26. }
  27. }

自定义动画效果1

 
   
  1. /**
  2. * Fab在滚动时候的显示与隐藏,自定义上下滑动的动画
  3. */
  4. public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
  5. private boolean mIsAnimatingOut = false;
  6. public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
  7. super();
  8. }
  9. @Override
  10. public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
  11. View directTargetChild, View target, int nestedScrollAxes) {
  12. // Ensure we react to vertical scrolling
  13. return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
  14. || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
  15. }
  16. @Override
  17. public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target,
  18. int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
  19. super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
  20. if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
  21. child.animate().scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setDuration(1500).start();
  22. } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
  23. child.animate().scaleX(1.0F).scaleY(1.0F).alpha(1.0F).setDuration(1500).start();
  24. }
  25. }
  26. }

自定义动画效果2

 
   
  1. /**
  2. * Fab在滚动时候的显示与隐藏,自定义上下滑动的动画
  3. */
  4. public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
  5. private int toolbarHeight;
  6. public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
  7. super();
  8. this.toolbarHeight = getToolbarHeight(context);
  9. }
  10. @Override
  11. public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
  12. return super.layoutDependsOn(parent, fab, dependency) || (dependency instanceof AppBarLayout);
  13. }
  14. @Override
  15. public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
  16. boolean returnValue = super.onDependentViewChanged(parent, fab, dependency);
  17. if (dependency instanceof AppBarLayout) {
  18. CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
  19. int fabBottomMargin = lp.bottomMargin;
  20. int distanceToScroll = fab.getHeight() + fabBottomMargin;
  21. float ratio = dependency.getY() / toolbarHeight;
  22. fab.setTranslationY(-distanceToScroll * ratio);
  23. }
  24. return returnValue;
  25. }
  26. public static int getToolbarHeight(Context context) {
  27. TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(new int[]{R.attr.actionBarSize});
  28. int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
  29. styledAttributes.recycle();
  30. return toolbarHeight;
  31. }
  32. }
2017-5-23




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值