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布局文件中 如:

<!-- 搜索 -->
     <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" />
        说明:1. 上面的MyMenuButton 是我自定义的一个菜单按钮控件  <图片和文字的组合控件>。

                  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.运行效果:

Android学习之 自定义属性及TypedArray的用法_第1张图片

--------------》 哈哈  这里搜索menuButton怎么那么另类呢、呵呵  这是小吕故意的   详细请看activity_main.xml和MyMenuButton.java代码说明。

        7.点击自定义菜单控件  后台日志信息如下:

Android学习之 自定义属性及TypedArray的用法_第2张图片

说明:这里我们可以看到自定义组件、onFinishInflate()方法的运行情况。




最后 附上本篇源码地址:http://download.csdn.net/detail/l416112167/7549299


你可能感兴趣的:(android,自定义属性)