Android自定义控件:如何使用自定义的XML属性

原著网址:http://m.blog.csdn.net/blog/u013716863/37662943     http://m.blog.csdn.net/blog/u013716863/37663325

 

 

什么是自定义XML属性

在我们使用自定义的控件时,很多时候都需要定义一些不同于一般的XML属性前缀(如android:layout_width)的属性,比如这样 app:textColor,这些就是自定义控件需要用到的自定义控件属性。

 

自定义XML属性有什么用

自定义XML属性的作用在于,在采取自定义的控件时,很多时候,系统的一般XML属性已经不能满足需求,比如我们在做一个具有描边效果的TextView时,就需要有额外定义的TextView外边框颜色和TextView内部颜色两种颜色。这时候,使用自定义XML属性,用户就可以很方便地在XML中配置额外的属性。

 

怎么使用自定义XML属性

1.定义对应的属性

values文件夹下新建一个attar_custom.xml文件:

<?xml version="1.0" encoding="utf-8"?>  

<resources>  

    <!-- 自定义控件的名称 -->  

    <declare-styleable name="StrokeTextView">  

        <!-- 自定义的属性名称 和对应的单位 -->  

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

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

    </declare-styleable>  

</resources>  

2.XML中定义自定义属性  

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

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

    android:layout_width="match_parent"  

    android:layout_height="match_parent"  

    >  

  

    <com.example.demo.StrokeTextView  

        android:layout_width="wrap_content"  

        android:layout_height="wrap_content"  

        android:text="@string/hello_world"   

        android:textSize="28sp"  

        app:outerColor="#000000"  

        app:innnerColor="#ffffff"  

        android:layout_centerInParent="true"/>  

  

</RelativeLayout>  

注意,自定义的XML属性必须给自定义的控件使用  

3.使用自定义的XML属性  

public StrokeTextView(Context context, AttributeSet attrs) {  

super(context, attrs);  

m_TextPaint = this.getPaint();  

//获取自定义的XML属性名称  

TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.StrokeTextView);  

//获取对应的属性值  

this.mInnerColor = a.getColor(R.styleable.StrokeTextView_innnerColor,0xffffff);  

this.mOuterColor = a.getColor(R.styleable.StrokeTextView_outerColor,0xffffff);  

 

案例:  

效果图  


源码  

1.定义XML属性:

<resources>  

    <!-- 自定义控件的名称 -->  

    <declare-styleable name="StrokeTextView">  

        <!-- 自定义的属性名称 和对应的单位 -->  

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

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

    </declare-styleable>  

</resources>  

2.使用XML定义描边TextView的属性

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  

    xmlns:tools="http://schemas.android.com/tools"  

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

    android:layout_width="match_parent"  

    android:layout_height="match_parent"  

    >  

  

    <com.example.demo.StrokeTextView  

        android:layout_width="wrap_content"  

        android:layout_height="wrap_content"  

        android:text="@string/hello_world"   

        android:textSize="28sp"  

        app:outerColor="#000000"  

        app:innnerColor="#ffffff"  

        android:layout_centerInParent="true"/>  

  

</RelativeLayout>  

3.重绘TextView

public class StrokeTextView extends TextView {  

  

    TextPaint m_TextPaint;  

    int mInnerColor;  

    int mOuterColor;  

      

    public StrokeTextView(Context context,int outerColor,int innnerColor) {  

        super(context);  

        m_TextPaint = this.getPaint();  

        this.mInnerColor = innnerColor;  

        this.mOuterColor = outerColor;  

          

        // TODO Auto-generated constructor stub  

    }  

  

    public StrokeTextView(Context context, AttributeSet attrs) {  

        super(context, attrs);  

        m_TextPaint = this.getPaint();  

        //获取自定义的XML属性名称  

        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.StrokeTextView);  

        //获取对应的属性值  

        this.mInnerColor = a.getColor(R.styleable.StrokeTextView_innnerColor,0xffffff);  

        this.mOuterColor = a.getColor(R.styleable.StrokeTextView_outerColor,0xffffff);  

          

    }  

  

    public StrokeTextView(Context context, AttributeSet attrs, int defStyle,int outerColor,int innnerColor) {  

        super(context, attrs, defStyle);  

        m_TextPaint = this.getPaint();  

        this.mInnerColor = innnerColor;  

        this.mOuterColor = outerColor;  

        // TODO Auto-generated constructor stub  

    }  

  

    private boolean m_bDrawSideLine = true; // 默认采用描边  

  

    /**  

     *   

     */  

    @Override  

    protected void onDraw(Canvas canvas) {  

        if (m_bDrawSideLine) {  

            // 描外层  

            // super.setTextColor(Color.BLUE); // 不能直接这么设,如此会导致递归  

            setTextColorUseReflection(mOuterColor);  

            m_TextPaint.setStrokeWidth(5); // 描边宽度  

            m_TextPaint.setStyle(Style.FILL_AND_STROKE); // 描边种类  

            m_TextPaint.setFakeBoldText(true); // 外层text采用粗体  

            m_TextPaint.setShadowLayer(1, 0, 0, 0); // 字体的阴影效果,可以忽略  

            super.onDraw(canvas);  

  

            // 描内层,恢复原先的画笔  

  

            // super.setTextColor(Color.BLUE); // 不能直接这么设,如此会导致递归  

            setTextColorUseReflection(mInnerColor);  

            m_TextPaint.setStrokeWidth(0);  

            m_TextPaint.setStyle(Style.FILL_AND_STROKE);  

            m_TextPaint.setFakeBoldText(false);  

            m_TextPaint.setShadowLayer(0, 0, 0, 0);  

              

        }  

        super.onDraw(canvas);  

    }  

  

    /**  

     * 使用反射的方法进行字体颜色的设置  

     * @param color  

     */  

    private void setTextColorUseReflection(int color) {  

        Field textColorField;  

        try {  

            textColorField = TextView.class.getDeclaredField("mCurTextColor");  

            textColorField.setAccessible(true);  

            textColorField.set(this, color);  

            textColorField.setAccessible(false);  

        } catch (NoSuchFieldException e) {  

            e.printStackTrace();  

        } catch (IllegalArgumentException e) {  

            e.printStackTrace();  

        } catch (IllegalAccessException e) {  

            e.printStackTrace();  

        }  

        m_TextPaint.setColor(color);  

    }  

  

}  

 

 

 




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值