Android之自定义View以及画一个时钟
2015-09-16 20:42
417 查看
概述:
当Android自带的View满足不了开发者时,自定义View就发挥了很好的作用。建立一个自定义View,需要继承于View类,并且实现其中的至少一个构造函数和两个方法:onMeasure()和onDraw();
onMeasure()用于设置自定义View的尺寸,onDraw()用于绘制View中的内容。
在onDraw()方法中,需要调用画笔绘制图形或文本,绘制的模板时Canvas对象, Canvas类中用来绘制图形文本的方法有:
drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域
drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。
drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象。
drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。
drawText(String text, float x, floaty, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。
drawOval(RectF oval, Paint paint)//画椭圆,参数一是扫描区域,参数二为paint对象;
drawCircle(float cx, float cy, float radius,Paint paint)// 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象;
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象。
绘制图形需要画笔Paint对象,Paint类中的方法有:
setARGB(int a, int r, int g, int b) // 设置 Paint对象颜色,参数一为alpha透明值
setAlpha(int a) // 设置alpha不透明度,范围为0~255
setAntiAlias(boolean aa) // 是否抗锯齿
setColor(int color) // 设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义
setTextScaleX(float scaleX) // 设置文本缩放倍数,1.0f为原始
setTextSize(float textSize) // 设置字体大小
setUnderlineText(booleanunderlineText) // 设置下划线
Demo
一个自定义时钟视图的写法:public class MyView extends View { private int width; private int height; private Paint mPaintLine; private Paint mPaintCircle; private Paint mPaintHour; private Paint mPaintMinute; private Paint mPaintSec; private Paint mPaintText; private Calendar mCalendar; public static final int NEED_INVALIDATE = 0X23; //每隔一秒,在handler中调用一次重新绘制方法 private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case NEED_INVALIDATE: mCalendar = Calendar.getInstance(); invalidate();//告诉UI主线程重新绘制 handler.sendEmptyMessageDelayed(NEED_INVALIDATE,1000); break; default: break; } } }; public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); mCalendar = Calendar.getInstance(); mPaintLine = new Paint(); mPaintLine.setColor(Color.BLUE); mPaintLine.setStrokeWidth(10); mPaintCircle = new Paint(); mPaintCircle.setColor(Color.GREEN);//设置颜色 mPaintCircle.setStrokeWidth(10);//设置线宽 mPaintCircle.setAntiAlias(true);//设置是否抗锯齿 mPaintCircle.setStyle(Paint.Style.STROKE);//设置绘制风格 mPaintText = new Paint(); mPaintText.setColor(Color.BLUE); mPaintText.setStrokeWidth(10); mPaintText.setTextAlign(Paint.Align.CENTER); mPaintText.setTextSize(40); mPaintHour = new Paint(); mPaintHour.setStrokeWidth(20); mPaintHour.setColor(Color.BLUE); mPaintMinute = new Paint(); mPaintMinute.setStrokeWidth(15); mPaintMinute.setColor(Color.BLUE); mPaintSec = new Paint(); mPaintSec.setStrokeWidth(10); mPaintSec.setColor(Color.BLUE); handler.sendEmptyMessage(NEED_INVALIDATE);//向handler发送一个消息,让它开启重绘 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int circleRadius = 400; //画出大圆 canvas.drawCircle(width / 2, height / 2, circleRadius, mPaintCircle); //画出圆中心 canvas.drawCircle(width / 2, height / 2, 20, mPaintCircle); //依次旋转画布,画出每个刻度和对应数字 for (int i = 1; i <= 12; i++) { canvas.save();//保存当前画布 canvas.rotate(360/12*i,width/2,height/2); //左起:起始位置x坐标,起始位置y坐标,终止位置x坐标,终止位置y坐标,画笔(一个Paint对象) canvas.drawLine(width / 2, height / 2 - circleRadius, width / 2, height / 2 - circleRadius + 30, mPaintCircle); //左起:文本内容,起始位置x坐标,起始位置y坐标,画笔 canvas.drawText(""+i, width / 2, height / 2 - circleRadius + 70, mPaintText); canvas.restore();// } int minute = mCalendar.get(Calendar.MINUTE);//得到当前分钟数 int hour = mCalendar.get(Calendar.HOUR);//得到当前小时数 int sec = mCalendar.get(Calendar.SECOND);//得到当前秒数 float minuteDegree = minute/60f*360;//得到分针旋转的角度 canvas.save(); canvas.rotate(minuteDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2 - 250, width / 2, height / 2 + 40, mPaintMinute); canvas.restore(); float hourDegree = (hour*60+minute)/12f/60*360;//得到时钟旋转的角度 canvas.save(); canvas.rotate(hourDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2 - 200, width / 2, height / 2 + 30, mPaintHour); canvas.restore(); float secDegree = sec/60f*360;//得到秒针旋转的角度 canvas.save(); canvas.rotate(secDegree,width/2,height/2); canvas.drawLine(width/2,height/2-300,width/2,height/2+40,mPaintSec); canvas.restore(); } }
需要在布局中加载自定义View,名字必须是全名(包括包名):
activity_timer
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.administrator.selfdefinedview.widget.MyView android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
主活动setContentView就行了
public class TimerActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_timer); } }
演示结果:
相关文章推荐
- 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文档是非常慢的问题
- Android 多媒体应用——调用系统相机和相册
- Android多线程下载文件
- Material Design 开发利器:Android Design Support Library 介绍
- Android的开发环境的发展演变
- 如何不翻墙下载Android代码
- android获取当前焦点的位置,查找焦点的位置