1 收获
通过学习这次,又学到了实现一种简单的动画,我们可以通过绘画的方式来是实现动画。通过这里的学习我们不再仅仅局限于Animator或者Animation,在这里我们还可以绘制文本,通过学习,我们也是第一接触这些新的知识点,当然还还是需要我们花费很多时间去理解的,不仅仅是学到了,还要学会,学以致用,只有这样我们才能掌握我们学到的东西,才会转化成我们自己的东西,才能拿出的手。说实话在课堂上我没有怎末听懂,只是有少部分的知识才听得懂,但是我知道也许我没有听懂的部分也许是重要的,后面虽然来上课的人越来越少,但是希望自己还是能够坚持下去,学习是以漫长的过程,他也是一个充满无数可能的过程!!!
2.技术
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
(2)笔的属性
(3)饼状图的三种绘制方式
(4)文本的绘制
(5 )波浪线的绘制
3.技术实践及其应用
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
我们在绘制图的过程图的过程种我们需要知道这个图到底是怎么绘制的。实际上我们绘制的过程是在onDraw方法中实现的
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
在这个方法中我们可以实现绘制,当然这个方法只能由系统调用,我们不能直接调用这个方法,如果我们需要调用这个方法 我们需要通过方法invalidate()方法来告诉系统我们需要方法onDraw(Canvas canvas),然后由系统来帮我们调用。
onMeasure()方法是系统的自己调用的,通过这方法系统可以得到最终的容器或者是控件的大小,不管外部设置多大或者是多小的值,只要一旦在onMeasure()方法里面设置了值,那磨最终还是依据onMeasure()方法里面设置的大小来。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
onSizeChanged方法也是一个系统的方法,他的作用是当父容器或者是一些控件的大小变化后就会调用此方法,父容器的大小确定也会由系统自己调用。
@Override//当父容器的大小确定后就会调用
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
(2)笔的属性
在我们绘制的过程必须要的就是绘制的笔,这个笔用许多的属性,接下来我们就将这些属性列举出来,以方便使用。
首先我们需要明确我们的笔在哪使用:关于这个笔的使用一般是在onDraw()方法中是用,在使用之前我们要对笔进行初始化也就是对笔进行设置属性
paint:
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);//对笔进行创建
paint.setColor(Color.BLACK);//对画笔的颜色进行设置
paint.setStrokeWidth(20);//对画笔的粗细进行设置
paint.setAntiAlias(true);//抗锯齿
paint.setStyle(Paint.Style.STROKE);//将画笔设置为空心(Paint.Style.FILL为实心)
在笔的使用时我们一般和cavas一起使用(cavas详单与是一块画)
(3)饼状图的三种绘制方式
在本此实验中我们以画饼状图为例。
首先我们需要新建一个类并且要继承于View,来管理画饼状图
实现这里的类的构造方法
public Testview(Context context) {
super(context);
}
public Testview(Context context, AttributeSet attrs) {
super(context, attrs);
}
然后在onDraw是实现画笔一些属性
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画一条线
//准备画笔
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);//画笔颜色
paint.setStrokeWidth(20);//画笔的粗细
paint.setAntiAlias(true);//抗锯齿
paint.setStyle(Paint.Style.STROKE);//设置为空心
1.通过添加点击事件来改变饼状图的进度
添加一个onTouchEven事件,我们通过点击就可以实现
//点击事件的方式来实现饼状图的绘制
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
//点击屏幕画一部分
angle+=speed;
//控制最大值
if(angle>360){
angle=360;
}
//告诉系统调用onDraw方法是自己绘制
invalidate();
}
return true;
}
效果:
2.通过动画的方式来实现动画
我们通过 ValueAnimator来实现动画
//通过动画的方式来实现动画
//创建Animator对象 设置范围0-360
ValueAnimator va=ValueAnimator.ofInt(0,360);
va.setDuration(1000);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
//设置监听器 监听值的变化 因为值是一直在变的,所以我们需要一直更新
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//获取某一刻的值
angle= (int) valueAnimator.getAnimatedValue();
//刷新
invalidate();
}
});
//启动动画
va.start();
效果:
3.通过定时器来实现动画的绘制
//创建定时器
final Timer t=new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
angle+=speed;
if(angle>360){
t.cancel();
}
//invalidate();
postInvalidate();//在子线程里面使用
}
},0,100);
效果:
(4)文本的绘制
在这个文本的绘制中我们是以油刻表为例来进行实现文字的绘制,这里的动态图是与文字有关的
对于文本的绘制与上面图形的绘制不同之处就是我们需要的是我们学要单独创建一个文字画笔,画笔与文字画笔有着不同的属性
同样我们需要画笔,两种不同颜色的画笔以便于画进度,这三个画笔都是在在一个法中实现的,而这个方法会被这个构造方法调用
private void inite() {
//背景画笔
bgpaint=new Paint(Paint.ANTI_ALIAS_FLAG);
bgpaint.setColor(Color.GRAY);
bgpaint.setStyle(Paint.Style.STROKE);
bgpaint.setStrokeWidth(40);
bgpaint.setStrokeCap(Paint.Cap.ROUND);//设置端头的类型
//进程画笔
progresspaint=new Paint(Paint.ANTI_ALIAS_FLAG);
progresspaint.setColor(Color.GREEN);
progresspaint.setStyle(Paint.Style.STROKE);
progresspaint.setStrokeWidth(40);
progresspaint.setStrokeCap(Paint.Cap.ROUND);//设置端头的类型
//文本画笔
textpaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
textpaint.setColor(Color.BLACK);//设置文本的压缩
textpaint.setTextSize(100);//设置文本的大小
}
接下来的一步是非常重要的绘制文本来说
首先要搞懂我们学要在哪绘制文本
我们在绘制文本时系统是将文本放在了一个矩形中而文本域矩形的关系如上图
然后我们就在onDraw()方法中绘制
@Override
protected void onDraw(Canvas canvas) {
//画初始圆
//确定矩形区域
RectF f=new RectF(50,100,getWidth()-50,getWidth()-50);
//画一个弧形
canvas.drawArc(f,120,300,false,bgpaint);
//计算对应进度的角度
int angle= (int) (progress*300);
canvas.drawArc(f,120,angle,false,progresspaint);
//对应文本变化
String text=(int)(progress*100)+"%";
//计算文字的宽度
int width= (int) textpaint.measureText(text);
//计算文字的矩阵 FontMetrics
//获取矩阵
Paint.FontMetricsInt fo=textpaint.getFontMetricsInt();
//文字的高度
int height=fo.bottom-fo.top;
//计算向下移动的距离 acent/2 acent为负数
int space=-fo.ascent/2;
//画文字
canvas.drawText(text,getWidth()/2-width/2,getWidth()/2+space,textpaint);
}
接下来我们需要进行判断这个进度是否达到最大值 没有到达最大值我们就继续绘制
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
//刷新 重绘
if(progress<=1.0001){
invalidate();
}
}
我们通过点击事件来触发
@Override
public boolean onTouchEvent(MotionEvent event) {
MeterView mv=findViewById(R.id.meter);
if(event.getAction()==MotionEvent.ACTION_DOWN){
//更改进度值 在原有的基础上+0.05
mv.setProgress((float) (mv.getProgress()+0.05));
}
return true;
}
效果:
(5 )波浪线的绘制
在或波浪线之前我们需要搞清楚什么时path
path是路径的意思
我们在进行绘制不规则图形是我们需要按照路劲来进行绘制
我们在绘制波浪线时我们有两种不同的方法绘制quadTo()和cubicTo()
首先我们需要路径和画笔,说一我们需要创建画笔和路径,在onDraw方法中进行创建
@Override
protected void onDraw(Canvas canvas) {
//创建一个路径
Path path=new Path();
path.moveTo(50,500);//绘制的起始点
/*
//1.塞尔曲线
path.cubicTo(50,500,200,200,350,500);
path.cubicTo(350,500,500,800,650,500);
*/
//2.画波浪线
path.quadTo(200,200,350,500);
path.quadTo(500,800,650,500f);
//画笔
Paint paint=new Paint();
paint.setStrokeWidth(10);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
//绘制
canvas.drawPath(path,paint);
}
效果: