日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android开发技巧——自定义控件之自定义属性

發(fā)布時(shí)間:2024/4/13 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android开发技巧——自定义控件之自定义属性 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android開(kāi)發(fā)技巧——自定義控件之自定義屬性

掌握自定義控件是很重要的,因?yàn)橥ㄟ^(guò)自定義控件,能夠:解決UI問(wèn)題,優(yōu)化布局性能,簡(jiǎn)化布局代碼

上一篇講了如何通過(guò)xml把幾個(gè)控件組織起來(lái),并繼承某個(gè)ViewGroup子類,把它們封裝起來(lái)使用。這是我們接觸到的最簡(jiǎn)單的一種自定制控件了。但許多時(shí)候,我們還需要在布局文件中使用它們的時(shí)候,能通過(guò)屬性傳入一些值,來(lái)影響最終的顯示結(jié)果。

我們?cè)谧鲰?xiàng)目中經(jīng)常會(huì)遇到的一個(gè)情況:一張圖片加一個(gè)文本的組合。比如充值賬戶成功之后顯示的一個(gè)界面,上面是一個(gè)表示成功的圖標(biāo),下面是對(duì)應(yīng)的說(shuō)明文字:“充值成功”。或者是在登錄界面的賬戶輸入框中,輸入框的左邊需要顯示一個(gè)表示賬戶的圖標(biāo)。如下所示:

圖標(biāo)文字組合的笨重實(shí)現(xiàn)

一開(kāi)始對(duì)于這樣的情況,我們可能會(huì)采用ImageView加TextView的方式。后來(lái)通過(guò)lint工具的提示,或者是其他的方式,你可能會(huì)知道TextView的幾個(gè)屬性drawableLeft,drawableRight,drawableTop以及drawableBottom可以做到。但是使用的時(shí)候,你會(huì)發(fā)現(xiàn)這幾個(gè)屬性設(shè)置進(jìn)去的圖片,是按其本身大小來(lái)顯示的。
好像也沒(méi)關(guān)系,讓設(shè)計(jì)師切好圖就是了。但是心里卻是沒(méi)底的。因?yàn)锳ndroid手機(jī)萬(wàn)萬(wàn)種,你公司的測(cè)試機(jī)卻只有那兩三個(gè),也許換上某個(gè)大屏低分辨率的千元機(jī),圖標(biāo)就被撐大了。所以你還是希望能設(shè)定圖片的大小。

使用一個(gè)TextView實(shí)現(xiàn)

設(shè)定一個(gè)TextView的drawable大小,可以通過(guò)在java代碼中調(diào)用drawable的setBounds(int left, int top, int right, int bottom)方法設(shè)置它的界限,然后調(diào)用setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)方法把我們的drawable對(duì)象設(shè)置進(jìn)去。
但是每次調(diào)用都要設(shè)置未免太麻煩,所以我們可以繼承TextView寫(xiě)一個(gè)DrawableTextView,重寫(xiě)setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom)方法;或者是setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom),如果你是通過(guò)drawableStart及drawableEnd屬性來(lái)設(shè)置圖片的話。通過(guò)在這里對(duì)drawable進(jìn)行setBounds(),也一樣能達(dá)到上面的效果。
現(xiàn)在我們用一個(gè)TextView實(shí)現(xiàn)了上面TextView+ImageView的效果,達(dá)到了我們的目的:優(yōu)化布局性能,簡(jiǎn)化布局代碼。
但是對(duì)于這樣的控件,我們可能在項(xiàng)目的多個(gè)地方用到,或者在其他項(xiàng)目也會(huì)用到。所以希望能把它做到更通用。這時(shí)我們就不能寫(xiě)死drawable的寬和高,而是希望能夠在外部xml使用它時(shí)進(jìn)行控制,也就是——自定義屬性。

自定義屬性

首先在res/values/attrs.xml文件中(如果沒(méi)有請(qǐng)創(chuàng)建)定義一個(gè)declare-styleable,然后在里面定義兩個(gè)屬性,分別表示drawable的寬和高:

<declare-styleable name="DrawableTextView"><attr name="drawableHeight" format="dimension"/><attr name="drawableWidth" format="dimension"/> </declare-styleable>

其中declare-styleable的名字name通常寫(xiě)為我們的控件的類名,這樣在寫(xiě)布局代碼中,Android Studio就可以給我們對(duì)應(yīng)的屬性提示了。
在attr中定義的是我們的屬性,name是屬性的名字,format是屬性值的格式,這里我們定義為dimension。

屬性是定義好了,也可以布局代碼中使用了。但是我們還需要在我們的自定義的DrawableTextView中讀取屬性。首先重寫(xiě)構(gòu)造方法:

public DrawableTextView(Context context) {super(context);}public DrawableTextView(Context context, AttributeSet attrs) {super(context, attrs);applyAttributes(context, attrs);}public DrawableTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);applyAttributes(context, attrs);}

然后在里面調(diào)用我們自定義的applyAttributes()方法,在里面我們會(huì)讀取到屬性。我們需要在我們的類中聲明兩個(gè)屬性:

private int mDrawableWidth;private int mDrawableHeight;

然后在applyAttributes()方法中,通過(guò)TypedArray獲取屬性值:

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DrawableTextView);mDrawableWidth = typedArray.getDimensionPixelSize(R.styleable.DrawableTextView_drawableWidth, 0);mDrawableHeight = typedArray.getDimensionPixelSize(R.styleable.DrawableTextView_drawableHeight, 0);typedArray.recycle();

這里說(shuō)明一下,attrs是我們?cè)趚ml中定義的相關(guān)聯(lián)的屬性集。通過(guò)調(diào)用context.obtainStyledAttributes(attrs, R.styleable.DrawableButton);,我們能夠接收到在Context所對(duì)應(yīng)的theme中我們的樣式屬性,也就是這里的屬性值我們也可以通過(guò)在theme中來(lái)設(shè)置。關(guān)于通過(guò)在theme中指定屬性值,后續(xù)的博客會(huì)再詳細(xì)說(shuō)明,這里暫略不談。第二個(gè)參數(shù)傳的是我們所定義的declare-styleable
得到TypedArray對(duì)象之后,通過(guò)它里面的getXXX方法我們可以得到各個(gè)屬性的值,比如通過(guò)getDimensionPixelSize(int index, int defValue)方法得到屬性尺寸對(duì)應(yīng)的像素大小。第一個(gè)參數(shù)是屬性的索引,第二個(gè)是默認(rèn)值。在獲取完屬性之后,必須調(diào)用typedArray.recycle()對(duì)它進(jìn)行回收,以便后面的調(diào)用者可以復(fù)用。因?yàn)镽esources對(duì)象中會(huì)緩存一些TypedArray的數(shù)據(jù),TypedArray使用的時(shí)候會(huì)從中獲取,以優(yōu)化內(nèi)存利用。

拿到屬性值并賦給我們的成員變量之后,我們就可以在后面的方法進(jìn)行設(shè)置了。由于本篇主要講自定義屬性,關(guān)于該項(xiàng)目的后續(xù)實(shí)現(xiàn),可以參考我在Github上的項(xiàng)目 DrawableWidget。

上面的例子中,關(guān)于在attrs定義屬性其實(shí)是存在著問(wèn)題的。因?yàn)槲覀冎苯泳投x了drawableWidth及drawableHeight屬性,如果我有一個(gè)項(xiàng)目使用到它,并且同時(shí)使用了另外一個(gè)庫(kù),那個(gè)庫(kù)也定義了這兩個(gè)屬性的話,就會(huì)產(chǎn)生沖突了。所以要強(qiáng)調(diào)一點(diǎn):對(duì)于自定義屬性,必須加上我們自己的前綴。比如把屬性定義為nbDrawableWidth等等。(我那個(gè)項(xiàng)目在寫(xiě)的時(shí)候還不成熟,而且自己有些懶,沒(méi)遇到問(wèn)題總是不想改,暫且留作反例吧。)

共用屬性

還有一種情況。我們?cè)诓季掷飼?huì)經(jīng)常遇到這樣一種情況:

在布局里面的每一個(gè)條目,會(huì)用分割線分開(kāi)。而這些條件還會(huì)分成幾組,組里面的分割線是有左邊距的。這樣的情況很好實(shí)現(xiàn),重寫(xiě)這個(gè)layout,在onDraw里面畫(huà)線就可以了。我們把右邊的每一個(gè)item看成是:上面一條滿的分割線或者是不帶分割線,下面是一條帶邊距的分割線,或者是滿的分割線。這樣我們就可以定義一個(gè)pwBorder屬性,里面定義<flag name="TOP" value="1"/>``<flag name="BOTTOM" value="2"/>表示標(biāo)記位。然后在代碼里獲取pwBorder的值,與1做&操作,大于0就表示要畫(huà)上面的分割線,否則不畫(huà),再和2做&操作,大于0就表示畫(huà)完整的分割線,否則畫(huà)帶邊距的分割線。如果需要左分割線或右分割線時(shí),還可以再定義值為4或者8的標(biāo)志位。
在xml引用它時(shí),屬性是這樣的:

app:pwBorder="TOP|BOTTOM"

但是,可能除了這個(gè)RelativeLayout需要這種屬性之外,我們?cè)趯?xiě)的其他控件,可能也要包括這個(gè)屬性以及其他屬性。這時(shí)我們可以把a(bǔ)ttr的定義抽出來(lái),寫(xiě)在declare-styleable節(jié)點(diǎn)外面。如下:

<!--帶邊框的Layout屬性--><attr name="pwBorder"><flag name="TOP" value="1"/><flag name="BOTTOM" value="2"/></attr><attr name="pwBorderWidth" format="dimension"/><attr name="pwBorderColor" format="color"/>

然后再這樣使用:

<declare-styleable name="BorderLinearLayout"><attr name="pwBorder"/><attr name="pwBorderWidth"/><attr name="pwBorderColor"/></declare-styleable><declare-styleable name="TextFieldView"><attr name="pwBorder"/><attr name="pwBorderWidth"/><attr name="pwBorderColor"/><attr name="pwLabel"/><attr name="pwValue" format="string"/><attr name="pwIcon" format="reference"/></declare-styleable>

我建議使用這種方式來(lái)定義屬性。因?yàn)檫@樣當(dāng)我們的屬性與其他庫(kù)的屬性正好重名時(shí),如果定義的format相同,也是可以被合并,并且通過(guò)編譯的。

本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/maosidiaoxian/article/details/50009725

總結(jié)

以上是生活随笔為你收集整理的Android开发技巧——自定义控件之自定义属性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。