Android中自定義屬性attrs.xml、TypedArray的使用

由於Android系統給TextView、EditText等空間提供的drawableLeft的屬性無法設置Gravity,系統默認居中,這樣無法到達項目中需要的效果。

下面這張圖是用的系統的drawableLeft屬性所展現出的效果


這樣是無法進行調整圖片位置的,比如我的項目需求是圖片居上的


如圖,如果是這樣的系統的drawableLeft屬性是無法滿足的。

如果要實現這樣的效果可以加一個Imaview控件,但有時候還需要再外面在套一層LinearLayout或RelativeLayout。

當然還有另外一種方法:就是Android中自定義屬性。


上圖就是我們想要的Android中自定義屬性的使用方式。

廢話不多說了,上代碼:

一、首先在values文件夾下創建一個attrs.xml文件,來設置自定義屬性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextViewDrawable">
        <attr name="leftResourceId" format="reference"></attr>//左側圖片
        <attr name="leftGravity">//圖片Gravity
            <flag name="leftTop" value="0" />
            <flag name="leftBottom" value="1" />
            <flag name="leftCenter" value="2" />
        </attr>
        <attr name="text" format="string"></attr>
        <attr name="textGravity">//文字Gravity
            <flag name="textLeftTop" value="0"/>
            <flag name="textLeftBottom" value="1"/>
            <flag name="textRightTop" value="2"/>
            <flag name="textRightBottom" value="3"/>
            <flag name="textCenter" value="4" />
            <flag name="textCenterHorizontal" value="5" />
            <flag name="textCenterVertical" value="6" />
        </attr>
    </declare-styleable>
</resources>
這裏要先說明下format="reference"裏面format的值

1. reference:參考某一資源ID。

(1)屬性定義:

<declare-styleable name = "名稱">

<attr name = "background" format = "reference" />

</declare-styleable>

(2)屬性使用:

<ImageView

android:layout_width = "wrap_content"

android:layout_height = "wrap_content"

android:background = "@drawable/圖片ID"

/>


2. color:顏色值


<declare-styleable name = "名稱">

<attr name = "textColor" format = "color" />

</declare-styleable>


3. boolean:布爾值


<declare-styleable name = "名稱">

<attr name = "focusable" format = "boolean" />

</declare-styleable>


4. dimension:尺寸值。


<declare-styleable name = "名稱">

<attr name = "layout_width" format = "dimension" />

</declare-styleable>


5. float:浮點值。


6. integer:整型值。


7. string:字符串


8. fraction:百分數。


9. enum:枚舉值


10. flag:位或運算


注意:

屬性定義時可以指定多種類型值。

(1)屬性定義:

<declare-styleable name = "名稱">

<attr name = "background" format = "reference|color" />

</declare-styleable>

(2)屬性使用:

<ImageView

android:layout_width = "wrap_content"

android:layout_height = "wrap_content"

android:background = "@drawable/圖片ID|#000000"

/>


二、創建一個MyTextView類,繼承RelativeLayout

package xu.dyso.com.mytextview;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * Created by xu on 2017/3/2.
 */

public class MyTextView extends RelativeLayout {

    /**
     * 圖片資源ID
     */
    private int imageResourceId;
    /**
     * 圖片的Gravity
     */
    private int leftGravity;
    /**
     * 文字的內容
     */
    private String text="";
    /**
     * 文字的Gravity
     */
    private int textGravity;
    /**
     * ImageView控件
     */
    private ImageView leftView;
    /**
     * 圖片控件
     */
    private TextView textView;
    /**
     * 圖片和文字的LayoutParams屬性
     */
    private LayoutParams leftParams,textParams;

    private Context mContext;

    public MyTextView(Context context) {
        super(context);
        this.mContext = context;
        initView(context, null);
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        initView(context, attrs);
    }

    public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        initView(context, attrs);
    }

    /**
     * 初始化
     * @param context
     * @param attrs
     */
    private void initView(Context context, AttributeSet attrs) {
        /**
         * 通過TypeArray獲取到attrs裏的自定義屬性
         */
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextViewDrawable);
        /**
         * 圖片資源ID賦值
         */
        imageResourceId = typedArray.getResourceId(R.styleable.TextDrawable_leftResourceId, 0);
        leftView = new ImageView(context);
        /**
         * 圖片屬性初始化
         */
        leftParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        /**
         * 設置圖片位於父控件裏面偏左側
         */
        leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,RelativeLayout.TRUE);
        /**
         * 圖片Gravity賦值,默認居中
         */
        leftGravity = typedArray.getInteger(R.styleable.TextDrawable_leftGravity, 2);
        switch (leftGravity){
            case 0://左上
                leftParams.addRule(RelativeLayout.ALIGN_PARENT_TOP,RelativeLayout.TRUE);
                break;
            case 1://左下
                leftParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
                break;
            case 2://左中
                leftParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
                break;
            default:
                leftParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
                break;
        }
        /**
         * 給該控件設置ID值,後面用來設置第二個控件位置
         */
        leftView.setId(R.id.left_iv);
        addView(leftView,leftParams);

        if (imageResourceId > 0) {
            leftView.setImageResource(imageResourceId);
        }

        textView=new TextView(context);
        /**
         * 文字屬性初始化
         */
        textParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        /**
         * 文字位置設置,位於leftView右側
         */
        textParams.addRule(RelativeLayout.RIGHT_OF,leftView.getId());
        /**
         * 文字內容賦值
         */
        text=typedArray.getString(R.styleable.TextDrawable_text);
        textView.setText(text);
        /**
         * 文字Gravity賦值,默認居中
         */
        textGravity=typedArray.getInteger(R.styleable.TextDrawable_textGravity,4);
        /**
         * 因爲textParams設置的屬性是LayoutParams.MATCH_PARENT,所以TextView的Gravity設置只好用textView.setGravity(int gravity);
         * 當然textParams也可以設置爲LayoutParams.WRAP_CONTENT,然後通過textParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);這樣來設置
         */
        switch (textGravity){
            case 0:
                textView.setGravity(Gravity.TOP);
                break;
            case 1:
                textView.setGravity(Gravity.BOTTOM);
                break;
            case 2:
                textView.setGravity(Gravity.TOP|Gravity.RIGHT);
                break;
            case 3:
                textView.setGravity(Gravity.BOTTOM|Gravity.RIGHT);
                break;
            case 4:
                textView.setGravity(Gravity.CENTER);
                break;
            case 5:
                textView.setGravity(Gravity.CENTER_HORIZONTAL);
                break;
            case 6:
                textView.setGravity(Gravity.CENTER_VERTICAL);
                break;
            default:
                textView.setGravity(Gravity.CENTER);
                break;
        }
        addView(textView,textParams);
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
這裏要注意下

leftView.setId(int ID)的時候,在Android Studio中不能像Eclipse中那樣直接leftView.setId(1);

而是要在values文件夾下新建一個ids.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="left_iv" type="id">1</item>
</resources>
否則會空指針錯誤。

三、在Layout界面中引用自定義屬性

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:mytextview="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <xu.dyso.com.mytextview.MyTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        mytextview:leftResourceId="@mipmap/iv_remark"
        mytextview:leftGravity="leftTop"
        mytextview:text="這是一段\n測試文字\n這是一段\n測試文字"
        mytextview:textGravity="textLeftTop"/>
</LinearLayout>
注意別忘了在根節點添加
xmlns:mytextview="http://schemas.android.com/apk/res-auto"

這個mytextview是自己起的名字,你可以隨便起。


源碼下載


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章