原文:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html
最近android中有很多新的设计规范被引入,最流行的莫过于被称作Promoted Actions的设计了,Promoted Actions是指一种操作按钮,它不是放在actionbar中,而是直接在可见的UI布局中(当然这里的UI指的是setContentView所管辖的范围)。因此它更容易在代码中被获取到(试想如果你要在actionbar中获取一个菜单按钮是不是很难?),Promoted Actions往往主要用于一个界面的主要操作,比如在email的邮件列表界面,promoted action可以用于接受一个新邮件。promoted action在外观上其实就是一个悬浮按钮,更常见的是漂浮在界面上的圆形按钮,一般我直接将promoted action称作悬浮按钮,英文名称Float Action Button 简称(FAB,不是FBI哈)。
float action button是android l中的产物,但是我们也可以在更早的版本中实现。假设我这里有一个列表界面,我想使用floataction button代表添加新元素的功能,界面如下:
要实现float action button可以有多种方法,一种只适合android L,另外一种适合任意版本。
用ImageButton实现
这种方式其实是在ImageButton的属性中使用了android L才有的一些特性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<ImageButton android:layout_width= "56dp" android:layout_height= "56dp" android:src= "@drawable/plus" android:layout_alignParentBottom= "true" android:layout_alignParentRight= "true" android:layout_marginRight= "16dp" android:layout_marginBottom= "16dp" android:tint= "@android:color/white" android:id= "@+id/fab" android:elevation= "1dp" android:background= "@drawable/ripple" android:stateListAnimator= "@anim/fab_anim" /> |
仔细一点,你会发现我们将这个ImageButton放到了布局的右下角,为了实现float action button应该具备的效果,需要考虑以下几个方面:
·Background
·Shadow
·Animation
背景上我们使用ripple drawable来增强吸引力。注意上面的xml代码中我们将background设置成了@drawable/ripple ,ripple drawable的定义如下:
1
2
3
4
5
6
7
|
<ripple xmlns:android= "http://schemas.android.com/apk/res/android" android:color= "?android:colorControlHighlight" > <item> <shape android:shape= "oval" > <solid android:color= "?android:colorAccent" /> </shape> </item> </ripple> |
既然是悬浮按钮,那就需要强调维度上面的感觉,当按钮被按下的时候,按钮的阴影需要扩大,并且这个过程是渐变的,我们使用属性动画去改变translatioz。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<item android:state_enabled= "true" android:state_pressed= "true" > <objectAnimator android:duration= "@android:integer/config_shortAnimTime" android:propertyName= "translationZ" android:valueFrom= "@dimen/start_z" android:valueTo= "@dimen/end_z" android:valueType= "floatType" /> </item> <item> <objectAnimator android:duration= "@android:integer/config_shortAnimTime" android:propertyName= "translationZ" android:valueFrom= "@dimen/end_z" android:valueTo= "@dimen/start_z" android:valueType= "floatType" /> </item> </selector> |
使用自定义控件的方式实现悬浮按钮
这种方式不依赖于android L,而是码代码。
首先定义一个这样的类:
1
2
3
|
public class CustomFAB extends ImageButton { ... } |
然后是读取一些自定义的属性(假设你了解styleable的用法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private void init(AttributeSet attrSet) { Resources.Theme theme = ctx.getTheme(); TypedArray arr = theme.obtainStyledAttributes(attrSet, R.styleable.FAB, 0, 0); try { setBgColor(arr.getColor(R.styleable.FAB_bg_color, Color.BLUE)); setBgColorPressed(arr.getColor(R.styleable.FAB_bg_color_pressed, Color.GRAY)); StateListDrawable sld = new StateListDrawable(); sld.addState( new int[] {android.R.attr.state_pressed}, createButton(bgColorPressed)); sld.addState( new int[] {}, createButton(bgColor)); setBackground(sld); } catch (Throwable t) {} finally { arr.recycle(); } } |
在xml中我们需要加入如下代码,一般是在attr.xml文件中。
1
2
3
4
5
6
7
8
|
<?xml version= "1.0" encoding= "utf-8" ?> <resources> <declare-styleable name= "FAB" > <!-- Background color --> <attr name= "bg_color" format= "color|reference" /> <attr name= "bg_color_pressed" format= "color|reference" /> </declare-styleable> </resources> |
使用StateListDrawable来实现不同状态下的背景
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
private Drawable createButton(int color) { OvalShape oShape = new OvalShape(); ShapeDrawable sd = new ShapeDrawable(oShape); setWillNotDraw( false ); sd.getPaint().setColor(color); OvalShape oShape1 = new OvalShape(); ShapeDrawable sd1 = new ShapeDrawable(oShape); sd1.setShaderFactory( new ShapeDrawable.ShaderFactory() { @Override public Shader resize(int width, int height) { LinearGradient lg = new LinearGradient(0,0,0, height, new int[] { Color.WHITE, Color.GRAY, Color.DKGRAY, Color.BLACK }, null , Shader.TileMode.REPEAT); return lg; } }); LayerDrawable ld = new LayerDrawable( new Drawable[] { sd1, sd }); ld.setLayerInset(0, 5, 5, 0, 0); ld.setLayerInset(1, 0, 0, 5, 5); return ld; } |
最后将控件放xml中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" android:paddingLeft= "@dimen/activity_horizontal_margin" android:paddingRight= "@dimen/activity_horizontal_margin" android:paddingTop= "@dimen/activity_vertical_margin" android:paddingBottom= "@dimen/activity_vertical_margin" tools:context= ".MyActivity" > ... <com.survivingwithandroid.fab.CustomFAB android:layout_width= "56dp" android:layout_height= "56dp" android:src= "@android:drawable/ic_input_add" android:layout_alignParentBottom= "true" android:layout_alignParentRight= "true" android:layout_marginRight= "16dp" android:layout_marginBottom= "16dp" custom:bg_color= "@color/light_blue" android:tint= "@android:color/white" /> </RelativeLayout> |
项目的源码下载:github