Android之自定义View以及画一个时钟
https://www.2cto.com/kf/201509/443112.html
概述:
当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) // 设置下划线
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();
}
Android之自定义View以及画一个时钟的更多相关文章
- Android之自定义View学习(一)
Android之自定义View学习(一) Canvas常用方法: 图片来源 /** * Created by SiberiaDante on 2017/6/3. */ public class Bas ...
- Android读取自定义View属性
Android读取自定义View属性 attrs.xml : <?xml version="1.0" encoding="utf-8"?> < ...
- 深夜,用canvas画一个时钟
深夜,用canvas画一个时钟 查看demo 这几天准备阿里巴巴的笔试,可以说已经是心力交瘁,自从阿里和蘑菇街的内推被刷掉之后,开始越来越怀疑起自己的能力来,虽然这点打击应该是微不足道的.毕竟校招在刚 ...
- Android的自定义View及View的绘制流程
目标:实现Android中的自定义View,为理清楚Android中的View绘制流程“铺路”. 想法很简单:从一个简单例子着手开始编写自定义View,对ViewGroup.View类中与绘制View ...
- android开发:Android 中自定义View的应用
大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...
- 自定义View实战--实现一个清新美观的加载按钮
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在 Dribble 上偶然看到了一组交互如下: 当时在心里问自己能不能做,答案肯定是能做的,不过我比较懒,觉得中间那个伸缩变化要编写 ...
- Android之自定义View的实现
对于学习Android开发的小童鞋对于自定义View一定不会陌生,相信大家对它是又爱又恨,爱它可以跟随我们的心意设计出漂亮的效果:恨它想要完全流畅掌握,需要一定的功夫.对于初学者来说确实很不容易,网上 ...
- 自定义View(三)--实现一个简单地流式布局
Android中的流式布局也就是常说的瀑布流很是常见,不仅在很多项目中都能见到,而且面试中也有很多面试官问道,那么什么是流式布局呢?简单来说就是如果当前行的剩余宽度不足以摆放下一个控件的时候,则自动将 ...
- Android解决自定义View获取不到焦点的情况
引言: 我们在使用Android View或者SurfaceView进行图形绘制,可以绘制各种各样我们喜欢的图形,然后满怀信心的给我们的View加上onTouchEvent.onKeyDown.onK ...
随机推荐
- Linux Shell脚本编程基础
1. 脚本是一个包含一系列命令序列的文本文件,当运行这个脚本文件时,文件中包含的命令序列将得到执行. 2. 脚本主要由两部分组成:脚本解释器和命令序列 注:#!/bin/bash 指明脚本解释器为Ba ...
- 使用chart.js時取消懸浮在圖表頂部的'undefined'標識
解決方法:在options中設置legend項中display屬性為false options: { scales: { yAxes: [{ ticks: { beginAtZero: true } ...
- $bzoj1027-JSOI2007$ 合金 计算几何 最小环
题面描述 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金 ...
- spark第八篇:与Phoenix整合
spark sql可以与hbase交互,比如说通过jdbc,但是实际使用时,一般是利用phoenix操作hbase.此时,需要在项目中引入phoenix-core-4.10.0-HBase-1.2.j ...
- Oracle 如何修改列的数据类型
链接:http://www.cnblogs.com/david-zhang-index/archive/2012/04/10/2441015.html 对字段操作 操作方法 更新字段名 alter t ...
- 封装element-ui的dialog组件
封装组件: <template> <div class="dialog-container"> <el-dialog title="titl ...
- Django开发步骤
Django开发步骤 Django框架每次开发的初始化的套路都基本一样,这里记录一下. 安装Django 首先安装Python软件,上python官网下载对应的安装包.接下来就是安装Django: p ...
- Django 入门项目案例开发(中)
关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. 昨天已经描述了如何搭建Django的开发环境,今天描述业务流程,具体我们要实现一个什么样的业务 ...
- 使用 Qt 获取 UDP 数据并显示成图片(2)
本文首发于 BriFuture 的 个人博客 在我的前一篇文章 使用 Qt 获取 UDP 数据并显示成图片 中,我讲了如何用 Python 模拟发送数据,如何在 Qt 中高效的接收 UDP 数据包并将 ...
- Silverlight & Blend动画设计系列九:动画(Animation)与视图状态管理(Visual State Manager)
Silverlight中的动画(Animation)与视图状态管理(Visual State Manager) 结合使用是非常常见的,动画用于管理对象在某段事件段内执行的动画动作,视图状态管理则用于控 ...