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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發布時間:2024/4/13 Android 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android开发技巧——自定义控件之自定义属性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android開發技巧——自定義控件之自定義屬性

掌握自定義控件是很重要的,因為通過自定義控件,能夠:解決UI問題,優化布局性能,簡化布局代碼

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

我們在做項目中經常會遇到的一個情況:一張圖片加一個文本的組合。比如充值賬戶成功之后顯示的一個界面,上面是一個表示成功的圖標,下面是對應的說明文字:“充值成功”。或者是在登錄界面的賬戶輸入框中,輸入框的左邊需要顯示一個表示賬戶的圖標。如下所示:

圖標文字組合的笨重實現

一開始對于這樣的情況,我們可能會采用ImageView加TextView的方式。后來通過lint工具的提示,或者是其他的方式,你可能會知道TextView的幾個屬性drawableLeft,drawableRight,drawableTop以及drawableBottom可以做到。但是使用的時候,你會發現這幾個屬性設置進去的圖片,是按其本身大小來顯示的。
好像也沒關系,讓設計師切好圖就是了。但是心里卻是沒底的。因為Android手機萬萬種,你公司的測試機卻只有那兩三個,也許換上某個大屏低分辨率的千元機,圖標就被撐大了。所以你還是希望能設定圖片的大小。

使用一個TextView實現

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

自定義屬性

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

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

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

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

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);}

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

private int mDrawableWidth;private int mDrawableHeight;

然后在applyAttributes()方法中,通過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();

這里說明一下,attrs是我們在xml中定義的相關聯的屬性集。通過調用context.obtainStyledAttributes(attrs, R.styleable.DrawableButton);,我們能夠接收到在Context所對應的theme中我們的樣式屬性,也就是這里的屬性值我們也可以通過在theme中來設置。關于通過在theme中指定屬性值,后續的博客會再詳細說明,這里暫略不談。第二個參數傳的是我們所定義的declare-styleable
得到TypedArray對象之后,通過它里面的getXXX方法我們可以得到各個屬性的值,比如通過getDimensionPixelSize(int index, int defValue)方法得到屬性尺寸對應的像素大小。第一個參數是屬性的索引,第二個是默認值。在獲取完屬性之后,必須調用typedArray.recycle()對它進行回收,以便后面的調用者可以復用。因為Resources對象中會緩存一些TypedArray的數據,TypedArray使用的時候會從中獲取,以優化內存利用。

拿到屬性值并賦給我們的成員變量之后,我們就可以在后面的方法進行設置了。由于本篇主要講自定義屬性,關于該項目的后續實現,可以參考我在Github上的項目 DrawableWidget。

上面的例子中,關于在attrs定義屬性其實是存在著問題的。因為我們直接就定義了drawableWidth及drawableHeight屬性,如果我有一個項目使用到它,并且同時使用了另外一個庫,那個庫也定義了這兩個屬性的話,就會產生沖突了。所以要強調一點:對于自定義屬性,必須加上我們自己的前綴。比如把屬性定義為nbDrawableWidth等等。(我那個項目在寫的時候還不成熟,而且自己有些懶,沒遇到問題總是不想改,暫且留作反例吧。)

共用屬性

還有一種情況。我們在布局里會經常遇到這樣一種情況:

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

app:pwBorder="TOP|BOTTOM"

但是,可能除了這個RelativeLayout需要這種屬性之外,我們在寫的其他控件,可能也要包括這個屬性以及其他屬性。這時我們可以把attr的定義抽出來,寫在declare-styleable節點外面。如下:

<!--帶邊框的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>

我建議使用這種方式來定義屬性。因為這樣當我們的屬性與其他庫的屬性正好重名時,如果定義的format相同,也是可以被合并,并且通過編譯的。

本文原創,轉載請注明出處:http://blog.csdn.net/maosidiaoxian/article/details/50009725

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。