自定义控件一

来源:互联网 发布:舆情指数算法 编辑:程序博客网 时间:2024/05/22 15:52

        自定义控件主要分成三种,1.完全自定义的控件;2.对当前的控件进行扩展;3.对当前的控件组合。

        首先看第一种,完全自定义控件。以MyCircleImageView为例来说明自定义控件的创建方法。

先来看看MyCircleImageView 的效果,如下图所示,将一幅图片显示为圆形,并可以在边缘加上自己设定的颜色。

S70108-123602

        创建的过程大致分为以下几步:

        1)创建MyCircleImageView类继承自View,并提供初始化函数

public class MyCircleImageView extends View{      public MyCircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public MyCircleImageView(Context context, AttributeSet attrs) {        super(context, attrs);        //初始化    }    public MyCircleImageView(Context context) {        super(context);    }}

 

       2)自定义属性

        在MyCircleView当中,设置了三个自定义的属性,分别是图片资源、边缘宽度、边缘颜色。

自定义属性写在attr.xml文件当中。

    <declare-styleable name="MyCircleImageView">        <attr name="imageSrc" format="reference"/>        <attr name="borderWidth" format="dimension"/>        <attr name="borderColor" format="color"/>    </declare-styleable>

       3)在XML布局文件当中引入自定义属性

        引入自定义属性的时候还必须加入自定义属性的命名空间,如下图所示

Catch

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

然后就可以在view当中加入自定义属性了

    <com.example.a.circleimage.MyCircleImageView        android:id="@+id/top"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:layout_marginLeft="10dp"        custom:imageSrc="@drawable/mycatch"        custom:borderColor="@color/yellow"        custom:borderWidth="10dp"/>

        4)在代码当中读取XML文件当中的属性,初始化View

    private void initAttrs(AttributeSet attrs){        if(attrs!=null){            TypedArray array = null;            try{                //读取属性                array = getContext().obtainStyledAttributes(attrs,R.styleable.MyCircleImageView);                this.mDrawable = array.getDrawable(R.styleable.MyCircleImageView_imageSrc);                this.mBorderWidth = array.getDimension(R.styleable.MyCircleImageView_borderWidth,0);                this.mBorderColor = array.getInt(R.styleable.MyCircleImageView_borderColor, 0);                this.mesureDrawable();            }catch (Exception e){                e.printStackTrace();            }        }    }

        5)测量View的尺寸

        首先看一下设置View尺寸的三种模式,如下表所示

模式类型

说明

EXACTLY

对应于match_parent或者具体的数值

AT_MOST

对应于wrap_content

UNSPECIFIED

开发人员可以按照自己的意愿设置成任何大小,应用比较少

       复写父类的onMeasure()方法,并且只有当模式为EXACTLY时,宽高才从MeasureSpec当中取,其他模式则宽高设置成图片的宽高。

    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //获取宽度的模式和大小        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        //获取高度的模式和大小        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int height = MeasureSpec.getSize(heightMeasureSpec);        //设置view的宽和高        this.setMeasuredDimension(this.measureWidth(widthMode,width),this.measureHeight(heightMode,height));    }    private int measureWidth(int mode ,int width){        switch (mode){            case MeasureSpec.UNSPECIFIED:                break;            case MeasureSpec.AT_MOST:                break;            case MeasureSpec.EXACTLY:                this.mWidth = width;                break;        }        return mWidth;    }    private int measureHeight(int mode , int height){        switch (mode){            case MeasureSpec.UNSPECIFIED:                break;            case MeasureSpec.AT_MOST:                break;            case MeasureSpec.EXACTLY:                this.mHeight = height;                break;        }        return mHeight;    }

         6)绘制View

         复写ondraw()函数,将所得到的图片绘制成为圆形,并在外层添加颜色边缘。

@Override    protected void onDraw(Canvas canvas) {        if(mBitmap == null){            mBitmap = Bitmap.createScaledBitmap(drawableToBitmap(mDrawable),                                                 getMeasuredWidth(),                                                 getMeasuredHeight(),                                                 true);        }        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,                Shader.TileMode.CLAMP);        this.mPaint.setShader(bitmapShader);        this.mPaint.setStyle(Paint.Style.FILL);        float x = mBitmap.getWidth()/2.0f;        float y = mBitmap.getHeight()/2.0f;        float radiu = Math.min(x,y);        canvas.drawCircle(x,y,radiu,mPaint);        if(this.mBorderColor!=0 && this.mBorderWidth!=0){            Paint borderPaint = new Paint();            borderPaint.setColor(this.mBorderColor);            borderPaint.setStyle(Paint.Style.STROKE);            borderPaint.setStrokeWidth(mBorderWidth);            borderPaint.setAntiAlias(true);            canvas.drawCircle(x,y,radiu+1-mBorderWidth/2.0f,borderPaint);        }    }

完整的源码如下:

public class MyCircleImageView extends View {    private Paint mPaint;//画笔    private Drawable mDrawable;//图片    private int mWidth;//宽度    private int mHeight;//高度    private Bitmap mBitmap;    private int mBorderColor;//边框颜色    private float mBorderWidth;//边框宽度    public MyCircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public MyCircleImageView(Context context, AttributeSet attrs) {        super(context, attrs);        this.initAttrs(attrs);        this.mPaint = new Paint();        this.mPaint.setAntiAlias(true);//抗锯齿    }    public MyCircleImageView(Context context) {        super(context);    }    private void initAttrs(AttributeSet attrs){        if(attrs!=null){            TypedArray array = null;            try{                //读取属性                array = getContext().obtainStyledAttributes(attrs,R.styleable.MyCircleImageView);                this.mDrawable = array.getDrawable(R.styleable.MyCircleImageView_imageSrc);                this.mBorderWidth = array.getDimension(R.styleable.MyCircleImageView_borderWidth,0);                this.mBorderColor = array.getInt(R.styleable.MyCircleImageView_borderColor, 0);                this.mesureDrawable();            }catch (Exception e){                e.printStackTrace();            }        }    }    //测量控件的大小    public void mesureDrawable(){        if(this.mDrawable!=null){            this.mHeight = this.mDrawable.getIntrinsicHeight();            this.mWidth = this.mDrawable.getIntrinsicWidth();        }    }    @Override    protected void onDraw(Canvas canvas) {        if(mBitmap == null){            mBitmap = Bitmap.createScaledBitmap(drawableToBitmap(mDrawable),                                                 getMeasuredWidth(),                                                 getMeasuredHeight(),                                                 true);        }        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,                Shader.TileMode.CLAMP);        this.mPaint.setShader(bitmapShader);        this.mPaint.setStyle(Paint.Style.FILL);        float x = mBitmap.getWidth()/2.0f;        float y = mBitmap.getHeight()/2.0f;        float radiu = Math.min(x,y);        canvas.drawCircle(x,y,radiu,mPaint);        if(this.mBorderColor!=0 && this.mBorderWidth!=0){            Paint borderPaint = new Paint();            borderPaint.setColor(this.mBorderColor);            borderPaint.setStyle(Paint.Style.STROKE);            borderPaint.setStrokeWidth(mBorderWidth);            borderPaint.setAntiAlias(true);            canvas.drawCircle(x,y,radiu+1-mBorderWidth/2.0f,borderPaint);        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        //获取宽度的模式和大小        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        //获取高度的模式和大小        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int height = MeasureSpec.getSize(heightMeasureSpec);        //设置view的宽和高        this.setMeasuredDimension(this.measureWidth(widthMode,width),this.measureHeight(heightMode,height));    }    private int measureWidth(int mode ,int width){        switch (mode){            case MeasureSpec.UNSPECIFIED:                break;            case MeasureSpec.AT_MOST:                break;            case MeasureSpec.EXACTLY:                this.mWidth = width;                break;        }        return mWidth;    }    private int measureHeight(int mode , int height){        switch (mode){            case MeasureSpec.UNSPECIFIED:                break;            case MeasureSpec.AT_MOST:                break;            case MeasureSpec.EXACTLY:                this.mHeight = height;                break;        }        return mHeight;    }    //将drawable转换成bitmap    public Bitmap drawableToBitmap(Drawable drawable) {        Bitmap bitmap = Bitmap.createBitmap(                drawable.getIntrinsicWidth(),                drawable.getIntrinsicHeight(),                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888                        : Bitmap.Config.RGB_565);        Canvas canvas = new Canvas(bitmap);        canvas.setBitmap(bitmap);        drawable.setBounds(0, 0,  drawable.getIntrinsicWidth() ,drawable.getIntrinsicHeight());        drawable.draw(canvas);        return bitmap;    }}
0 0
原创粉丝点击