android 自定義View 之自定義屬性

1:新建 attrs文件 目錄?res/value/attrs.xml?

?屬性類型一共有8種:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;

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

<resources>

? ? <attr name="titleText" format="string" />

? ? <attr name="titleTextSize" format="dimension" />

? ? <attr name="titleTextColor" format="color" />

? ? <attr name="image" format="reference" />

? ? <attr name="imageScaleType">

? ? ? ? <enum name="fillXY" value="0" />

? ? ? ? <enum name="center" value="1" />

? ? </attr>

? ? <declare-styleable name="CustomView">

? ? ? ? <attr name="titleText" />

? ? ? ? <attr name="titleTextSize" />

? ? ? ? <attr name="titleTextColor" />

? ? ? ? <attr name="image" />

? ? ? ? <attr name="imageScaleType" />

? ? </declare-styleable>

</resources>


2:布局中使用:

一定要引入 xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"我們的命名空間,后面的包路徑指的是項目的package? 或者? xmlns:custom="http://schemas.android.com/apk/res-auto"

xmlns的作用

xml布局中使用最多的是android:id、andorid:layout_width等形式,在我們自定義的xml中,添加了app:Text、app:TextAllow等這樣的寫法,其實冒號前面的單詞并不重要,重要的是后面引號中的內(nèi)容,前面的單詞可以任意取名,我們在最開始指定了這樣一句代碼:

? ? xmlns:app="http://schemas.android.com/apk/res-auto"

包括系統(tǒng)自動為我們添加的這一句代碼:

xmlns:android="http://schemas.android.com/apk/res/android"

正是這兩句代碼的存在,才使得我們能夠使用android、app這樣的標(biāo)簽,為什么呢?


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

? ? xmlns:tools="http://schemas.android.com/tools"

? ? xmlns:custom="http://schemas.android.com/apk/res/com.zhy.customview02"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent"

? ? android:orientation="vertical" >

<--或者聲明這個-->

<-- xmlns:custom="http://schemas.android.com/apk/res-auto"-->

? ? <com.zhy.customview02.view.CustomImageView

? ? ? ? android:layout_width="wrap_content"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:layout_margin="10dp"

? ? ? ? android:padding="10dp"

? ? ? ? custom:image="@drawable/ic_launcher"

? ? ? ? custom:imageScaleType="center"

? ? ? ? custom:titleText="hello andorid ! "

? ? ? ? custom:titleTextColor="#ff0000"

? ? ? ? custom:titleTextSize="30sp" />

</LinearLayout>


3:自定義view中使用

public class CustomView extends View {

? ? public CustomView(Context context, AttributeSet attrs) {

? ? ? ? super(context, attrs);

? ? ? ? TypedArray ta = context.obtainStyledAttributes(attrs,

? ? ? ? ? ? ? ? ? ? ? R.styleable.CustomView);

? ? ? ? String text = ta.getString(R.styleable.CustomeView_titletext);

? ? ? ? Bitmap mImage = BitmapFactory.decodeResource(getResources(),

? ? ? ? ? ? ? ? ? ? ta.getResourceId(R.styleable.CustomeView_image, 0));

? ? ? ? int? mTextSize =

? ? ? ? ? ? ? ta.getDimensionPixelSize(R.styleable.CustomeView_titleTextSize, (int)

? ? ? ? ? ? ? TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,

16, getResources().getDisplayMetrics()));

? ? ? ? ta.recycle();

? ? }

? ? public CustomView(Context context,AttributeSet attrs,int defStyleAttr){

? ? ? ? super(context, attrs,defStyleAttr);

? ? TypedArray typedArray =context.getTheme().obtainStyledAttributes(attrs,

? ? ? ? ? ? ? ? ? ? ? ? ? ? R.styleable.CustomView,defStyleAttr,0);

? }

}

4:TypedArray和AttributeSet的不同

AttributeSet中的確保存的是該View聲明的所有的屬性,并且外面的確可以通過它去獲取屬性自定義和原有的屬性

public CustomView(Context context, AttributeSet attrs) {

? ? ? ? super(context, attrs);

? ? ? ? int count = attrs.getAttributeCount();

? ? ? ? for (int i = 0; i < count; i++) {

? ? ? ? ? ? String attrName = attrs.getAttributeName(i);

? ? ? ? ? ? String attrVal = attrs.getAttributeValue(i);

? ? ? ? ? ? Log.e(TAG, "attrName = " + attrName + " , attrVal = " + attrVal);

? ? ? ? }

? ? }


通過AttributeSet可以獲得布局文件中定義的所有屬性的key和value,但通過AttributeSet獲取的值,如果是值是@的資源,那么引用都變成了@+數(shù)字的字符串。

ypedArray其實是用來簡化我們的工作的,比如上例,如果布局中的屬性的值是引用類型(比如:@dimen/dp100),如果使用AttributeSet去獲得最終的像素值,那么需要第一步拿到id,第二步再去解析id。而TypedArray正是幫我們簡化了這個過程。

貼一下:如果通過AttributeSet獲取最終的像素值的過程:

int widthDimensionId = ?attrs.getAttributeResourceValue(0, -1);

? ? ? ? Log.e(TAG, "layout_width= "+getResources().getDimension(widthDimensionId));

5:declare-styleable

直接在attrs.xml中使用android:text屬性。


? <declare-styleable name="test">

? ? ? ? <attr name="android:text" />

? ? ? ? <attr name="testAttr" format="integer" />

? ? </declare-styleable>

注意,這里我們是使用已經(jīng)定義好的屬性,不需要去添加format屬性(注意聲明和使用的區(qū)別,差別就是有沒有format)。?

然后在類中這么獲取:ta.getString(R.styleable.test_android_text);布局文件中直接android:text="@string/hello_world"即可。

declare-styleable的標(biāo)簽也可以不寫

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

<resources>

? ? <attr name="testAttr" format="integer" />

</resources>

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

<resources>

? ? <attr name="testAttr" format="integer" />

</resources>


public class MyTextView extends View {

? ? private static final String TAG = MyTextView.class.getSimpleName();

? ? private static final int[] mAttr = { android.R.attr.text, R.attr.testAttr };

? ? private static final int ATTR_ANDROID_TEXT = 0;

? ? private static final int ATTR_TESTATTR = 1;

? ? public MyTextView(Context context, AttributeSet attrs) {

? ? ? ? super(context, attrs);

? ? ? ? // ==>use typedarray

? ? ? ? TypedArray ta = context.obtainStyledAttributes(attrs, mAttr);

? ? ? ? String text = ta.getString(ATTR_ANDROID_TEXT);

? ? ? ? int textAttr = ta.getInteger(ATTR_TESTATTR, -1);

? ? ? ? //輸出 text = Hello world! , textAttr = 520

? ? ? ? Log.e(TAG, "text = " + text + " , textAttr = " + textAttr);

? ? ? ? ta.recycle();

? ? }

}


可以看到我們聲明了一個int數(shù)組,數(shù)組中的元素就是我們想要獲取的attr的id。并且我們根據(jù)元素的在數(shù)組中的位置,定義了一些整形的常量代表其下標(biāo),然后通過TypedArray進行獲取。

https://blog.csdn.net/lmj623565791/article/details/45022631

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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