自定义view初探--闹钟的实现

来源:互联网 发布:java io 编辑:程序博客网 时间:2024/06/03 12:39

研究过一段时间自定义视图,下面我们来实现一个比较常见的功能----闹钟。

废话不多说,先上效果图:


从上图可以看见,帆布作为底层画布,我们需要画一个大钟圆圈,画俩条直线作为指针,问题是俩个铃铛怎么画?

这里我们可以用到俩种方法:

1.图层覆盖

2. PorterDuffXfermode混合模式


针对上面的思路我们给出相应的代码:

1.使用图层覆盖

公共类AlarmClock的扩展视图{私人涂料粉刷;私人路径路径;公众的AlarmClock(上下文的背景下,ATTRS的AttributeSet,诠释defStyleAttr){超(背景下,ATTRS,defStyleAttr);在里面();}公众的AlarmClock(上下文的背景下,ATTRS的AttributeSet){超(背景下,ATTRS);在里面();}公众的AlarmClock(上下文的背景下){超级(上下文);在里面();}私人无效的init(){油漆=新的油漆();paint.setColor(Color.WHITE);paint.setStyle(Style.FILL);paint.setAntiAlias(真);paint.setStrokeWidth(30);}@覆盖保护无效的onDraw(帆布油画){super.onDraw(画布);// 1.画出左右俩个圆canvas.drawColor(Color.RED);canvas.drawCircle(200,100,100,油漆);canvas.drawCircle(500,100,100,油漆);canvas.save();// INT SC = canvas.saveLayer(0,0,600,800,空,canvas.ALL_SAVE_FLAG);// 2.画出红色圆乙paint.setColor(Color.RED);canvas.drawCircle(350,300,270,油漆);canvas.save();// 3.再画出底下一个大圆Çpaint.setColor(Color.WHITE);canvas.drawCircle(350,300,250,油漆);canvas.save();// 4.在画出红色小圆ðpaint.setColor(Color.RED);canvas.drawCircle(350,300,200,油漆);canvas.save();// 5.在小圆上画出直线路径paint.setColor(Color.WHITE);浮动[] PTS = {350,150,350,300};浮[] PTS1 = {335,300,500,300};canvas.drawLines(PTS,油漆);canvas.drawLines(PTS1,油漆);canvas.save();canvas.restore();}}
上面使用方法比较简单,代码直观,我们不细说了。看第二种方式




2.使用PorterDuffXfermode混合模式


公共类AlarmClock的扩展视图{    私人诠释宽度= 400,高度= 400; //定义绘图区域    私人位图srcBitmap,dstBitmap;    私人涂料mPaint;    私人诠释的centerX,centerY; //中心点    私人诠释largerRadius,smallRadius; //大小圆的半径    私有静态最终诠释DISTANCE_X = 40,DISTANCE_Y = 60; //设置绘制线条的长度    私人INT strokeWidth = 16;    公众的AlarmClock(上下文的背景下){        超级(上下文);        在里面();    }    公众的AlarmClock(上下文的背景下,ATTRS的AttributeSet){        超(背景下,ATTRS);        在里面();    }    公众的AlarmClock(上下文的背景下,ATTRS的AttributeSet,诠释defStyleAttr){        超(背景下,ATTRS,defStyleAttr);        在里面();    }    私人无效的init(){        的centerX =宽度/ 2;        centerY =身高/ 2;        largerRadius =宽/ 4;        smallRadius =宽/ 8;        mPaint =新的油漆();        srcBitmap = creatBitMapSrc();        dstBitmap = creatBitMapDst();    }    @覆盖    保护无效的onDraw(帆布油画){        super.onDraw(画布);        canvas.drawBitmap(srcBitmap,0,0,mPaint); //首先绘制的Src图,做为底图,因为在使用XOR模式后,源所在区域会被截取,使用SRC_OUT同样可以实现        INT layerId的= canvas.saveLayer(0,0,宽* 2,身高* 2,mPaint,Canvas.ALL_SAVE_FLAG); //创建新的图层        canvas.drawBitmap(srcBitmap,0,0,mPaint);        mPaint.setXfermode(新PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));        canvas.drawBitmap(dstBitmap,0,0,mPaint);        mPaint.setXfermode(NULL);        canvas.restoreToCount(layerId的);    }    / **     *创建源图     * @返回     * /    私人位图creatBitMapSrc(){        位图的位图= Bitmap.createBitmap(宽度,高度,Bitmap.Config.ARGB_8888);        帆布C =新的Canvas(位图);        涂料mPaint =新的油漆();        mPaint.setColor(0xffffcc22);        c.drawCircle(的centerX,centerY,largerRadius + 20,mPaint); //首先以背景色填充画圆// c.drawOval(新RectF(80,80,宽度80,高度80),mPaint);        mPaint.setColor(为0xffffffff);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(strokeWidth);        c.drawCircle(的centerX,centerY,largerRadius,mPaint); //绘制一个无填充的圆,半径比填充的圆小一些// c.drawOval(新RectF(100,100,宽度100,高度100),mPaint); //以矩形区域画椭圆,同样可以实现,效果一样        c.drawLine(的centerX,centerY,的centerX + DISTANCE_X,centerY,mPaint); //绘制横向距离为40的线条        c.drawLine(的centerX,centerY + strokeWidth / 2的centerX,centerY-DISTANCE_Y,mPaint); //因为画笔宽度为strokeWidth,偏移strokeWidth / 2,让两条直线完全重合纵向为60        返回位图;    }    / **     *创建目标图     * @返回     * /    私人位图creatBitMapDst(){        位图的位图= Bitmap.createBitmap(宽度,高度,Bitmap.Config.ARGB_8888);        帆布C =新的Canvas(位图);        涂料mPaint =新的油漆();        c.drawColor(0xffffcc22);        mPaint.setColor(为0xffffffff);        / **         *双重罪(双D)         *双COS(双D)         *双谭(双D)在数学中这三个方法传进去的数值不是度数,而是         *度数所对应的弧度值计算弧度值的方法有:         *         * 1。使用数学类里面的toRadians()方法         * Math.toRadians()根据度数取得相对应的弧度值         *         * 2.Math.PI代表180度所对应的弧度值,所以计算某个角度所对应的弧度值可以使用公式:         *弧度值=角度值* Math.PI / 180         * /        INT X1 =(int)的(的centerX  -  100 * Math.sin(Math.toRadians(45)));        INT Y1 =(int)的(centerY  -  100 * Math.cos(45 * Math.PI / 180));        INT X2 =(int)的(的centerX + 100 * Math.sin(Math.toRadians(45)));        INT Y2 =(int)的(centerY  -  100 * Math.cos(Math.toRadians(45)));        c.drawCircle(X1,Y1,smallRadius,mPaint); //绘制两个小圆        c.drawCircle(X2,Y2,smallRadius,mPaint);        返回位图;    }}

我们简单解释一下,利用源图像层覆盖目标图层,其次调用PorterDuff.Mode.SRC_OUT(只在源图像和目标图像不相交的地方绘制源图像)模式来达到绘制的效果。不理解的部分,代码已经注释说明。



针对上面的混合模式不是很清楚的童鞋,可以阅读这一篇:HTTP://blog.csdn.net/aigestudio/article/details/41316141。



1 0
原创粉丝点击