1 收獲
通過(guò)學(xué)習(xí)這次宫补,又學(xué)到了實(shí)現(xiàn)一種簡(jiǎn)單的動(dòng)畫(huà)檬姥,我們可以通過(guò)繪畫(huà)的方式來(lái)是實(shí)現(xiàn)動(dòng)畫(huà)。通過(guò)這里的學(xué)習(xí)我們不再僅僅局限于Animator或者Animation,在這里我們還可以繪制文本粉怕,通過(guò)學(xué)習(xí)健民,我們也是第一接觸這些新的知識(shí)點(diǎn),當(dāng)然還還是需要我們花費(fèi)很多時(shí)間去理解的贫贝,不僅僅是學(xué)到了荞雏,還要學(xué)會(huì),學(xué)以致用,只有這樣我們才能掌握我們學(xué)到的東西凤优,才會(huì)轉(zhuǎn)化成我們自己的東西悦陋,才能拿出的手。說(shuō)實(shí)話在課堂上我沒(méi)有怎末聽(tīng)懂筑辨,只是有少部分的知識(shí)才聽(tīng)得懂俺驶,但是我知道也許我沒(méi)有聽(tīng)懂的部分也許是重要的,后面雖然來(lái)上課的人越來(lái)越少棍辕,但是希望自己還是能夠堅(jiān)持下去暮现,學(xué)習(xí)是以漫長(zhǎng)的過(guò)程,他也是一個(gè)充滿無(wú)數(shù)可能的過(guò)程3选F艽!
2.技術(shù)
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
(2)筆的屬性
(3)餅狀圖的三種繪制方式
(4)文本的繪制
(5 )波浪線的繪制
3.技術(shù)實(shí)踐及其應(yīng)用
(1)onDraw方法和onMeasure方法以及onSizeChanged方法
我們?cè)诶L制圖的過(guò)程圖的過(guò)程種我們需要知道這個(gè)圖到底是怎么繪制的抚太。實(shí)際上我們繪制的過(guò)程是在onDraw方法中實(shí)現(xiàn)的
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
在這個(gè)方法中我們可以實(shí)現(xiàn)繪制塘幅,當(dāng)然這個(gè)方法只能由系統(tǒng)調(diào)用,我們不能直接調(diào)用這個(gè)方法尿贫,如果我們需要調(diào)用這個(gè)方法 我們需要通過(guò)方法invalidate()方法來(lái)告訴系統(tǒng)我們需要方法onDraw(Canvas canvas)电媳,然后由系統(tǒng)來(lái)幫我們調(diào)用。
onMeasure()方法是系統(tǒng)的自己調(diào)用的庆亡,通過(guò)這方法系統(tǒng)可以得到最終的容器或者是控件的大小匾乓,不管外部設(shè)置多大或者是多小的值,只要一旦在onMeasure()方法里面設(shè)置了值又谋,那磨最終還是依據(jù)onMeasure()方法里面設(shè)置的大小來(lái)拼缝。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
onSizeChanged方法也是一個(gè)系統(tǒng)的方法,他的作用是當(dāng)父容器或者是一些控件的大小變化后就會(huì)調(diào)用此方法彰亥,父容器的大小確定也會(huì)由系統(tǒng)自己調(diào)用咧七。
@Override//當(dāng)父容器的大小確定后就會(huì)調(diào)用
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
(2)筆的屬性
在我們繪制的過(guò)程必須要的就是繪制的筆,這個(gè)筆用許多的屬性剩愧,接下來(lái)我們就將這些屬性列舉出來(lái)猪叙,以方便使用。
首先我們需要明確我們的筆在哪使用:關(guān)于這個(gè)筆的使用一般是在onDraw()方法中是用仁卷,在使用之前我們要對(duì)筆進(jìn)行初始化也就是對(duì)筆進(jìn)行設(shè)置屬性
paint:
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);//對(duì)筆進(jìn)行創(chuàng)建
paint.setColor(Color.BLACK);//對(duì)畫(huà)筆的顏色進(jìn)行設(shè)置
paint.setStrokeWidth(20);//對(duì)畫(huà)筆的粗細(xì)進(jìn)行設(shè)置
paint.setAntiAlias(true);//抗鋸齒
paint.setStyle(Paint.Style.STROKE);//將畫(huà)筆設(shè)置為空心(Paint.Style.FILL為實(shí)心)
在筆的使用時(shí)我們一般和cavas一起使用(cavas詳單與是一塊畫(huà))
(3)餅狀圖的三種繪制方式
在本此實(shí)驗(yàn)中我們以畫(huà)餅狀圖為例穴翩。
首先我們需要新建一個(gè)類(lèi)并且要繼承于View,來(lái)管理畫(huà)餅狀圖
實(shí)現(xiàn)這里的類(lèi)的構(gòu)造方法
public Testview(Context context) {
super(context);
}
public Testview(Context context, AttributeSet attrs) {
super(context, attrs);
}
然后在onDraw是實(shí)現(xiàn)畫(huà)筆一些屬性
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//畫(huà)一條線
//準(zhǔn)備畫(huà)筆
Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);//畫(huà)筆顏色
paint.setStrokeWidth(20);//畫(huà)筆的粗細(xì)
paint.setAntiAlias(true);//抗鋸齒
paint.setStyle(Paint.Style.STROKE);//設(shè)置為空心
1.通過(guò)添加點(diǎn)擊事件來(lái)改變餅狀圖的進(jìn)度
添加一個(gè)onTouchEven事件锦积,我們通過(guò)點(diǎn)擊就可以實(shí)現(xiàn)
//點(diǎn)擊事件的方式來(lái)實(shí)現(xiàn)餅狀圖的繪制
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
//點(diǎn)擊屏幕畫(huà)一部分
angle+=speed;
//控制最大值
if(angle>360){
angle=360;
}
//告訴系統(tǒng)調(diào)用onDraw方法是自己繪制
invalidate();
}
return true;
}
效果:
2.通過(guò)動(dòng)畫(huà)的方式來(lái)實(shí)現(xiàn)動(dòng)畫(huà)
我們通過(guò) ValueAnimator來(lái)實(shí)現(xiàn)動(dòng)畫(huà)
//通過(guò)動(dòng)畫(huà)的方式來(lái)實(shí)現(xiàn)動(dòng)畫(huà)
//創(chuàng)建Animator對(duì)象 設(shè)置范圍0-360
ValueAnimator va=ValueAnimator.ofInt(0,360);
va.setDuration(1000);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
//設(shè)置監(jiān)聽(tīng)器 監(jiān)聽(tīng)值的變化 因?yàn)橹凳且恢痹谧兊拿⑴粒晕覀冃枰恢备? va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//獲取某一刻的值
angle= (int) valueAnimator.getAnimatedValue();
//刷新
invalidate();
}
});
//啟動(dòng)動(dòng)畫(huà)
va.start();
效果:
3.通過(guò)定時(shí)器來(lái)實(shí)現(xiàn)動(dòng)畫(huà)的繪制
//創(chuàng)建定時(shí)器
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)文本的繪制
在這個(gè)文本的繪制中我們是以油刻表為例來(lái)進(jìn)行實(shí)現(xiàn)文字的繪制,這里的動(dòng)態(tài)圖是與文字有關(guān)的
對(duì)于文本的繪制與上面圖形的繪制不同之處就是我們需要的是我們學(xué)要單獨(dú)創(chuàng)建一個(gè)文字畫(huà)筆丰介,畫(huà)筆與文字畫(huà)筆有著不同的屬性
同樣我們需要畫(huà)筆背蟆,兩種不同顏色的畫(huà)筆以便于畫(huà)進(jìn)度鉴分,這三個(gè)畫(huà)筆都是在在一個(gè)法中實(shí)現(xiàn)的,而這個(gè)方法會(huì)被這個(gè)構(gòu)造方法調(diào)用
private void inite() {
//背景畫(huà)筆
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è)置端頭的類(lèi)型
//進(jìn)程畫(huà)筆
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è)置端頭的類(lèi)型
//文本畫(huà)筆
textpaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
textpaint.setColor(Color.BLACK);//設(shè)置文本的壓縮
textpaint.setTextSize(100);//設(shè)置文本的大小
}
接下來(lái)的一步是非常重要的繪制文本來(lái)說(shuō)
首先要搞懂我們學(xué)要在哪繪制文本
我們?cè)诶L制文本時(shí)系統(tǒng)是將文本放在了一個(gè)矩形中而文本域矩形的關(guān)系如上圖
然后我們就在onDraw()方法中繪制
@Override
protected void onDraw(Canvas canvas) {
//畫(huà)初始圓
//確定矩形區(qū)域
RectF f=new RectF(50,100,getWidth()-50,getWidth()-50);
//畫(huà)一個(gè)弧形
canvas.drawArc(f,120,300,false,bgpaint);
//計(jì)算對(duì)應(yīng)進(jìn)度的角度
int angle= (int) (progress*300);
canvas.drawArc(f,120,angle,false,progresspaint);
//對(duì)應(yīng)文本變化
String text=(int)(progress*100)+"%";
//計(jì)算文字的寬度
int width= (int) textpaint.measureText(text);
//計(jì)算文字的矩陣 FontMetrics
//獲取矩陣
Paint.FontMetricsInt fo=textpaint.getFontMetricsInt();
//文字的高度
int height=fo.bottom-fo.top;
//計(jì)算向下移動(dòng)的距離 acent/2 acent為負(fù)數(shù)
int space=-fo.ascent/2;
//畫(huà)文字
canvas.drawText(text,getWidth()/2-width/2,getWidth()/2+space,textpaint);
}
接下來(lái)我們需要進(jìn)行判斷這個(gè)進(jìn)度是否達(dá)到最大值 沒(méi)有到達(dá)最大值我們就繼續(xù)繪制
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
//刷新 重繪
if(progress<=1.0001){
invalidate();
}
}
我們通過(guò)點(diǎn)擊事件來(lái)觸發(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 )波浪線的繪制
在或波浪線之前我們需要搞清楚什么時(shí)path
path是路徑的意思
我們?cè)谶M(jìn)行繪制不規(guī)則圖形是我們需要按照路勁來(lái)進(jìn)行繪制
我們?cè)诶L制波浪線時(shí)我們有兩種不同的方法繪制quadTo()和cubicTo()
首先我們需要路徑和畫(huà)筆带膀,說(shuō)一我們需要?jiǎng)?chuàng)建畫(huà)筆和路徑志珍,在onDraw方法中進(jìn)行創(chuàng)建
@Override
protected void onDraw(Canvas canvas) {
//創(chuàng)建一個(gè)路徑
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.畫(huà)波浪線
path.quadTo(200,200,350,500);
path.quadTo(500,800,650,500f);
//畫(huà)筆
Paint paint=new Paint();
paint.setStrokeWidth(10);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
//繪制
canvas.drawPath(path,paint);
}
效果: