自定义View之点 线 面以及绘制一个综合应用时钟
来源:互联网 发布:知乎 经典 编辑:程序博客网 时间:2024/06/06 02:06
本来前天应该整理的了,但是临时有任务给耽搁了,不过今天回过头来发现好多注意点都忘了,还是记录一下吧。
canvas绘制点,绘制线,绘制各种图形,其实这个可以说是最简单的了,也没有什么具体可以讲的,方法的参数含义基本上都可以理解,这里只说一点:圆弧或者扇形是的绘制如何确定。圆弧的绘制是这样的,他是将一个矩形(之所以不是正方形是因为也可以是椭圆的一部分)的内切圆的一部分截取出来的。那问题就是矩形如何确定呢?这里举个例子:例如所需扇形的半径为100,圆心坐标为(200,200),那么所需矩形的左上角坐标就为(100,100),右下角坐标为(300,300),我想规律已经出来了,没错就是这么算的,矩形的左上角坐标x=centerX-r,y=centerY-r ,矩形右下角坐标为 x=centerX+r y=centerY+r 。这个自己敲一下代码就看出来了。。。。其他方法,没什么好说的,自己敲一下代码就理解了,不多说了也,我把我的代码复制下来,里面也有注意的地方。
@Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.YELLOW); canvas.drawPoint(50,50,mPaint); //实心圆 圆心坐标x y 半径 r 画笔 mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(100, 100, 80, mPaint); //绘制圆弧(实心) 这里注意如何确定参数中第一个矩形的坐标如何确定,(centerX-r,centerY-r,centerX+r,centerY+r) 开始的角度 -90度为我们理解的0度方向 转过的角度 是否连接圆心 RectF oval = new RectF(0, 200, 200, 400);// canvas.drawArc(oval,-90,90,false,mPaint);//圆弧 canvas.drawArc(oval, -90, 90, true, mPaint);//扇形 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(3); RectF ov = new RectF(0, 350, 200, 550);// canvas.drawArc(ov,-90,90,true,mPaint);//扇形 canvas.drawArc(ov, -90, 90, false, mPaint);//弧线 //椭圆 canvas.drawOval(0, 650, 200, 800, mPaint); //矩形 Rect rect = new Rect(0, 850, 200, 1050); canvas.drawRect(rect, mPaint); //圆角矩形 canvas.drawRoundRect(250, 10, 450, 210, 15, 15, mPaint); // 按照path写文字 mPaint.setTextSize(DensityUtils.sp2px(getContext(), 16)); mPaint.setStrokeWidth(1); mPaint.setStyle(Paint.Style.FILL); String te = "abcdefsgeg"; Path pa = new Path(); pa.addArc(300, 500, 900, 1000, -180, 120); canvas.drawTextOnPath(te, pa, 0, 0, mPaint); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(3); Path p = new Path(); p.moveTo(500, 800); p.quadTo(650, 850, 450, 1150);//赛贝尔曲线// p.cubicTo(100,200,200,500,6200,850);//两个控制点的赛贝尔曲线 http://www.cnblogs.com/lenve/p/5865874.html canvas.drawPath(p, mPaint);
补充:看来确实是过了两天忘了很多东西,有两个重要的知识忘了记录了
1.绘制线,必须要说Paint中与线有关的参数,因为很重要,很重要
//绘制线的一些设置 mPaint.setStrokeCap(Paint.Cap.SQUARE);//Paint.Cap.BUTT 无延伸效果,是多大就多大 Paint.Cap.ROUND 延伸为圆角 Paint.Cap.SQUARE 延伸为矩形 mPaint.setStrokeJoin(Paint.Join.ROUND);//设置连接处效果 Paint.Join.BEVEL 有倒角,为直线倒角 Paint.Join.MITER 没有倒角 Paint.Join.ROUND 圆形倒角 详见:http://blog.csdn.net/abcdef314159/article/details/51720686 mPaint.setStrokeMiter(Paint.ANTI_ALIAS_FLAG);//设置画笔的倾斜度(不知有没有用) mPaint.setHinting(Paint.HINTING_OFF);//设置画笔的隐藏模式 Paint.HINTING_OFF 关闭 Paint.HINTING_ON 打开 //TODO:特殊线需要单独研究 mPaint.setPathEffect(new CornerPathEffect(2));//有时候我们需要点画线等特殊的线,这个可以设置连接线的形状 CornerPathEffect 两段线之间用圆角 DashPathEffect将线段虚线话 DiscretePathEffect打散path效果 其他效果详见 http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0120/2334.html //mPaint.setRasterizer();//设置光栅,被废弃(无需研究)下面举例说明两个参数的含义,其他可以看看里面引用的参考文章,讲的很好
mPaint.setStrokeCap(Paint.Cap.BUTT);//设置线的两端情况 默认为此状态即是多长就多长 mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(25); Path path=new Path(); path.moveTo(400,500); path.lineTo(600,500); canvas.drawPath(path,mPaint); mPaint.setStrokeCap(Paint.Cap.ROUND);//两端为圆角伸出 Path path1=new Path(); path1.moveTo(400,550); path1.lineTo(600,550); canvas.drawPath(path1,mPaint); mPaint.setStrokeCap(Paint.Cap.SQUARE);//两端为矩形伸出 Path path2=new Path(); path2.moveTo(400,600); path2.lineTo(600,600); canvas.drawPath(path2,mPaint); mPaint.setStrokeCap(Paint.Cap.BUTT); mPaint.setStrokeJoin(Paint.Join.BEVEL);//设置线与线的连接方式,此参数表示直切,还有圆角,直角,默认为直角 Path path3=new Path(); path3.moveTo(400,650); path3.lineTo(600,650); path3.lineTo(600,750); canvas.drawPath(path3,mPaint);效果就是最后第二张图片中的几条大粗线。
2.绘制点线面,不得不说一个path函数,非常非常重要 参见:http://www.cnblogs.com/lenve/p/5865874.html
下面开始绘制一个大家都会练习的一个例子:时钟。里面有很重要的内容,最好运行一下,仔细看思路。
public class TimeView extends TextView { private Paint mPaint; private int mSecond; private int mMinite; private int mHour; public TimeView(Context context) { this(context, null); } public TimeView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TimeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setAntiAlias(true); String time = getTimeShort(); int hour = Integer.valueOf(time.substring(0, 2)); mHour = hour % 12; mMinite = Integer.valueOf(time.substring(3, 5)); mSecond = Integer.valueOf(time.substring(6, time.length())); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: mSecond++; if (mSecond == 60) { mSecond = 0; mMinite++; if (mMinite == 60) { mMinite = 0; mHour++; if (mHour == 12) { mHour = 0; } } } invalidate(); break; } } }; @Override protected void onDraw(Canvas canvas) { int screenX = getMeasuredWidth() / 2; int screenY = getMeasuredHeight() / 2; mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(3); mPaint.setColor(Color.GREEN); //绘制背景 canvas.drawColor(Color.YELLOW); //绘制大圆 canvas.drawCircle(screenX, screenY, 250, mPaint); //绘制表芯小圆 mPaint.setColor(Color.GRAY); mPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(screenX, screenY, 18, mPaint); //绘制指针小圆 mPaint.setColor(Color.GREEN); canvas.drawCircle(screenX, screenY, 10, mPaint); //绘制文字北京时间 问题:如何计算指定长度的字符所占的角度(未解决) mPaint.setStrokeWidth(2); String s = "北京时间"; mPaint.setTextSize(DensityUtils.sp2px(getContext(), 19)); Path textPath = new Path(); RectF rect = new RectF(screenX - 205, screenY - 205, screenX + 205, screenY + 205); textPath.arcTo(rect, -111, 90, false);//这里没有做适配,所以可能运行不是在文字正上方 canvas.drawTextOnPath(s, textPath, 0, 0, mPaint); //绘制刻度 这个不是很好理解:思路是这样的,首先将画布平移到圆的中心(本例子中就是屏幕中央),那么此时高中立体几何的知识就用到了,画布已经平移到屏幕中央了,那么 // 此时屏幕中央的坐标是多少呢?答案是(0,0),屏幕左上角的坐标是多少呢(-screenWidth/2,-screenHeight/2),为什么?想想立体几何中的知识(具体什么知识我也忘了,不过确实是) //然后我们绘制刻度线就要以屏幕中央为基准点,绘制。怎么绘制?很简单,画笔只负责在同一个位置画直线,然后让画布旋转,相对运动吗,这样转一圈,刻度就好了 //现在是怎么确定直线两点坐标为题,我的思路是在正上方绘制直线,那么坐标就是多少呢?例如线长为20,圆半径为100,则坐标为(0,-100)和(0,-120).理解一下,再读读上面内容画个坐标系就懂了 canvas.save();//保存当前画布的各种属性状态,配合canvas.restore();使用 canvas.translate(screenX, screenY); for (int i = 0; i < 60; i++) { if (i % 5 == 0) {//长 mPaint.setStrokeWidth(3); canvas.drawLine(0, -250, 0, -274, mPaint); } else {//短 mPaint.setStrokeWidth(2); canvas.drawLine(0, -250, 0, -265, mPaint); } canvas.rotate(6); } //绘制数字(思路和绘制刻度一样) Rect re = new Rect(); for (int i = 1; i < 13; i++) { int t = i - 1; if (t == 0) { t = 12; } mPaint.setStrokeWidth(2); mPaint.setTextSize(DensityUtils.sp2px(getContext(), 16)); String num = String.valueOf(t); mPaint.getTextBounds(num, 0, num.length(), re); canvas.drawText(num, -re.width() / 2, -280, mPaint); canvas.rotate(30); } canvas.restore();//回复保存的画布各种属性状态,这中间做的各种改变都放弃掉 canvas.save(); //绘制时针 mPaint.setStrokeWidth(7); canvas.translate(screenX, screenY); canvas.rotate((float) 30 * mHour + 30 * (float) mMinite / 60); canvas.drawLine(0, 20, 0, -155, mPaint); canvas.restore(); //绘制分针 canvas.save(); mPaint.setStrokeWidth(5); canvas.translate(screenX, screenY); canvas.rotate((float) 6 * mMinite + 6 * (float) mSecond / 60); canvas.drawLine(0, 25, 0, -175, mPaint); canvas.restore(); canvas.save(); //绘制秒针 canvas.translate(screenX, screenY); mPaint.setStrokeWidth(3); canvas.rotate(6 * mSecond); canvas.drawLine(0, 35, 0, -190, mPaint); canvas.restore(); mHandler.sendEmptyMessageDelayed(0, 1000); } /** * 获取时间 小时:分;秒 HH:mm:ss * * @return */ public static String getTimeShort() { SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); Date currentTime = new Date(); return formatter.format(currentTime); } public void onDestory() { mHandler.removeCallbacksAndMessages(null); mHandler = null; }}
0 0
- 自定义View之点 线 面以及绘制一个综合应用时钟
- Android之自定义View以及画一个时钟
- Android之自定义View以及画一个时钟
- 自定义View之canvas绘制时钟
- 自定义view绘制时钟
- 自定义View绘制时钟
- 自定义时钟View,表盘的绘制
- 绘制类似时钟的自定义view
- 自定义View之手绘时钟
- Android自定义View——绘制一个会动的时钟
- Android 自定义View以及View绘制详解
- 绘制点、线、面
- Android 自定义View(二),点,线的绘制
- 自定义View学习篇之绘制一个圆环动画
- android自定义view之自定义时钟wacthview
- 自定义View之绘制圆环
- 自定义View之绘制钟表
- Android 自定义View之View的绘制
- 自定义TextBox(带有自动完成输入项功能)
- 问问题
- 求1+2+3+...+n
- 第十二届北航程序设计竞赛初赛——勾肥大战题解
- redis之zset
- 自定义View之点 线 面以及绘制一个综合应用时钟
- 第十五周--用哈希组织关键字
- 关于在java1.8环境下成功用rmic命令生成_stub.class文件的方法
- 天气通遇见乐视TV,神奇化反在哪里
- FTP局域网内其他用户访问不了
- Android和H5(JS)简单交互
- Android实训案例(六)——四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听
- java 反射机制(Field)对类的字段进行操作
- 多项式相加