Google最近為了讓開發者更好的更規范的應用Material Design設計思想,特意放出了android support design library,里面含有更多Material Design的標志性組件,其中最常用的就是那個圓形按鈕,叫做Floating Action Button,可以簡稱為FAB。一個使用該控件的例子為:
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:layout_marginLeft="25dp" android:layout_gravity="start|top" app:borderWidth="0dp" app:fabSize="normal" app:elevation="4dp" android:scaleType="center" android:src="@drawable/btn_menu" />
注意,在跟布局中需要配置app這個命令空間:
xmlns:app="http://schemas.android.com/apk/res-auto"
這里關注FAB的app:fabSize這個屬性,它是用來規定大小,但是發現只有兩個值:mini和normal,默認情況下官方推薦的寬高是56dp,但是如果設計師需要你顯示一個比較大一些的FAB,比如100dp(這里發現將fabSize設置成normal或者mini都很小),該怎么辦?
第一反應是修改layout_height和layout_width這兩個屬性,將他們設置成100dp,最后卻發現成了這個慫樣:
看來改變上述兩個屬性是不行的,那么我們來看FloatingActionButton的源碼,在它的構造函數中,有下列代碼:
ShadowViewDelegate delegate = new ShadowViewDelegate() { public float getRadius() { return (float)FloatingActionButton.this.getSizeDimension() / 2.0F; } public void setShadowPadding(int left, int top, int right, int bottom) { FloatingActionButton.this.mShadowPadding.set(left, top, right, bottom); FloatingActionButton.this.setPadding(left + FloatingActionButton.this.mContentPadding, top + FloatingActionButton.this.mContentPadding, right + FloatingActionButton.this.mContentPadding, bottom + FloatingActionButton.this.mContentPadding); } public void setBackgroundDrawable(Drawable background) { FloatingActionButton.super.setBackgroundDrawable(background); } }; if(VERSION.SDK_INT >= 21) { this.mImpl = new FloatingActionButtonLollipop(this, delegate); } else { this.mImpl = new FloatingActionButtonEclairMr1(this, delegate); }
這里的mImpl是一個FloatingActionButtonImpl的實現類,FloatingActionButton大部分的操作實際上都是在操作這個mImpl,這個mImpl在被new出來的時候會判斷當前環境是不是API level大於等於21(實際上在小於21的時候,他用drawable繪制了一層陰影從而有類似於21以上的evevation的效果),隨后創建mImpl的時候傳入了delegate這個參數,ShadowViewDelegate實際上就是個drawable的包裝類。我們看getRadius這個實現方法,顯然它是計算半徑的,所以要想定制FAB的寬高,得要從這里找文章。
具體看getSizeDimension這個方法:
final int getSizeDimension() { switch(this.mSize) { case 0: default: return this.getResources().getDimensionPixelSize(dimen.fab_size_normal); case 1: return this.getResources().getDimensionPixelSize(dimen.fab_size_mini); } }
原來app:fabSize實際上是在調用fab_size_normal和fab_size_mini這兩個dimen的值,相應的對應了normal和mini這兩種情況,那么我們可以想到在我們的代碼中國同樣定義這兩個dimen值對原來的進行覆蓋,於是我們在醒目代碼的dimen.xml中定義:
<resources> <dimen name="fab_size_normal">100dp</dimen> </resources>
這個時候再看效果:
修改成功