Android學習之 自定義屬性及TypedArray的用法
一、 背景說明:
在xml檔案裡定義控制元件的屬性,我們用的最多的是 Android系統自帶的屬性如:
<ImageView android:id="@+id/iv_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@null" android:src="@drawable/ic_ms_quick_order" />
這裡小呂將自我學習與分享如何自定義屬性<通常在自定義控制元件中會被使用到>,在xml佈局檔案中 如:
說明:1. 上面的MyMenuButton 是我自定義的一個選單按鈕控制元件 <圖片和文字的組合控制元件>。<!-- 搜尋 --> <com.ice.view.menubutton.MyMenuButton xmlns:ice="http://schemas.android.com/apk/res/com.ice.view.menubutton" android:id="@+id/btn_search" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" ice:menuIcon="@drawable/ic_ms_search" ice:menuText="@string/ms_search" ice:textSize="14sp" ice:textColor="@color/orange" ice:btnCode="search" />
2. xmlns:ice=http://schemas.android.com/apk/res/com.ice.view.menubutton
是我自定義的名稱空間 名稱空間的名字可以自己隨便定義 ,這裡我定義的是ice 及 xmlns:ice 。
注意:
後面的地址則有限制,
其開始必須為:"http://schemas.android.com/apk/res/",後面則是包名com.ice.view.menubutton,
此處的包名與AndroidManifest.xml中
<manifest>節點的屬性package="com.ice.view.menubutton"一致,不是自定義控制元件Java程式碼所在的包。
3. menuIcon / menuText / textSize / textColor / btnCode 就是我自定義的屬性。
<只針對自定義控制元件 MyMenuButton有效>。
二、關於該自定義控制元件的開發和xml佈局檔案的配置大致步驟如下:
1、首先在res/values檔案下定義一個attrs.xml檔案.定義控制元件的自定義屬性集合 程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name ="MyMenuButton">
<!-- 圖示 -->
<attr name="menuIcon" format="reference" />
<!-- 文字 -->
<attr name="menuText" format="reference" />
<!-- 文字大小 -->
<attr name="textSize" format="dimension" />
<!-- 字型顏色 -->
<attr name="textColor" format="color" />
<!-- 頁面編號 -->
<attr name="btnCode">
<flag name="quickOrder" value="0"></flag>
<flag name="orderManager" value="1"></flag>
<flag name="favorite" value="2"></flag>
<flag name="search" value="3"></flag>
</attr>
</declare-styleable>
</resources>
說明: 1.declare-styleable 是定義自定義屬性集合名稱的節點元素
2.format可選項
"reference"//引用
"color"//顏色
"boolean"//布林值
"dimension"//尺寸值
"float"//浮點值
"integer"//整型值
"string"//字串
"fraction"//百分數,比如200%
3.元素節點 attr 定義各自定義屬性名稱 format用來定義屬性值的型別值,可以指定多種型別值如:
<attr name = "background" format ="reference|color" />
4.列舉值,格式如下:
<attrn ame="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
xml中使用時:
android:orientation= "vertical"
5.標誌位,位或運算,格式如下:
<!-- 頁面編號 -->
<attr name="btnCode">
<flag name="quickOrder" value="0"></flag>
<flag name="orderManager" value="1"></flag>
<flag name="favorite" value="2"></flag>
<flag name="search" value="3"></flag>
</attr>
Xml中使用時:
ice:btnCode="search"
2.在res/layout檔案下新建自定義控制元件的xml佈局檔案:ms_menu_button.xml 程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:background="@null" >
<!-- 圖示 -->
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_ms_quick_order" />
<!-- 文字 -->
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ms_quick_order" />
</LinearLayout>
</RelativeLayout>
3.自定義控制元件java類:MyMenuButton.java <核心程式碼>
package com.ice.view.menubutton;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* 自定義 選單按鈕
* @author ice
*
*/
public class MyMenuButton extends RelativeLayout {
private static final String TAG = "MyMenuButton";
RelativeLayout relativeLayout;
ImageView iv_icon;
TextView tv_text;
private Drawable menuIcon;
private CharSequence menuText;
private float textSize;
private int textColor;
private int btnCode;
private static final int PAGE_CODE_QUICK_ORDER = 0; // 快速訂單
private static final int PAGE_CODE_ORDER_MANAGER = PAGE_CODE_QUICK_ORDER + 1; // 訂單管理
private static final int PAGE_CODE_FAVORITE = PAGE_CODE_ORDER_MANAGER + 1; // 我的收藏
private static final int PAGE_CODE_SEARCH = PAGE_CODE_FAVORITE + 1; // 快速查詢
public MyMenuButton(Context context) {
this(context,null);
}
public MyMenuButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyMenuButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Log.d(TAG, "自定義元件構造方法MyMenuButton(...) invoke");
// 獲取所有自定義屬性組
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyMenuButton, defStyle, 0);
// 獲取自定義元件所在佈局檔案中的自定義屬性值
menuIcon = typedArray.getDrawable(R.styleable.MyMenuButton_menuIcon);
menuText = typedArray.getText(R.styleable.MyMenuButton_menuText);
// 設定當沒有設定textSize屬性值時 預設字型大小為14px 注意這裡的單位是px
textSize = typedArray.getDimension(R.styleable.MyMenuButton_textSize, 14);
textColor = typedArray.getInt(R.styleable.MyMenuButton_textColor, 0XFFFFFFFF);
btnCode = typedArray.getInt(R.styleable.MyMenuButton_btnCode, PAGE_CODE_QUICK_ORDER);
relativeLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.ms_menu_button, this, true);
// TypedArray 通常最後呼叫 .recycle() 方法,為了保持以後使用該屬性一致性!
typedArray.recycle();
}
/**
* 當View中所有的子控制元件均對映成XML後觸發
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
Log.d(TAG, "onFinishInflate invoke");
iv_icon = (ImageView) relativeLayout.findViewById(R.id.iv_icon);
tv_text = (TextView) relativeLayout.findViewById(R.id.tv_text);
iv_icon.setImageDrawable(menuIcon);
tv_text.setText(menuText);
tv_text.setTextColor(textColor);
tv_text.setTextSize(textSize);
Log.d(TAG, "menuText: "+menuText+" | textSize: "+textSize);
this.setOnClickListener(new OnClickEvent());
}
class OnClickEvent implements OnClickListener{
@Override
public void onClick(View v) {
switch (btnCode) {
case PAGE_CODE_QUICK_ORDER:
Log.d(TAG, "快速下單MenuButton被點選");
break;
case PAGE_CODE_ORDER_MANAGER:
Log.d(TAG, "訂單管理MenuButton被點選");
break;
case PAGE_CODE_FAVORITE:
Log.d(TAG, "我的收藏MenuButton被點選");
break;
case PAGE_CODE_SEARCH:
Log.d(TAG, "搜尋MenuButton被點選");
break;
}
}
}
}
4.測試展示Activity:MainActivity.java 程式碼如下:
package com.ice.view.menubutton;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "Before setContentView()...");
setContentView(R.layout.activity_main);
Log.d(TAG, "After setContentView()...");
}
}
5.測試展示佈局檔案:activity_main.xml 程式碼如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/bg_ms_menu"
android:gravity="bottom"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<!-- 快速下單 -->
<com.ice.view.menubutton.MyMenuButton
xmlns:ice="http://schemas.android.com/apk/res/com.ice.view.menubutton"
android:id="@+id/btn_quick_order"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
ice:menuIcon="@drawable/ic_ms_quick_order"
ice:menuText="@string/ms_quick_order"
ice:textColor="@android:color/black"
ice:btnCode="quickOrder"/>
<!-- 訂單管理 -->
<com.ice.view.menubutton.MyMenuButton
xmlns:ice="http://schemas.android.com/apk/res/com.ice.view.menubutton"
android:id="@+id/btn_order_manager"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
ice:menuIcon="@drawable/ic_ms_order_manager"
ice:menuText="@string/ms_order_manager"
ice:textColor="@color/green"
ice:btnCode="orderManager" />
<!-- 我的收藏 -->
<com.ice.view.menubutton.MyMenuButton
xmlns:ice="http://schemas.android.com/apk/res/com.ice.view.menubutton"
android:id="@+id/btn_my_favorite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
ice:menuIcon="@drawable/ic_ms_my_favorite"
ice:menuText="@string/ms_my_favorite"
ice:textColor="@color/red"
ice:textSize="14px"
ice:btnCode="favorite" />
<!-- 搜尋 -->
<com.ice.view.menubutton.MyMenuButton
xmlns:ice="http://schemas.android.com/apk/res/com.ice.view.menubutton"
android:id="@+id/btn_search"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
ice:menuIcon="@drawable/ic_ms_search"
ice:menuText="@string/ms_search"
ice:textSize="14sp"
ice:textColor="@color/orange"
ice:btnCode="search" />
</LinearLayout >
6.執行效果:
--------------》 哈哈 這裡搜尋menuButton怎麼那麼另類呢、呵呵 這是小呂故意的 詳細請看activity_main.xml和MyMenuButton.java程式碼說明。
7.點選自定義選單控制元件 後臺日誌資訊如下:
說明:這裡我們可以看到自定義元件、onFinishInflate()方法的執行情況。