Android自定义控件及属性

来源:互联网 发布:香港 收音机软件 推荐 编辑:程序博客网 时间:2024/06/07 03:57

在开发中,现有的控件并不能完全满足我们的需求,往往需要我们去进行自定义控件的设计。

在这里我们先了解一个属性,attrs中发 format。

format有多种可选值设置:

1. reference:参考某一资源ID。

(1)属性定义:

<declare-styleable name = "名称">

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

</declare-styleable>

(2)属性使用:

<ImageView

android:layout_width = "42dip"

android:layout_height = "42dip"

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 = "42dip"

android:layout_height = "42dip"

android:background = "@drawable/图片ID|#00FF00"/>


接下来我们就可以正式进行XML属性的自定义了

一、在res/values/attrs文件中定义属性

<declare-styleable name="PasswordInputView">        <!--边框圆角值-->        <attr name="pivBorderRadius" format="dimension"/>        <!--边框颜色-->        <attr name="pivBorderColor" format="color|reference"/>        <!--边框宽度-->        <attr name="pivBorderWidth" format="dimension"/>        <!--圆角尺寸-->        <attr name="pivPasswordRadius" format="dimension"/>        <!--密码颜色-->        <attr name="pivPasswordColor" format="color"/>        <!--密码大小-->        <attr name="pivPasswordWidth" format="dimension"/>        <!--密码长度-->        <attr name="pivPasswordLength" format="integer"/>        <!--密码文本-->        <attr name="pivTextSize" format="dimension"/>        <attr name="pivTextColor" format="color"/>        <attr name="pivIsPass" format="boolean"/>    </declare-styleable>

二、定义MyView继承View与自定义属性相关联(在构造方法中关联)

public PasswordInputView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordInputView, 0, 0);        borderColor = a.getColor(R.styleable.PasswordInputView_pivBorderColor, borderColor);        borderWidth = a.getDimension(R.styleable.PasswordInputView_pivBorderWidth, borderWidth);        borderRadius = a.getDimension(R.styleable.PasswordInputView_pivBorderRadius, borderRadius);        passwordLength = a.getInt(R.styleable.PasswordInputView_pivPasswordLength, passwordLength);        passwordColor = a.getColor(R.styleable.PasswordInputView_pivPasswordColor, passwordColor);        passwordWidth = a.getDimension(R.styleable.PasswordInputView_pivPasswordWidth, passwordWidth);        passwordRadius = a.getDimension(R.styleable.PasswordInputView_pivPasswordRadius, passwordRadius);        textSize = (int) a.getDimension(R.styleable.PasswordInputView_pivTextSize, textSize);        textColor = a.getColor(R.styleable.PasswordInputView_pivTextColor, textColor);        isPass = a.getBoolean(R.styleable.PasswordInputView_pivIsPass, isPass);        a.recycle();        borderPaint.setStrokeWidth(borderWidth);        borderPaint.setColor(borderColor);        passwordPaint.setStrokeWidth(passwordWidth);        passwordPaint.setStyle(Paint.Style.FILL);        passwordPaint.setColor(passwordColor);        InputFilter[] filters = {new InputFilter.LengthFilter(passwordLength)};        setFilters(filters);    }

注意:为防止使用时属性值未设置,在初始化时将个属性进行默认值的设定


PasswordInputView的具体代码如下

package com.laobai.view;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.text.InputFilter;import android.text.TextUtils;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.TypedValue;import android.widget.EditText;import com.laobai.R;import static android.graphics.Paint.ANTI_ALIAS_FLAG;/***改控件为自定义的密码输入框,可设置明文及密码*/@SuppressLint("AppCompatCustomView")public class PasswordInputView extends EditText {    private static final int defaultContMargin = 5;    private static final int defaultSplitLineWidth = 3;    /**     * 边框颜色     */    private int borderColor = 0xFFCCCCCC;    private float borderWidth = 2;    private float borderRadius = 0;    private int passwordLength = 4;    private int passwordColor = 0xFFCCCCCC;    private float passwordWidth = 8;    private float passwordRadius = 3;    int textSize = 15;    int textColor = Color.BLACK;    boolean isPass = true;    private Paint passwordPaint = new Paint(ANTI_ALIAS_FLAG);    private Paint borderPaint = new Paint(ANTI_ALIAS_FLAG);    private int textLength;    String passText;    public PasswordInputView(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordInputView, 0, 0);        borderColor = a.getColor(R.styleable.PasswordInputView_pivBorderColor, borderColor);        borderWidth = a.getDimension(R.styleable.PasswordInputView_pivBorderWidth, borderWidth);        borderRadius = a.getDimension(R.styleable.PasswordInputView_pivBorderRadius, borderRadius);        passwordLength = a.getInt(R.styleable.PasswordInputView_pivPasswordLength, passwordLength);        passwordColor = a.getColor(R.styleable.PasswordInputView_pivPasswordColor, passwordColor);        passwordWidth = a.getDimension(R.styleable.PasswordInputView_pivPasswordWidth, passwordWidth);        passwordRadius = a.getDimension(R.styleable.PasswordInputView_pivPasswordRadius, passwordRadius);        textSize = (int) a.getDimension(R.styleable.PasswordInputView_pivTextSize, textSize);        textColor = a.getColor(R.styleable.PasswordInputView_pivTextColor, textColor);        isPass = a.getBoolean(R.styleable.PasswordInputView_pivIsPass, isPass);        a.recycle();        borderPaint.setStrokeWidth(borderWidth);        borderPaint.setColor(borderColor);        passwordPaint.setStrokeWidth(passwordWidth);        passwordPaint.setStyle(Paint.Style.FILL);        passwordPaint.setColor(passwordColor);        InputFilter[] filters = {new InputFilter.LengthFilter(passwordLength)};        setFilters(filters);    }    @Override    protected void onDraw(Canvas canvas) {        int width = getWidth();        int height = getHeight();        // 外边框        RectF rect = new RectF(0, 0, width, height);        borderPaint.setColor(borderColor);        canvas.drawRoundRect(rect, borderRadius, borderRadius, borderPaint);        // 内容区        RectF rectIn = new RectF(rect.left + defaultContMargin, rect.top + defaultContMargin,                rect.right - defaultContMargin, rect.bottom - defaultContMargin);        borderPaint.setColor(Color.WHITE);        canvas.drawRoundRect(rectIn, borderRadius, borderRadius, borderPaint);        // 分割线        borderPaint.setColor(borderColor);        borderPaint.setStrokeWidth(defaultSplitLineWidth);        for (int i = 1; i < passwordLength; i++) {            float x = width * i / passwordLength;            canvas.drawLine(x, 0, x, height, borderPaint);        }        float cx, cy = height / 2;        float half = width / passwordLength / 2;        if (isPass) {            // 密码            for (int i = 0; i < textLength; i++) {                cx = width * i / passwordLength + half;                canvas.drawCircle(cx, cy, passwordWidth, passwordPaint);            }        } else {            passwordPaint.setTextSize(textSize);            passwordPaint.setColor(textColor);            passwordPaint.setTextAlign(Paint.Align.CENTER);            Paint.FontMetrics fontMetrics = passwordPaint.getFontMetrics();            float top = fontMetrics.top;//为基线到字体上边框的距离,即上图中的top            float bottom = fontMetrics.bottom;//为基线到字体下边框的距离,即上图中的bottom            int baseLineY = (int) (rect.centerY() - top / 2 - bottom / 2);//基线中间点的y轴计算公式            if (!TextUtils.isEmpty(passText)) {                for (int i = 0; i < textLength; i++) {                    cx = width * i / passwordLength + half;                    canvas.drawText(String.valueOf(passText.charAt(i)), cx, baseLineY, passwordPaint);                }            }        }    }    @Override    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {        super.onTextChanged(text, start, lengthBefore, lengthAfter);        passText = text.toString();        textLength = passText.length();        invalidate();    }    public int getBorderColor() {        return borderColor;    }    public void setBorderColor(int borderColor) {        this.borderColor = borderColor;        borderPaint.setColor(borderColor);        invalidate();    }    public float getBorderWidth() {        return borderWidth;    }    public void setBorderWidth(float borderWidth) {        this.borderWidth = borderWidth;        borderPaint.setStrokeWidth(borderWidth);        invalidate();    }    public float getBorderRadius() {        return borderRadius;    }    public void setBorderRadius(float borderRadius) {        this.borderRadius = borderRadius;        invalidate();    }    public int getPasswordLength() {        return passwordLength;    }    public void setPasswordLength(int passwordLength) {        this.passwordLength = passwordLength;        invalidate();    }    public int getPasswordColor() {        return passwordColor;    }    public void setPasswordColor(int passwordColor) {        this.passwordColor = passwordColor;        passwordPaint.setColor(passwordColor);        invalidate();    }    public float getPasswordWidth() {        return passwordWidth;    }    public void setPasswordWidth(float passwordWidth) {        this.passwordWidth = passwordWidth;        passwordPaint.setStrokeWidth(passwordWidth);        invalidate();    }    public float getPasswordRadius() {        return passwordRadius;    }    public void setPasswordRadius(float passwordRadius) {        this.passwordRadius = passwordRadius;        invalidate();    }    public void setIsPass(boolean isPass){        this.isPass = isPass;        invalidate();    }    public void setTextSize(int textSize){        this.textSize = textSize;        invalidate();    }    public void setTextColor(int textColor){        this.textColor = textColor;        invalidate();    }}

三、XML布局文件中的应用

要使用自定义属性必须加上前缀:xmlns:app="http://schemas.android.com/apk/res-auto"

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@color/backcolor_white"    android:gravity="center_horizontal"    android:orientation="vertical">    <com.view.PasswordInputView        android:id="@+id/code_edit"        android:layout_width="270dp"        android:layout_height="45dp"        android:layout_marginTop="10dp"        android:inputType="number"        android:lines="1"        android:visibility="gone"        app:pivBorderColor="#dddddd"        app:pivBorderWidth="0.5dp"        app:pivIsPass="false"        app:pivPasswordLength="6"        app:pivPasswordWidth="10dp"        app:pivTextColor="#333333"        app:pivTextSize="@dimen/sp_text_16"        tools:text="125635"        tools:visibility="visible" /></LinearLayout>