0916Android基础自定义View(Canvas绘图)
2015-09-16 21:00
567 查看
自定义View
自定义View的一些知识
自定义一个类继承View,然后将这个View添加到布局文件中 ,然后在活动中对这个View进行UI操作。在onDraw方法中需要用到Canvas来画各种形状的图形。Canvas的方法中还涉及到一个API:Paint,代表了Canvas上面的画笔,因此Paint类主要用于设置绘制风格,包括画笔颜色、画笔笔触粗细、填充风格等,常用的方法例:setColor(int color):设置颜色
setAntiAlias(boolean aa):设置是否抗锯齿(true则抗锯齿)
setStrokeWidth(float width):设置线宽
setStyle(Paint.Style style):设置风格,例setStyle(Paint.Style.STROKE)设置为无填充
setTextSize(float textSize):设置字体大小
另外Canvas还提供了一些方法进行坐标变换,如
rotate(float degrees,float px,float py):对Canvas进行旋转变换
scale(float sx,float sy,float px,float py): 对Canvas进行缩放变换
skew(float sx,float sy):对Canvas执行倾斜变换
translate(float dx,float dy):移动Canvas (正数:向右移动dx距离,向下移动dy距离;负数:相反)
自定义View的步骤:
新建一个类继承View
继承一个构造方法(根据自己的需要,此处选的是两个参数的那个构造
器和一个参数的那个构造器)
重写onMesure
重写onDraw
时钟Demo
其实这玩意也挺麻烦的。。。这家伙数字还没有调过来呢,要调的话太麻烦,将就用了╮(╯▽╰)╭。
实现这个钟表大体分为4步:
新建类继承View,重写俩个方法onDraw和onMeasure,继承两个构造方法
绘制钟表
使钟表动起来
将组件添加到布局中
绘制钟表
在onMeasure中设置长度宽度
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); }
在两个参数的构造器中设置画笔paint
public MyView(Context context, AttributeSet attrs) { super(context, attrs); mLinePaint=new Paint(); mLinePaint.setColor(Color.BLACK); mLinePaint.setStrokeWidth(5);//线宽 mLinePaint.setAntiAlias(true);//抗锯齿 mLineSecondPaint=new Paint(); mLineSecondPaint.setColor(Color.BLACK); mLineSecondPaint.setStrokeWidth(2);//线宽 mLineSecondPaint.setAntiAlias(true);//抗锯齿 mCirclePaint=new Paint(); mCirclePaint.setColor(Color.BLACK); mCirclePaint.setStrokeWidth(5);//线宽 mCirclePaint.setStyle(Paint.Style.STROKE);//空心圆 mCirclePaint.setAntiAlias(true);//抗锯齿 mCircleText=new Paint(); mCircleText.setTextSize(30);//字体大小 mCircleText.setTextAlign(Paint.Align.CENTER);//对齐方式 }
在onDraw中画出图形,需要注意的是其中整数相除的时候必须要造型成浮点型数据,不然会出错。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // onDraw是由UI主线程自动调用,只需要再此绘制即可 // canvas.drawLine(0, 0, 222, 222, mLinePaint); canvas.drawCircle(mWith / 2, mHeight / 2, 200, mCirclePaint); canvas.drawCircle(mWith / 2, mHeight / 2, 2, mCirclePaint); for(int i=1;i<=12;i++) { canvas.save();//保存当前画布状态 canvas.rotate(360 / 12 * i, mWith / 2, mHeight / 2);//旋转,先旋转再画(旋转角度,旋转中心点xy坐标) canvas.drawLine(mWith / 2, mHeight / 2 - 200, mWith / 2, mHeight / 2 - 180, mLinePaint); canvas.drawText("" + i, mWith / 2, mHeight / 2 - 150, mCircleText); canvas.restore();//恢复到原位置 } mCalendar=Calendar.getInstance(); // 获得时分秒 int minute=mCalendar.get(Calendar.MINUTE); int hour=mCalendar.get(Calendar.HOUR); int second=mCalendar.get(Calendar.SECOND); // 画上分针 float degree=minute/60f*360;//必须定义成浮点型数据, canvas.save(); canvas.rotate(degree, mWith / 2, mHeight / 2);//将下面line旋转这些角度 canvas.drawLine(mWith / 2, mHeight / 2 - 120, mWith / 2, mHeight / 2 +20, mLinePaint); canvas.restore(); // 画上时针 float hourDegree=(hour*60+minute)/(12*60f)*360; canvas.save(); canvas.rotate(hourDegree, mWith / 2, mHeight / 2); canvas.drawLine(mWith / 2, mHeight / 2 - 90, mWith / 2, mHeight / 2 +20, mLinePaint); canvas.restore(); // 画上秒针 float secondDegree=second/60f*360;//加f的位置要注意- - canvas.save(); canvas.rotate(secondDegree, mWith / 2, mHeight / 2); canvas.drawLine(mWith / 2, mHeight / 2 - 140, mWith / 2, mHeight / 2 + 20, mLineSecondPaint); canvas.restore(); }
让钟表动起来,通过Handler实现
在两个参数的构造器 MyView(Context context, AttributeSet attrs)中发送信息
handler.sendEmptyMessageDelayed(CLOCKFLUSH,1000);
接收消息并处理,在handler中再发送消息形成循环
public static final int CLOCKFLUSH=0X23; private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case CLOCKFLUSH: mCalendar=Calendar.getInstance();//重新获取当前时间 invalidate();//刷新 handler.sendEmptyMessageDelayed(CLOCKFLUSH,1000); break; default: break; } } };
布局中只添加了这个组件
<com.example.laowang.android0916canvas_.weight.MyView android:layout_width="match_parent" android:layout_height="match_parent" />
实现效果(请无视这个按键。。。)
全部代码View类
package com.example.laowang.android0916canvas_.weight; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.View; import java.util.Calendar; /** * Created by Administrator on 2015/9/16. */ public class MyView extends View { private int mWith; private int mHeight; private Paint mLinePaint; private Paint mLineSecondPaint; private Paint mCirclePaint; private Paint mCircleText; private Calendar mCalendar; public static final int CLOCKFLUSH=0X23; private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case CLOCKFLUSH: mCalendar=Calendar.getInstance();//重新获取当前时间 invalidate();//刷新 handler.sendEmptyMessageDelayed(CLOCKFLUSH,1000); break; default: break; } } }; public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); mLinePaint=new Paint(); mLinePaint.setColor(Color.BLACK); mLinePaint.setStrokeWidth(5);//线宽 mLinePaint.setAntiAlias(true);//抗锯齿 mLineSecondPaint=new Paint(); mLineSecondPaint.setColor(Color.BLACK); mLineSecondPaint.setStrokeWidth(2);//线宽 mLineSecondPaint.setAntiAlias(true);//抗锯齿 mCirclePaint=new Paint(); mCirclePaint.setColor(Color.BLACK); mCirclePaint.setStrokeWidth(5);//线宽 mCirclePaint.setStyle(Paint.Style.STROKE);//空心圆 mCirclePaint.setAntiAlias(true);//抗锯齿 mCircleText=new Paint(); mCircleText.setTextSize(30);//字体大小 mCircleText.setTextAlign(Paint.Align.CENTER);//对齐方式 handler.sendEmptyMessageDelayed(CLOCKFLUSH,1000); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWith = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // onDraw是由UI主线程自动调用,只需要再此绘制即可 // canvas.drawLine(0, 0, 222, 222, mLinePaint); canvas.drawCircle(mWith / 2, mHeight / 2, 200, mCirclePaint); canvas.drawCircle(mWith / 2, mHeight / 2, 2, mCirclePaint); for(int i=1;i<=12;i++) { canvas.save();//保存当前画布状态 canvas.rotate(360 / 12 * i, mWith / 2, mHeight / 2);//旋转,先旋转再画(旋转角度,旋转中心点xy左边) canvas.drawLine(mWith / 2, mHeight / 2 - 200, mWith / 2, mHeight / 2 - 180, mLinePaint); canvas.drawText("" + i, mWith / 2, mHeight / 2 - 150, mCircleText); canvas.restore();//恢复到原位置 } mCalendar=Calendar.getInstance(); // 获得时分秒 int minute=mCalendar.get(Calendar.MINUTE); int hour=mCalendar.get(Calendar.HOUR); int second=mCalendar.get(Calendar.SECOND); // 画上分针 float degree=minute/60f*360;//必须定义成浮点型数据, canvas.save(); canvas.rotate(degree, mWith / 2, mHeight / 2);//将下面line旋转这些角度 canvas.drawLine(mWith / 2, mHeight / 2 - 120, mWith / 2, mHeight / 2 +20, mLinePaint); canvas.restore(); // 画上时针 float hourDegree=(hour*60+minute)/(12*60f)*360; canvas.save(); canvas.rotate(hourDegree, mWith / 2, mHeight / 2); canvas.drawLine(mWith / 2, mHeight / 2 - 90, mWith / 2, mHeight / 2 +20, mLinePaint); canvas.restore(); // 画上秒针 float secondDegree=second/60f*360;//加f的位置要注意- - canvas.save(); canvas.rotate(secondDegree, mWith / 2, mHeight / 2); canvas.drawLine(mWith / 2, mHeight / 2 - 140, mWith / 2, mHeight / 2 + 20, mLineSecondPaint); canvas.restore(); } }
相关文章推荐
- Android学习笔记之——GridView
- Android学习笔记之——Spinner
- Android开发之Intent.Action
- Android中自制各种进度条的实现
- Android 无法获取正在运行的程序
- Android之自定义View以及画一个时钟
- Android屏幕适配及DisplayMetrics解析
- android学习:android Activity生命周期的七个方法测试
- 初识Android
- Android多媒体之调用摄像头和从本地相册中选择图片
- Android 自定义View——自定义View控件
- Android 4.4 kitkat以上及以下根据uri获取路径的方法
- Android启动服务播放音乐(两种启动方式)
- Android扩展存储--ExtraStorage
- Android调试系统类时代码对不上的原因
- 彻底解决Android 应用方法数不能超过65K的问题
- Android Studio中如何将GIT提交项目到远程仓库
- Android0915<十九>(多媒体、SoundPool、MediaRecorder、SurfaceView,简单地使用摄像头)
- Android自定义View及canvas(表盘实例)
- 解决本地访问Android文档是非常慢的问题