Android Support Design 库 之 FloatingActionButton使用及源码分析

先来看一段谷歌官方对FAB的解释http://www.google.co.in/design/spec/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button

我简单归纳一下文中所说的几个重点:

1.不是每个app 都需要FAB,如果需要的话最多也是只要一个FAB即可。

2.FAB的icon应该是表示一个动词,而不能是一个名词。

比如我们可以这样:

但是不能这样:

3.FAB必须得是圆形的icon 不能是其他样子。并且只能是2d平面图。不能带有3d的投影之类的效果

好我们来看一下FAB的简单使用

xml文件

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:app="http://schemas.android.com/apk/res-auto"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:paddingBottom="@dimen/activity_vertical_margin"
 7     android:paddingLeft="@dimen/activity_horizontal_margin"
 8     android:paddingRight="@dimen/activity_horizontal_margin"
 9     android:paddingTop="@dimen/activity_vertical_margin"
10     tools:context=".MainActivity">
11
12     <FrameLayout
13         android:id="@+id/layout"
14         android:layout_width="match_parent"
15         android:layout_height="match_parent">
16
17         <android.support.design.widget.FloatingActionButton
18             android:id="@+id/fabutton"
19             android:layout_width="wrap_content"
20             android:layout_height="wrap_content">
21
22         </android.support.design.widget.FloatingActionButton>
23
24
25     </FrameLayout>
26
27
28 </RelativeLayout>

看一下运行的效果:

当然也可以改变位置FAB的位置,因为FAB一般情况下都在右下角落

再加一些属性

看看所谓的按下去的波纹效果:

然后看一下另外一个特殊的效果,很多GOOGLE 官方的app里面 FAB和listview 在一起的时候会有额外的效果,

比如listview 往下拉的时候 FAB才显示 往上滑的时候就不显示 这个效果放在以前是不太好做的,

但是更新了这个新的官方库以后这个效果就比较好做了。

首先你要使用新的 Recyclerview这个类来代替listview。并且要22版本以上的,21版本不支持这个特性

compile ‘com.android.support:recyclerview-v7:22.2.1‘

然后xml文件要稍微更改一下

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:app="http://schemas.android.com/apk/res-auto"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:paddingBottom="@dimen/activity_vertical_margin"
 7     android:paddingLeft="@dimen/activity_horizontal_margin"
 8     android:paddingRight="@dimen/activity_horizontal_margin"
 9     android:paddingTop="@dimen/activity_vertical_margin"
10     tools:context=".MainActivity">
11
12     <android.support.design.widget.CoordinatorLayout
13         android:layout_width="match_parent"
14         android:layout_height="match_parent">
15
16         <android.support.v7.widget.RecyclerView
17             android:id="@+id/recyclerView"
18             android:layout_width="match_parent"
19             android:layout_height="match_parent">
20
21         </android.support.v7.widget.RecyclerView>
22
23         <android.support.design.widget.FloatingActionButton
24             android:layout_width="wrap_content"
25             android:layout_height="wrap_content"
26             android:layout_gravity="bottom|right"
27             android:layout_margin="16dp"
28             app:layout_anchor="@id/recyclerView"
29             app:layout_anchorGravity="bottom|right|end"
30             app:layout_behavior="com.example.administrator.testfab.ScrollBehavior" />
31     </android.support.design.widget.CoordinatorLayout>
32
33
34 </RelativeLayout>

注意30行 使用了一个我们自定义的behavior。

  1 package com.example.administrator.testfab;
  2
  3
  4 import android.content.Context;
  5 import android.os.Build;
  6 import android.support.design.widget.CoordinatorLayout;
  7 import android.support.design.widget.FloatingActionButton;
  8 import android.support.v4.view.ViewCompat;
  9 import android.support.v4.view.ViewPropertyAnimatorListener;
 10 import android.support.v4.view.animation.FastOutSlowInInterpolator;
 11 import android.util.AttributeSet;
 12 import android.view.View;
 13 import android.view.animation.Animation;
 14 import android.view.animation.AnimationUtils;
 15 import android.view.animation.Interpolator;
 16
 17 public class ScrollBehavior extends FloatingActionButton.Behavior {
 18     private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
 19     private boolean mIsAnimatingOut = false;
 20
 21     public ScrollBehavior(Context context, AttributeSet attrs) {
 22         super();
 23     }
 24
 25     @Override
 26     public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
 27                                        final View directTargetChild, final View target, final int nestedScrollAxes) {
 28         // 确定是在垂直方向上滑动
 29         return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
 30                 || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
 31     }
 32
 33     @Override
 34     public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
 35                                final View target, final int dxConsumed, final int dyConsumed,
 36                                final int dxUnconsumed, final int dyUnconsumed) {
 37         super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
 38         if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) {
 39             // 不显示FAB
 40             animateOut(child);
 41         } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
 42             // 显示FAB
 43             animateIn(child);
 44         }
 45     }
 46
 47     // 定义滑动时的属性动画效果
 48     private void animateOut(final FloatingActionButton button) {
 49         if (Build.VERSION.SDK_INT >= 14) {
 50             ViewCompat.animate(button).scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setInterpolator(INTERPOLATOR).withLayer()
 51                     .setListener(new ViewPropertyAnimatorListener() {
 52                         public void onAnimationStart(View view) {
 53                             ScrollBehavior.this.mIsAnimatingOut = true;
 54                         }
 55
 56                         public void onAnimationCancel(View view) {
 57                             ScrollBehavior.this.mIsAnimatingOut = false;
 58                         }
 59
 60                         public void onAnimationEnd(View view) {
 61                             ScrollBehavior.this.mIsAnimatingOut = false;
 62                             view.setVisibility(View.GONE);
 63                         }
 64                     }).start();
 65         } else {
 66             Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out);
 67             anim.setInterpolator(INTERPOLATOR);
 68             anim.setDuration(200L);
 69             anim.setAnimationListener(new Animation.AnimationListener() {
 70                 public void onAnimationStart(Animation animation) {
 71                     ScrollBehavior.this.mIsAnimatingOut = true;
 72                 }
 73
 74                 public void onAnimationEnd(Animation animation) {
 75                     ScrollBehavior.this.mIsAnimatingOut = false;
 76                     button.setVisibility(View.GONE);
 77                 }
 78
 79                 @Override
 80                 public void onAnimationRepeat(final Animation animation) {
 81                 }
 82             });
 83             button.startAnimation(anim);
 84         }
 85     }
 86
 87     private void animateIn(FloatingActionButton button) {
 88         button.setVisibility(View.VISIBLE);
 89         if (Build.VERSION.SDK_INT >= 14) {
 90             ViewCompat.animate(button).scaleX(1.0F).scaleY(1.0F).alpha(1.0F)
 91                     .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
 92                     .start();
 93         } else {
 94             Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in);
 95             anim.setDuration(200L);
 96             anim.setInterpolator(INTERPOLATOR);
 97             button.startAnimation(anim);
 98         }
 99     }
100 }

最后看一下效果:

最后FAB的源码只有300行,继承自IMAGEVIEW,比较简单,我就不带大家分析了,但是这个源码还是建议去看一下,

因为FAB源码里面会有很多自定义属性的代码在里面,FAB在版本不同的android机器上面会有不一样的显示效果(其实就是小bug),

如果发现这类小bug,需要自己看下源码 找到对应的属性 然后自己把这个属性在外部定义成你想统一的效果才行!

时间: 2024-09-30 09:17:42

Android Support Design 库 之 FloatingActionButton使用及源码分析的相关文章

Android Support Design 库 之 Snackbar使用及源码分析

在谷歌提出 material design 之后,终于推出了 android.support.design 这个官方的material design库,这几天我也简单浏览了下这个库,基本上我们常用的组件都有了,从今天开始,就可以一步步替换掉 以前使用的github上的那些开源控件了,毕竟谷歌出品 才属精品~~另外分析这个design库的源码我认为是非常有意义的,android上的app 在以前各家都有各家的风格,但是在谷歌出了material design这门新的 设计语言以及官方的库以后,相信

Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)

1 背景 还记得前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事件疑惑吗?当时说了,在那一篇咱们只讨论View的触摸事件派发机制,这个疑惑留在了这一篇解释,也就是ViewGroup的事件派发机制. PS:阅读本篇前建议先查看前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>,这一篇承接上一篇. 关于View与ViewGroup的区别在前一篇的A

Android触摸屏事件派发机制详解与源码分析

请看下面三篇博客,思路还是蛮清晰的,不过还是没写自定义控件系列哥们的思路清晰: Android触摸屏事件派发机制详解与源码分析一(View篇) http://blog.csdn.net/yanbober/article/details/45887547 Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇) http://blog.csdn.net/yanbober/article/details/45912661 Android触摸屏事件派发机制详解与源码分析三(Activi

Android事件传递机制详解及最新源码分析——ViewGroup篇

在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴,强烈建议先阅读上一篇. 好了,废话还是少说,直奔主题,开始本篇的ViewGroup事件传递机制探索之旅. 依然从简单的Demo例子现象开始分析 新建安卓工程,首先自定义一个Button以及一个RelativeLayout,很简单,只是重写了主要与事件传递机制相关的方法,代码如下: 自定义WLButton类: 1 public class WLButton e

Android触摸屏事件派发机制详解与源码分析三(Activity篇)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 该篇承接上一篇<Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)>,阅读本篇之前建议先阅读. 1 背景 还记得前面两篇从Android的基础最小元素控件(View)到ViewGroup控件的触摸屏事件分发机制分析吗?你可能看完会有疑惑,View的事件是ViewGro

Android Support Design Library之FloatingActionButton

为了文章的精彩,前三个标题实现FloatingActionButton的特效,最后一节讲解其属性详情. 1.自定义Behavior实现掌阅底部菜单与按钮联动效果. 我们来看看掌阅的菜单效果: 以前没有这个支持库的时候,需要写两个动画,一个按钮的动画一个菜单的动画,现在因为有了Behavior,那么一个在另一个的相对位置就可以实现其效果. 另外标记一下这个库最重要的知识点就是Behavior,其他的与基本控件无异.下面我们来实现其效果. 自定义Behavior代码: public class LY

【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑][下文简称(五),请先阅读完(五)再阅读本文],我们通过示例和log来分析了Android的事件分发机制.这些,我们只是看到了现象,如果要进一步了解事件分发机制,这是不够的,我们还需要透过现象看本质,去研究研究源码.本文将从源码(基

Android消息机制Handler、Looper、MessageQueue源码分析

1. Handler Looper MessageQueue的关系 2.源码分析 下图表示了Handler.Looper.MessageQueue.Message这四个类之间的关系. Handler必须与一个Looper关联,相关Looper决定了该Handler会向哪个MessageQueue发送Message 每一个Looper中都包含一个MessageQueue Handler中的mQueue引用的就是与之关联的Looper的MessageQueue 不管Handler在哪个线程发送Mes

Android应用AsyncTask处理机制详解及源码分析

[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机制详解及源码分析>文章),这里继续分析Android的另一个异步机制AsyncTask的原理. 当使用线程和Handler组合实现异步处理时,当每次执行耗时操作都创建一条新线程进行处理,性能开销会比