1. 程式人生 > >自定義控制元件屬性以及程式碼設定selectableItemBackground

自定義控制元件屬性以及程式碼設定selectableItemBackground

最近做專案的時候,需要自定義一個檢視,需要點選有水波紋效果,這個在xml中簡單:

android:background="?attr/selectableItemBackground"

可是寫自定義控制元件的時候,就需要用程式碼來獲取這個屬性了,在這之前我們需要了解一些關於自定義控制元件的知識,知道的同學可以跳過前面,直接到3

1.

首先,我們要知道怎麼獲取AttributeSet中相關的屬性,比如我定義了一個檢視RippleButton,若想在xml中有我自定義屬性的聯想,那麼就需要新增 declare-styleable,

<resources>
    <declare-styleable
name="RippleButton">
<attr name="text" format="string"/> <attr name="textColor" format="color"/> <attr name="textSize" format="dimension"/> </declare-styleable> </resources>

如上,在style中添加了這些東西,那麼在我引用我的控制元件的時候,就會出現提示了:

       <com.xunyou.xunyouapp
.view.customview.RippleButton android:layout_width="wrap_content" android:layout_height="wrap_content" app:text="立即組隊" app:textColor ="@color/colorFontMainWhite" app:textSize = "@dimen/general_font_x2"/>

2.

接下來進入正題,
設定了自定義屬性,那我們就會在程式碼中的構造方法中收到傳過來的AttributeSet,比如我們此時需要獲取我們定義的text屬性的值:

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RippleButton);
typedArray.getString(R.styleable.RippleButton_text);

重點就在於 typedArray.getString(attrid)這一步,當我們是自定義屬性的時候,系統會生成對應的attrId,格式為: R.styleable. + declare-styleable名 + _ + attr名

3.

設定selectableItemBackground
知道了原理,那麼現在問題來了,怎麼獲取selectableItemBackground中對應的attrId,這就需要使用TypeValue這個東西,它是用來解析attr屬性相關內容的

TypedValue typedValue = new TypedValue();
getContext().getTheme()
.resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true);

下面重頭戲來了,我們可以用typedValue.resourceId獲取到attr對應的id:

int[] attribute = new int[]{android.R.attr.selectableItemBackground};
        TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(typedValue.resourceId, attribute);

之後就可以從裡面獲取對應的Drawable了:

        setBackground(typedArray.getDrawable(0));

以上就是怎麼用程式碼設定selectableItemBackground的內容了,有錯誤請指出,下面附上我寫的帶水波紋的控制元件
(DensityUtil就是個dp,sp轉px的工具,網上很多)

RippleButton.java

package com.xunyou.xunyouapp.view.customview;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.design.internal.ForegroundLinearLayout;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;

import com.xunyou.xunyouapp.R;
import com.xunyou.xunyouapp.util.DensityUtil;

/**
 * Created by phc on 2016/11/10 0010.
 * 水波紋按鈕 就是在裡面加個 AppTextView
 */

public class RippleButton extends ForegroundLinearLayout {
    private AppCompatTextView mTextView;
    private final int DEFULT_TXT_COL = 0xffffffff;
    private final int DEFULT_TXT_SIZE = 16;

    public RippleButton(Context context) {
//        super(context);
        this(context, null, 0);
    }

    public RippleButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RippleButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        mTextView = new AppCompatTextView(getContext());
        mTextView.setTextColor(DEFULT_TXT_COL);
        mTextView.setTextSize(DEFULT_TXT_SIZE);
        if (attrs != null) {
            TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RippleButton);
            String texContent = typedArray.getString(R.styleable.RippleButton_text);
            float textSize = typedArray.getDimension(R.styleable.RippleButton_textSize, DensityUtil.sp2Px(getContext(), DEFULT_TXT_SIZE));
            int textColor = typedArray.getColor(R.styleable.RippleButton_textColor, DEFULT_TXT_COL);
            mTextView.setText(texContent);
            mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
            mTextView.setTextColor(textColor);
            typedArray.recycle();
        } else {
            mTextView.setTextColor(DEFULT_TXT_COL);
            mTextView.setTextSize(DEFULT_TXT_SIZE);
        }
        addView(mTextView);
        setGravity(Gravity.CENTER);
        setClickable(true);
        TypedValue typedValue = new TypedValue();
        getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true);
        int[] attribute = new int[]{android.R.attr.selectableItemBackground};
        TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(typedValue.resourceId, attribute);
        setForeground(typedArray.getDrawable(0));
        typedArray.recycle();
    }

    private void setTxtColor(int color) {
        if (mTextView != null) {
            mTextView.setTextColor(color);
        }
    }
}

style.xml

<resources>

    <declare-styleable name="RippleButton">
        <attr name="text" format="string"/>
        <attr name="textColor" format="color"/>
        <attr name="textSize" format="dimension"/>
    </declare-styleable>
    </resources>