Android自定义控件(二)

来源:互联网 发布:如何快速升淘宝等级 编辑:程序博客网 时间:2024/06/06 00:21

上篇文章通过继承view定义了一个圆形控件,在界面上绘制一个圆形,并且根据不同的测量模式设置了不同的大小:自定义控件(一) 。但是我们定义的圆形在界面设计时半径、颜色都已经固定了,本文主要总结如何像原生控件一样,通过在xml文件中设置属性来控制圆形的半径以及颜色,并在圆形中心显示一段文字


首先要定义控件的属性名称,在values文件夹中新建attrs.xml文件,声明属性的名称和类型:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="myView">        <attr name="Text" format="string"/>        <attr name="TextColor" format="color"/>        <attr name="CircleColor" format="color"/>        <attr name="Radius" format="dimension"/>        <attr name="TextSize" format="dimension"/>    </declare-styleable></resources>


这里定义了文字、文字颜色、半径、圆形颜色、文字大小等属性, format用来指定属性的类型。

      系统提供了TypedArray数据结构来获取自定义属性值,通过TypedArray对象的getString()、getColor()等方法就可以获得xml中设置的属性值,需要注意的是获取完属性值后需要调用TypedArray的recycle方法来完成资源的回收:

TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.myView);        mCircleText = ta.getString(R.styleable.myView_Text);        mCircleColor = ta.getColor(R.styleable.myView_CircleColor,0);        mTextColor = ta.getColor(R.styleable.myView_TextColor,0);        radius = ta.getDimension(R.styleable.myView_Radius,50);        mTextSize = ta.getDimension(R.styleable.myView_TextSize,15);        ta.recycle();

获取到属性之后,通过Paint 的setcolor、setTextSize等函数定义画笔,就可以在屏幕上进行绘制了,我们要实现在圆形绘制一段文字,所以在onDraw中绘制完圆形后,通过调用drawText方法绘制文字,使用这个方法时需要注意参数的含义:

canvas.drawText(text,x,y,paint)


(1)text: 表示要绘制的文字内容

(2)x:表示对齐位置,通过调用paint的setTextAlign(Align align)方法,设置文字的对齐标准,Paint.Align.Center:以中心对齐,Paint.Align.LEFT以左边界对齐,Paint.Align.RIGHT以右边界对齐。

(3)y:表示字符baseline 的位置,这里需要特别注意,y不表示文字中心的高度,而表示文字基线的高度,基线是位于文字下方的,就像在直线上写英文字母一样,那条横线叫做基线。

(2)paint:是绘制的画笔


我们在以圆心位置对齐,绘制文字,所以x以中心对齐,设置宽对齐位置为圆心的位置,若要使文字的中心和圆心重合,需要使文字的基线在圆心下方Text.height()/2的高度才能保证,通过获取问题的外接矩形就可以方便的知道文字的高,从而设置y的大小:

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        Rect bounds = new Rect();        mTextPaint.getTextBounds(mCircleText,0,mCircleText.length(),bounds);        canvas.drawCircle(width/2,height/2,radius,mPaint);        canvas.drawText(mCircleText,width/2,height/2+bounds.height()/2,mTextPaint);    }


这样就可以通过xml设置属性,来改变控件的大小、颜色以及文字,但是在设置前,一定要记得引用第三方空间的名字空间,在布局文件中可以看到:

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


xmlns即xml namespace,指定命名空间为android,所以在使用系统属性的时候可以使用android:来引用系统的属性,自定义的属性就需要创建自己的命名空间,AS中使用如下代码引入命名空间:

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


将第三方名字空间取名为custom,然后使用自定义属性:

<my.project.ViewTest.myView        android:layout_width="match_parent"        android:layout_height="200dp"        custom:Text="my circle"        custom:TextColor="#33ff00"        custom:Radius="50dp"        custom:CircleColor="#993300"        custom:TextSize="20sp"        />

效果图如下:



myView源码:

public class myView extends View {    private int mCircleColor;    private String mCircleText = "defuat";    private int mTextColor;    private float mTextSize;    private TypedArray ta ;    private float radius = 50;    private Paint mPaint,mTextPaint;    public myView(Context context) {        super(context);        init(context);    }    public myView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        ta = context.obtainStyledAttributes(attrs,R.styleable.myView);        init(context);    }    public myView(Context context, AttributeSet attrs) {        super(context, attrs);        ta = context.obtainStyledAttributes(attrs,R.styleable.myView);        init(context);    }    private void init(Context context){        mCircleText = ta.getString(R.styleable.myView_Text);        mCircleColor = ta.getColor(R.styleable.myView_CircleColor,0);        mTextColor = ta.getColor(R.styleable.myView_TextColor,0);        radius = ta.getDimension(R.styleable.myView_Radius,50);        mTextSize = ta.getDimension(R.styleable.myView_TextSize,15);        mPaint = new Paint();        mTextPaint = new Paint();        mTextPaint.setTextAlign(Paint.Align.CENTER);        mTextPaint.setTextSize(mTextSize);        mPaint.setColor(mCircleColor);        mTextPaint.setColor(mTextColor);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getWidth();        int height = getHeight();        Rect bounds = new Rect();        mTextPaint.getTextBounds(mCircleText,0,mCircleText.length(),bounds);        canvas.drawCircle(width/2,height/2,radius,mPaint);        canvas.drawText(mCircleText,width/2,height/2+bounds.height()/2,mTextPaint);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthMeasured,heightMeasured;        widthMeasured = measureWidth(widthMeasureSpec);        heightMeasured = measureHeight(heightMeasureSpec);        setMeasuredDimension(widthMeasured,heightMeasured);    }    private int measureHeight(int measureSpec){        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if(specMode == MeasureSpec.EXACTLY){            result = specSize;        }else{            result = 200;            if(specMode == MeasureSpec.AT_MOST){                result = Math.min(result,specSize);            }        }        return result;    }    private int measureWidth(int measureSpec){        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if(specMode == MeasureSpec.EXACTLY){            result = specSize;        }else{            result = 200;            if(specMode == MeasureSpec.AT_MOST){                result = Math.min(result,specSize);            }        }        return result;    }}


原创粉丝点击