最近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代表添加新元素的功能,界面如下:
dna-/wp-content/uploads//09/android_floating_action_button_14.png
要实现float action button可以有多种方法,一种只适合android L,另外一种适合任意版本。
用ImageButton实现
这种方式其实是在ImageButton的属性中使用了android L才有的一些特性:
<ImageButtonandroid: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的定义如下:
<ripple xmlns:android="/apk/res/android"android:color="?android:colorControlHighlight"><item><shape android:shape="oval"><solid android:color="?android:colorAccent"/></shape></item></ripple>
既然是悬浮按钮,那就需要强调维度上面的感觉,当按钮被按下的时候,按钮的阴影需要扩大,并且这个过程是渐变的,我们使用属性动画去改变translatioz。
<selector xmlns:android="/apk/res/android"><itemandroid:state_enabled="true"android:state_pressed="true"><objectAnimatorandroid:duration="@android:integer/config_shortAnimTime"android:propertyName="translationZ"android:valueFrom="@dimen/start_z"android:valueTo="@dimen/end_z"android:valueType="floatType"/></item><item><objectAnimatorandroid: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,而是码代码。
首先定义一个这样的类:
public class CustomFAB extends ImageButton {...}然后是读取一些自定义的属性(假设你了解styleable的用法)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 = newStateListDrawable();sld.addState(newint[] {android.R.attr.state_pressed}, createButton(bgColorPressed));sld.addState(newint[] {}, createButton(bgColor));setBackground(sld);}catch(Throwable t) {}finally {arr.recycle();}}
在xml中我们需要加入如下代码,一般是在attr.xml文件中。
<?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来实现不同状态下的背景
private Drawable createButton(int color) {OvalShape oShape = newOvalShape();ShapeDrawable sd = newShapeDrawable(oShape);setWillNotDraw(false);sd.getPaint().setColor(color);OvalShape oShape1 = newOvalShape();ShapeDrawable sd1 = newShapeDrawable(oShape);sd1.setShaderFactory(newShapeDrawable.ShaderFactory() {@Overridepublic Shader resize(int width, int height) {LinearGradient lg = newLinearGradient(0,0,0, height,newint[] {Color.WHITE,Color.GRAY,Color.DKGRAY,Color.BLACK}, null, Shader.TileMode.REPEAT);returnlg;}});LayerDrawable ld = newLayerDrawable(newDrawable[] {sd1, sd });ld.setLayerInset(0, 5, 5, 0, 0);ld.setLayerInset(1, 0, 0, 5, 5);returnld;}
最后将控件放xml中:
<RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"xmlns:custom="/apk/res/com.survivingwithandroid.fab"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.CustomFABandroid: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>