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等這樣的寫法,其實冒號前面的單詞並不重要,重要的是後面引號中的內容,前面的單詞可以任意取名,我們在最開始指定了這樣一句代碼:
xmlns:app="http://schemas.android.com/apk/res-auto"
包括系統自動爲我們添加的這一句代碼:
xmlns:android="http://schemas.android.com/apk/res/android"
正是這兩句代碼的存在,才使得我們能夠使用android、app這樣的標籤,爲什麼呢?
<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
獲取的值,如果是值是@的資源,那麼引用都變成了@+數字的字符串。
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>
注意,這裏我們是使用已經定義好的屬性,不需要去添加format屬性(注意聲明和使用的區別,差別就是有沒有format)。
然後在類中這麼獲取:ta.getString(R.styleable.test_android_text);佈局文件中直接android:text="@string/hello_world"即可。
declare-styleable的標籤也可以不寫
<?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數組,數組中的元素就是我們想要獲取的attr的id。並且我們根據元素的在數組中的位置,定義了一些整形的常量代表其下標,然後通過TypedArray
進行獲取。