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

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

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


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

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

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值