Android自定義ViewGroup:認識generateLayoutParams方法的作用

2018-11-29
在學(xué)習(xí)android自定義ViewGroup控件的過程中豺旬,隨著學(xué)習(xí)的深入會很容易意識到一些問題

比如:ViewGroup可以讓我通過重寫onLayout方法來操作子view在ViewGroup中的布局 做出很多比如線性布局這樣的自定義布局效果 但是有時候你會遇到
“不同的子view在布局中有不一樣的布局需求”的情況

最常見的就是:FrameLayout和LinearLayout 在xml文件中添加子view時你會發(fā)現(xiàn) FrameLayout的子view是不能添加Margin屬性的 而LinearLayout卻可以

這時你會發(fā)現(xiàn) 你的自定義ViewGroup里的子view也沒有這個屬性 這是什么原因钠惩?要知道 在android中要給一個view添加不同的屬性是需要重寫這個view帶AttributeSet的構(gòu)造方法的:

public TagGroup(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray typedArray =  context.obtainStyledAttributes(attrs,R.styleable.TagGroup);

        int targetColorInt = typedArray.getInt(R.styleable.TagGroup_targetColor,0);
        if (targetColorInt != 0){
            targetColor = context.getResources().getColor(targetColorInt);
        }else targetColor = Color.WHITE;

        typedArray.recycle();

    }

要使用上面的方式獲取 int targetColorInt 需要先在android的values文件夾下新建一個名為attrs的xml文件 :

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="TagGroup">
        <attr name="targetColor" format="integer"/>
    </declare-styleable>

</resources>

但是很明顯 LinearLayout并沒有使用這種方法 因為不管你添加什么view(包括你自定義的什么屬性都沒有的view)進去他們都會擁有Margin屬性

要怎么才能讓 “我的ViewGroup下的所有子view都擁有我希望它們擁有的屬性呢?” 這就需要我們的generateLayoutParams方法了

首先 我們修改下之前在attrs文件中的代碼:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <declare-styleable name="TagGroup_Layout">
        <attr name="layoutMargin" format="dimension"/>
    </declare-styleable>
</resources>

然后 我們先在我們的自定義ViewGroup中定義一個靜態(tài)的內(nèi)部類:

    public static class TagGroupLayoutParams extends MarginLayoutParams {

        public float margin;

        public TagGroupLayoutParams(Context context, AttributeSet attrs) {
            super(context, attrs);

            TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TagGroup_Layout);

            margin = typedArray.getDimension(R.styleable.TagGroup_Layout_layoutMargin,0f);

            typedArray.recycle();

        }

        public TagGroupLayoutParams(int width, int height) {
            super(width, height);
        }

        public TagGroupLayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public TagGroupLayoutParams(LayoutParams source) {
            super(source);
        }
    }

現(xiàn)在 在你的自定義ViewGroup中重寫關(guān)鍵的generateLayoutParams方法:

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new TagGroupLayoutParams(getContext(), attrs);
    }

現(xiàn)在你會發(fā)現(xiàn) 在你的xml中 你的自定義ViewGroup不但擁有了margin屬性 還有了一個layoutMargin屬性:

   <com.example.godru.demo.TagGroup
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/tag_group"
        android:padding="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:myMargin="10dp"
            android:layout_margin="10dp"
            android:textSize="18sp"
            android:text="@string/app_name"
            />

    </com.example.godru.demo.TagGroup>

現(xiàn)在 你可以在任何地方通過獲取到你的ViewGroup中的子view 然后調(diào)用他們的getLayoutParams()方法來獲取TagGroupLayoutParams了 之后就可以使用你的自定義屬性來布局你的控件了

終上 其實generateLayoutParams方法的作用其實就是定義你的控件下所有子控件所使用的layoutParams類 通過這種形式使你的控件可以按自己想要的方式和屬性來操作它的子view 你甚至不需要關(guān)心子view本身 只要你重寫過generateLayoutParams方法 他們就一定會使用你給的LayoutParams來修飾自己 你也必然可以通過getLayoutParams方法獲取到 是一個高度解耦合的設(shè)計

注:自定義屬性可能在androidStudio中會報紅 說找不到目標(biāo)屬性 這是編譯問題 不會影響運行 通常把as關(guān)掉再進就會好

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哈垢,隨后出現(xiàn)的幾起案子妻柒,更是在濱河造成了極大的恐慌,老刑警劉巖耘分,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件举塔,死亡現(xiàn)場離奇詭異绑警,居然都是意外死亡,警方通過查閱死者的電腦和手機央渣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門计盒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芽丹,你說我怎么就攤上這事北启。” “怎么了拔第?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵咕村,是天一觀的道長。 經(jīng)常有香客問我蚊俺,道長,這世上最難降的妖魔是什么泳猬? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任得封,我火速辦了婚禮,結(jié)果婚禮上拷呆,老公的妹妹穿的比我還像新娘洋腮。我一直安慰自己手形,他們只是感情好悯恍,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布瞬欧。 她就那樣靜靜地躺著罢防,像睡著了一般。 火紅的嫁衣襯著肌膚如雪野建。 梳的紋絲不亂的頭發(fā)上属划,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音须蜗,去河邊找鬼目溉。 笑死缭付,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的官份。 我是一名探鬼主播舅巷,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼钠右,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了媚值?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎献酗,沒想到半個月后坷牛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體京闰,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了爱葵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片反浓。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡辆雾,死狀恐怖度迂,靈堂內(nèi)的尸體忽然破棺而出惭墓,到底是詐尸還是另有隱情腊凶,我是刑警寧澤拴念,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布钧萍,位于F島的核電站,受9級特大地震影響政鼠,放射性物質(zhì)發(fā)生泄漏风瘦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一缔俄、第九天 我趴在偏房一處隱蔽的房頂上張望弛秋。 院中可真熱鬧器躏,春花似錦俐载、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揽浙,卻和暖如春状婶,著一層夾襖步出監(jiān)牢的瞬間意敛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工膛虫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留草姻,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓稍刀,卻偏偏與公主長得像撩独,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子账月,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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