android懸浮按鈕(Floating action button)的兩種實現方法
來自: 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中的產物,但是我們也可以在更早的版本中實現。假設我這里有一個列表界面,我想使用float action button代表添加新元素的功能,界面如下:
要實現float action button可以有多種方法,一種只適合android L,另外一種適合任意版本。
用ImageButton實現
這種方式其實是在ImageButton的屬性中使用了android L才有的一些特性:
<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的定義如下:
<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。
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <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,而是碼代碼。
首先定義一個這樣的類:
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 = 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文件中。
<?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 = 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中:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/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.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