Android實現(xiàn)FloatingActionButton自定義大小

最近在項目中使用了FloatingActionButton ,但是為了讓UI看起來留白不是那么多你踩,需要對FloatingActionButton 進行自定義大小虑乖。

根據(jù)官方文檔的說明歧斟,FloatingActionButton 僅僅支持設(shè)置app:fabSize="normal"來改變fab的大小,并且這個fabSize的大小提供了三個可選項(normal剃氧,mini和auto)來設(shè)置,可以在布局里設(shè)置也可以在代碼里調(diào)用setSize方法進行設(shè)置阻星。

這里一開始是想到通過在布局里改變layout_width和layout_height來改變控件的大小的朋鞍,但是設(shè)置之后(兩者均設(shè)置為100dp,fabSize設(shè)置為normal),效果如下所示:

并且當設(shè)置了fab的固定寬高再來改變它的fabSize屬性(改為mini或auto)時滥酥,效果會是fab的圖標被撐的很大更舞,甚至邊緣都看不到了,顯然這樣通過固定fab的寬高屬性來改變其大小是行不通的坎吻。

翻閱FloatingActionButton的源碼缆蝉,其第三個構(gòu)造函數(shù)如下


    public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        ThemeUtils.checkAppCompatTheme(context);

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.FloatingActionButton, defStyleAttr,
                R.style.Widget_Design_FloatingActionButton);
        mBackgroundTint = a.getColorStateList(R.styleable.FloatingActionButton_backgroundTint);
        mBackgroundTintMode = ViewUtils.parseTintMode(a.getInt(
                R.styleable.FloatingActionButton_backgroundTintMode, -1), null);
        mRippleColor = a.getColor(R.styleable.FloatingActionButton_rippleColor, 0);
        mSize = a.getInt(R.styleable.FloatingActionButton_fabSize, SIZE_AUTO);
        mBorderWidth = a.getDimensionPixelSize(R.styleable.FloatingActionButton_borderWidth, 0);
        final float elevation = a.getDimension(R.styleable.FloatingActionButton_elevation, 0f);
        final float pressedTranslationZ = a.getDimension(
                R.styleable.FloatingActionButton_pressedTranslationZ, 0f);
        mCompatPadding = a.getBoolean(R.styleable.FloatingActionButton_useCompatPadding, false);
        a.recycle();

        mImageHelper = new AppCompatImageHelper(this);
        mImageHelper.loadFromAttributes(attrs, defStyleAttr);

        mMaxImageSize = (int) getResources().getDimension(R.dimen.design_fab_image_size);

        getImpl().setBackgroundDrawable(mBackgroundTint, mBackgroundTintMode,
                mRippleColor, mBorderWidth);
        getImpl().setElevation(elevation);
        getImpl().setPressedTranslationZ(pressedTranslationZ);
    }

都是讀取屬性來設(shè)置一些自定義屬性,看到最后三行瘦真,發(fā)現(xiàn)getImpl方法的調(diào)用刊头,它的返回值是FloatingActionButtonImpl,原來fab都是通過FloatingActionButtonImpl來實現(xiàn)其自定義屬性的吗氏,找到getImpl這個方法芽偏,源碼如下:

    private FloatingActionButtonImpl getImpl() {
        if (mImpl == null) {
            mImpl = createImpl();
        }
        return mImpl;
    }

    private FloatingActionButtonImpl createImpl() {
        final int sdk = Build.VERSION.SDK_INT;
        if (sdk >= 21) {
            return new FloatingActionButtonLollipop(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        } else if (sdk >= 14) {
            return new FloatingActionButtonIcs(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        } else {
            return new FloatingActionButtonGingerbread(this, new ShadowDelegateImpl(),
                    ViewUtils.DEFAULT_ANIMATOR_CREATOR);
        }
    }

上面創(chuàng)建FloatingActionButtonImpl每種情況都傳遞了ShadowDelegateImpl的一個實例,說明這個類對創(chuàng)建FloatingActionButtonImpl很重要弦讽,往下看這個類的源碼污尉,如下所示:

    private class ShadowDelegateImpl implements ShadowViewDelegate {
        ShadowDelegateImpl() {
        }

        @Override
        public float getRadius() {
            return getSizeDimension() / 2f;
        }

        @Override
        public void setShadowPadding(int left, int top, int right, int bottom) {
            mShadowPadding.set(left, top, right, bottom);
            setPadding(left + mImagePadding, top + mImagePadding,
                    right + mImagePadding, bottom + mImagePadding);
        }

        @Override
        public void setBackgroundDrawable(Drawable background) {
            FloatingActionButton.super.setBackgroundDrawable(background);
        }

        @Override
        public boolean isCompatPaddingEnabled() {
            return mCompatPadding;
        }
    }

這個類里有一個getRadius方法,字面意思理解就是獲取半徑的往产,終于柳暗花明被碗,原來fab的大小(即半徑)是這個方法來獲取的仿村,可以看到它調(diào)用了getSizeDimension锐朴,下面看這個getSizeDimension方法,源碼如下:

    int getSizeDimension() {
        return getSizeDimension(mSize);
    }

    private int getSizeDimension(@Size final int size) {
        final Resources res = getResources();
        switch (size) {
            case SIZE_AUTO:
                // If we're set to auto, grab the size from resources and refresh
                final int width = ConfigurationHelper.getScreenWidthDp(res);
                final int height = ConfigurationHelper.getScreenHeightDp(res);
                return Math.max(width, height) < AUTO_MINI_LARGEST_SCREEN_WIDTH
                        ? getSizeDimension(SIZE_MINI)
                        : getSizeDimension(SIZE_NORMAL);
            case SIZE_MINI:
                return res.getDimensionPixelSize(R.dimen.design_fab_size_mini);
            case SIZE_NORMAL:
            default:
                return res.getDimensionPixelSize(R.dimen.design_fab_size_normal);
        }
    }

原來這里google做的控件也是通過獲取資源文件dimens.xml來獲取dimen值的(廢話蔼囊,當然是了)焚志。終于看到這里,我才恍然大悟畏鼓,我可以通過自定義這個design_fab_size_normal來實現(xiàn)覆蓋默認的dimen值呀(因為我的布局里是設(shè)置fabSize為normal的)酱酬,自定義代碼如下所示:

<dimen name="design_fab_size_normal" tools:ignore="PrivateResource">80dp</dimen>

這樣即完美搞定我的fab自定義大小的需求。上張效果圖云矫,如下所示:

和之前那個設(shè)置fab的固定寬高的效果比好多了膳沽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市让禀,隨后出現(xiàn)的幾起案子挑社,更是在濱河造成了極大的恐慌,老刑警劉巖巡揍,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痛阻,死亡現(xiàn)場離奇詭異,居然都是意外死亡吼肥,警方通過查閱死者的電腦和手機录平,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門麻车,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斗这,你說我怎么就攤上這事动猬。” “怎么了表箭?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵赁咙,是天一觀的道長。 經(jīng)常有香客問我免钻,道長彼水,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任极舔,我火速辦了婚禮凤覆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拆魏。我一直安慰自己盯桦,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布渤刃。 她就那樣靜靜地躺著拥峦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卖子。 梳的紋絲不亂的頭發(fā)上略号,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音洋闽,去河邊找鬼玄柠。 笑死,一個胖子當著我的面吹牛诫舅,可吹牛的內(nèi)容都是我干的随闪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼骚勘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了撮奏?” 一聲冷哼從身側(cè)響起俏讹,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畜吊,沒想到半個月后泽疆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡玲献,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年殉疼,在試婚紗的時候發(fā)現(xiàn)自己被綠了梯浪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓢娜,死狀恐怖挂洛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情眠砾,我是刑警寧澤虏劲,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站褒颈,受9級特大地震影響柒巫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谷丸,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一堡掏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刨疼,春花似錦泉唁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漩绵,卻和暖如春贱案,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背止吐。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工宝踪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碍扔。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓瘩燥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親不同。 傳聞我的和親對象是個殘疾皇子厉膀,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容