1 收獲
通過學(xué)習(xí)這次,又學(xué)到了實(shí)現(xiàn)一種簡單的動畫,我們可以通過繪畫的方式來是實(shí)現(xiàn)動畫。通過這里的學(xué)習(xí)我們不再僅僅局限于Animator或者Animation,在這里我們還可以繪制文本,通過學(xué)習(xí),我們也是第一接觸這些新的知識點(diǎn),當(dāng)然還還是需要我們花費(fèi)很多時間去理解的,不僅僅是學(xué)到了,還要學(xué)會,學(xué)以致用,只有這樣我們才能掌握我們學(xué)到的東西,才會轉(zhuǎn)化成我們自己的東西,才能拿出的手。說實(shí)話在課堂上我沒有怎末聽懂,只是有少部分的知識才聽得懂,但是我知道也許我沒有聽懂的部分也許是重要的,后面雖然來上課的人越來越少,但是希望自己還是能夠堅(jiān)持下去,學(xué)習(xí)是以漫長的過程,他也是一個充滿無數(shù)可能的過程!!!
2.技術(shù)
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
(2)筆的屬性
(3)餅狀圖的三種繪制方式
(4)文本的繪制
(5 )波浪線的繪制
3.技術(shù)實(shí)踐及其應(yīng)用
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
我們在繪制圖的過程圖的過程種我們需要知道這個圖到底是怎么繪制的。實(shí)際上我們繪制的過程是在onDraw方法中實(shí)現(xiàn)的
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
在這個方法中我們可以實(shí)現(xiàn)繪制,當(dāng)然這個方法只能由系統(tǒng)調(diào)用,我們不能直接調(diào)用這個方法,如果我們需要調(diào)用這個方法 我們需要通過方法invalidate()方法來告訴系統(tǒng)我們需要方法onDraw(Canvas canvas),然后由系統(tǒng)來幫我們調(diào)用。
onMeasure()方法是系統(tǒng)的自己調(diào)用的,通過這方法系統(tǒng)可以得到最終的容器或者是控件的大小,不管外部設(shè)置多大或者是多小的值,只要一旦在onMeasure()方法里面設(shè)置了值,那磨最終還是依據(jù)onMeasure()方法里面設(shè)置的大小來。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
onSizeChanged方法也是一個系統(tǒng)的方法,他的作用是當(dāng)父容器或者是一些控件的大小變化后就會調(diào)用此方法,父容器的大小確定也會由系統(tǒng)自己調(diào)用。
@Override//當(dāng)父容器的大小確定后就會調(diào)用
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
(2)筆的屬性
在我們繪制的過程必須要的就是繪制的筆,這個筆用許多的屬性,接下來我們就將這些屬性列舉出來,以方便使用。
首先我們需要明確我們的筆在哪使用:關(guān)于這個筆的使用一般是在onDraw()方法中是用,在使用之前我們要對筆進(jìn)行初始化也就是對筆進(jìn)行設(shè)置屬性
paint:
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);//對筆進(jìn)行創(chuàng)建
paint.setColor(Color.BLACK);//對畫筆的顏色進(jìn)行設(shè)置
paint.setStrokeWidth(20);//對畫筆的粗細(xì)進(jìn)行設(shè)置
paint.setAntiAlias(true);//抗鋸齒
paint.setStyle(Paint.Style.STROKE);//將畫筆設(shè)置為空心(Paint.Style.FILL為實(shí)心)
在筆的使用時我們一般和cavas一起使用(cavas詳單與是一塊畫)
(3)餅狀圖的三種繪制方式
在本此實(shí)驗(yàn)中我們以畫餅狀圖為例。
首先我們需要新建一個類并且要繼承于View,來管理畫餅狀圖
實(shí)現(xiàn)這里的類的構(gòu)造方法
public Testview(Context context) {
super(context);
}
public Testview(Context context, AttributeSet attrs) {
super(context, attrs);
}
然后在onDraw是實(shí)現(xiàn)畫筆一些屬性
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//畫一條線
//準(zhǔn)備畫筆
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);//畫筆顏色
paint.setStrokeWidth(20);//畫筆的粗細(xì)
paint.setAntiAlias(true);//抗鋸齒
paint.setStyle(Paint.Style.STROKE);//設(shè)置為空心
1.通過添加點(diǎn)擊事件來改變餅狀圖的進(jìn)度
添加一個onTouchEven事件,我們通過點(diǎn)擊就可以實(shí)現(xiàn)
//點(diǎn)擊事件的方式來實(shí)現(xiàn)餅狀圖的繪制
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
//點(diǎn)擊屏幕畫一部分
angle+=speed;
//控制最大值
if(angle>360){
angle=360;
}
//告訴系統(tǒng)調(diào)用onDraw方法是自己繪制
invalidate();
}
return true;
}
效果:
2.通過動畫的方式來實(shí)現(xiàn)動畫
我們通過 ValueAnimator來實(shí)現(xiàn)動畫
//通過動畫的方式來實(shí)現(xiàn)動畫
//創(chuàng)建Animator對象 設(shè)置范圍0-360
ValueAnimator va=ValueAnimator.ofInt(0,360);
va.setDuration(1000);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
//設(shè)置監(jiān)聽器 監(jiān)聽值的變化 因?yàn)橹凳且恢痹谧兊模晕覀冃枰恢备? va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//獲取某一刻的值
angle= (int) valueAnimator.getAnimatedValue();
//刷新
invalidate();
}
});
//啟動動畫
va.start();
效果:
3.通過定時器來實(shí)現(xiàn)動畫的繪制
//創(chuàng)建定時器
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)文本的繪制
在這個文本的繪制中我們是以油刻表為例來進(jìn)行實(shí)現(xiàn)文字的繪制,這里的動態(tài)圖是與文字有關(guān)的
對于文本的繪制與上面圖形的繪制不同之處就是我們需要的是我們學(xué)要單獨(dú)創(chuàng)建一個文字畫筆,畫筆與文字畫筆有著不同的屬性
同樣我們需要畫筆,兩種不同顏色的畫筆以便于畫進(jìn)度,這三個畫筆都是在在一個法中實(shí)現(xiàn)的,而這個方法會被這個構(gòu)造方法調(diào)用
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);//設(shè)置端頭的類型
//進(jìn)程畫筆
progresspaint=new Paint(Paint.ANTI_ALIAS_FLAG);
progresspaint.setColor(Color.GREEN);
progresspaint.setStyle(Paint.Style.STROKE);
progresspaint.setStrokeWidth(40);
progresspaint.setStrokeCap(Paint.Cap.ROUND);//設(shè)置端頭的類型
//文本畫筆
textpaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
textpaint.setColor(Color.BLACK);//設(shè)置文本的壓縮
textpaint.setTextSize(100);//設(shè)置文本的大小
}
接下來的一步是非常重要的繪制文本來說
首先要搞懂我們學(xué)要在哪繪制文本
我們在繪制文本時系統(tǒng)是將文本放在了一個矩形中而文本域矩形的關(guān)系如上圖
然后我們就在onDraw()方法中繪制
@Override
protected void onDraw(Canvas canvas) {
//畫初始圓
//確定矩形區(qū)域
RectF f=new RectF(50,100,getWidth()-50,getWidth()-50);
//畫一個弧形
canvas.drawArc(f,120,300,false,bgpaint);
//計算對應(yīng)進(jìn)度的角度
int angle= (int) (progress*300);
canvas.drawArc(f,120,angle,false,progresspaint);
//對應(yīng)文本變化
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為負(fù)數(shù)
int space=-fo.ascent/2;
//畫文字
canvas.drawText(text,getWidth()/2-width/2,getWidth()/2+space,textpaint);
}
接下來我們需要進(jìn)行判斷這個進(jìn)度是否達(dá)到最大值 沒有到達(dá)最大值我們就繼續(xù)繪制
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
//刷新 重繪
if(progress<=1.0001){
invalidate();
}
}
我們通過點(diǎn)擊事件來觸發(fā)
@Override
public boolean onTouchEvent(MotionEvent event) {
MeterView mv=findViewById(R.id.meter);
if(event.getAction()==MotionEvent.ACTION_DOWN){
//更改進(jìn)度值 在原有的基礎(chǔ)上+0.05
mv.setProgress((float) (mv.getProgress()+0.05));
}
return true;
}
效果:
(5 )波浪線的繪制
在或波浪線之前我們需要搞清楚什么時path
path是路徑的意思
我們在進(jìn)行繪制不規(guī)則圖形是我們需要按照路勁來進(jìn)行繪制
我們在繪制波浪線時我們有兩種不同的方法繪制quadTo()和cubicTo()
首先我們需要路徑和畫筆,說一我們需要創(chuàng)建畫筆和路徑,在onDraw方法中進(jìn)行創(chuàng)建
@Override
protected void onDraw(Canvas canvas) {
//創(chuàng)建一個路徑
Path path=new Path();
path.moveTo(50,500);//繪制的起始點(diǎn)
/*
//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);
}
效果: