Android 自定義view(二) —— attr 使用


前言:

attr 在前一篇文章《Android 自定義view —— attr理解》已經簡單的進行了介紹和創建,那么這篇文章就來一步步說說attr的簡單使用吧

自定義view簡單實現步驟

(1)首先創建attrs自定義屬性文件名稱,定義屬性以及相關數據類型

(2)再次創建自定義view,然后讀取相關屬性完成需要的view相關布局、繪制等工作

(3)最后在xml布局文件中引用或者直接在代碼中new一個相關對象進行使用

任務需求

為了能夠簡單的練習演示attr 相關使用,我現在自己規定了如下需求

(1)定義view,將需要的屬性定義在 attr 中

(2)在自定義view中 顯示文字、文字顏色、文字背景、文字大小

(3)在xml中引用或者在代碼中new一個對象進行使用

實現任務

為了方便理解,我將編寫順序進行調整

我的目錄結構:

{307E782C-32E1-203C-5024-B707D1016893}

 

第一步:先來看看我們的自定義屬性以及相關數據類型 attrs_ysj.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--name 是自定義屬性名,一般采用駝峰命名,可以隨意。 format 是屬性的單位-->
    <attr name="viewText" format="string" />
    <attr name="viewTextColor" format="color" />
    <attr name="viewTextSize" format="dimension" />
    <!--name 是自定義控件的類名-->
    <declare-styleable name="YText">
        <attr name="viewText" />
        <attr name="viewTextColor" />
        <attr name="viewTextSize" />
        <!--注意:一般情況是按照上面這樣寫,把屬性單獨定義在上面,然后在styleable這里面引用,但是我要裝一下逼,就單獨混寫在里面了下,取值的時候就需要單獨去取名稱才能取到值不然是取不到值-->
        <attr name="viewTextBg" format="color" />
    </declare-styleable>
</resources>

注意:關於attr里面的屬性定義或者理解有疑惑請移步《Android 自定義view —— attr理解

第二步:再次來看看XML布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--引用自定義view必須是包名.類名-->
    <com.boyoi.ysj.custom.one.view.YView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:viewText="這是我的自定義View"
        custom:viewTextColor="@android:color/holo_red_dark"
        custom:viewTextBg="@android:color/holo_blue_dark"
        custom:viewTextSize="18sp" />
</LinearLayout>

哈哈在看了xml還是先來補補點小知識點(很多時候會暈的,特別是面試這些小知識點搞不好你還真說不清楚)——命名空間中的 res/android 和 res-auto

xmlns:android=http://schemas.android.com/apk/res/android
xmlns:customview=http://schemas.android.com/apk/res-auto

注意:這2個實際上前者是就是讓你引用系統自帶屬性的,后者是讓你使用lib庫里自定義屬性的。但是這個地方要注意,在eclipse中如果要使用你自定義的屬性 是不能用res-auto的必須得替換成你自定義view所屬的包名,如果你在恰好使用的自定義屬性被做成了lib那就只能使用res-auto了,而在android-studio里,無論你是自己寫自定義view還是引用的lib里的自定義的view 都只能使用res-auto這個寫法。以前那個包名的寫法在android-studio里是被廢棄無法使用的。

第三步:最后讓我們來看看我們是怎么自定義view

/**
* Created by yishujun on 16/6/3.
*/
public class YView extends View {
    private Context mContext;
    //文本
    private String mText;
    //文本的顏色
    private int mTextColor;
    //文本的大小
    private int mTextSize;
    //文本的背景
    private int mTextBg;
    //繪制時控制文本繪制的范圍
    private Rect mBound;
    //繪制文本畫筆
    private Paint mPaint;
    public YView(Context context) {
        this(context, null);
    }
    public YView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public YView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        typedYView(attrs, defStyleAttr);
    }
    /**
     * 獲得我們所定義的自定義樣式屬性
     *
     * @param attrs
     * @param defStyleAttr
     */
    private void typedYView(AttributeSet attrs, int defStyleAttr) {
        //獲得我們所定義的自定義樣式屬性
        //final Resources.Theme theme = mContext.getTheme();
        //TypedArray a = theme.obtainStyledAttributes(attrs,R.styleable.YText, defStyleAttr, 0);
        //獲取自定義屬性值的方式一般情況分為兩種:styleable組 和 直接獲取attr屬性
        //這里獲取的屬性用的styleable組,同時我也建議用這種方式方便規范attrs文件,
        //另外一種獲取方式如下,當然也可以一個個獲取屬性值,這里不再演示
        //int[] custom = {R.attr.viewText, R.attr.viewTextSize};
        //TypedArray a = mContext.obtainStyledAttributes(attrs, custom);
        TypedArray a = mContext.getTheme().obtainStyledAttributes(attrs, R.styleable.YText, defStyleAttr, 0);
        int n = a.getIndexCount();
        for (int i = 0; i <= n; i++) {
            int attr = a.getIndex(i);
            switch (attr) {
                //注意獲取屬性的方式為 styleable的名稱_屬性名稱
                case R.styleable.YText_viewText:
                    mText = a.getString(attr);
                    break;
                case R.styleable.YText_viewTextColor:
                    // 默認顏色設置為黑色
                    mTextColor = a.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.YText_viewTextSize:
                    // 默認設置為16sp,TypeValue也可以把sp轉化為px
                    mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 18, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.YText_viewTextBg:
                    // 默認顏色設置為黃色
                    mTextBg = a.getColor(attr, Color.YELLOW);
                    //但是在這里上面的那種取值方式就是取不到值哦,因為返回后的attr沒有YText_viewTextBg,原因是因為我剛裝逼了一下,所以我們要單獨去取值
                    break;
            }
        }
        //記得在這里單獨取出文本的背景mTextBg值哦,因為上面的mTextBg取不到值哦
        mTextBg = a.getColor(R.styleable.YText_viewTextBg, Color.YELLOW);
        //回收資源
        a.recycle();
        //新建畫筆對象
        mPaint = new Paint();
        //設置畫筆
        mPaint.setTextSize(mTextSize);
        mBound = new Rect();
        //設置畫筆繪制文字及相關區域
        mPaint.getTextBounds(mText, 0, mText.length(), mBound);
        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mText = "你摸了我一下";
                //刷新畫布
                postInvalidate();
            }
        });
    }
    @Override
    protected void onDraw(Canvas canvas) {
        //設置畫布顏色即文字背景色
        mPaint.setColor(mTextBg);
        //繪制背景,全屏
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
        //設置文字顏色
        mPaint.setColor(mTextColor);
        //繪制文字
        canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
    }
}

 

運行效果:

{D6C7159B-5814-C1AB-CE26-D64914D389F9}{093B4F7C-8D33-92C1-FE50-861E0A7F2C66}

 

總結:

怎樣一個簡單的自定義view不就完成了嘛,是不是看起來很簡單,對的是很簡單,但是對我來說還有很多東西是需要去深究那么


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM