內(nèi)容簡(jiǎn)概
一拖刃、畫(huà)線删壮、圓、扇形
二序调、扇形動(dòng)畫(huà)
具體內(nèi)容
一醉锅、畫(huà)線、圓发绢、扇形硬耍、圓弧
(一)創(chuàng)建一個(gè)類(lèi)(繼承View)用于測(cè)試
在這個(gè)類(lèi)中,我們放置線边酒、圓经柴、扇形、圓弧墩朦。
public class TestView extends View {
// 實(shí)現(xiàn)View的兩個(gè)方法
public TestView(Context context) {
super(context);
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
// 畫(huà)線
// 1. 準(zhǔn)備畫(huà)筆 抗鋸齒
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(70);
mPaint.setColor(Color.BLACK); // 設(shè)置畫(huà)筆顏色
mPaint.setStrokeWidth(20); // 設(shè)置畫(huà)筆粗細(xì)
// 2.在畫(huà)布上畫(huà)線
canvas.drawLine(50,50,300,400,mPaint);
// x,y為開(kāi)頭文字左下角左標(biāo)
canvas.drawText("↑",200,600,mPaint);
canvas.drawText("drawLine",50,700,mPaint);
//3.畫(huà)圓
// 這里的top是圓心坐標(biāo)坯认,
canvas.drawArc(600,50,1000,450,0,300,true,mPaint);
canvas.drawText("↑",770,600,mPaint);
canvas.drawText("drawArc",650,700,mPaint);
// useCenter = false
canvas.drawArc(50,800,450,1200,0,300,false,mPaint);
canvas.drawText("↑",200,1300,mPaint);
canvas.drawText("drawArc",50,1400,mPaint);
canvas.drawText("useCenter=false",50,1500,mPaint);
// 畫(huà)圓的另一種方法
canvas.drawCircle(800,1000,200,mPaint);
canvas.drawText("↑",770,1300,mPaint);
canvas.drawText("drawCircle",650,1400,mPaint);
}
}
這里的圓是實(shí)心的,如果想要畫(huà)空心的圓或者圓弧怎么辦呢氓涣?只要多加一句mPaint.setStyle(Paint.Style.STROKE);
就可以了牛哺,系統(tǒng)默認(rèn)的style為FILL(實(shí)心)。
(二) xml(使用RelativeLayout)
<com.example.test.TestView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
(三)運(yùn)行結(jié)果圖
左邊為實(shí)心劳吠,右邊為空心引润。空心就是描繪外輪廓痒玩。(請(qǐng)忽略空心的丑陋文字)淳附。
二、扇形動(dòng)畫(huà)
扇形動(dòng)畫(huà)是扇形的半徑不變蠢古,轉(zhuǎn)的角度在變奴曙。下面我用兩個(gè)類(lèi)分別實(shí)現(xiàn)兩種動(dòng)畫(huà),一種是點(diǎn)擊展開(kāi)的扇形草讶,一種是自動(dòng)展開(kāi)的扇形洽糟。前者可以用onTouchEvent方法實(shí)現(xiàn),后者可以用Timer(定時(shí)器)或?qū)傩詣?dòng)畫(huà)實(shí)現(xiàn)。
(一)點(diǎn)擊展開(kāi)的扇形
規(guī)定扇形完全展開(kāi)后就固定為圓形脊框,不再變化颁督。
public class FanAnimation extends View {
int angle; //每次增長(zhǎng)之后的值
int speed = 20; //增長(zhǎng)速度
public FanAnimation(Context context) {
super(context);
}
public FanAnimation(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas,Color.BLACK, (float) (angle/360.0),"點(diǎn)擊展開(kāi)的扇形");
}
// onDraw方法不能滿足需求,所以自己寫(xiě)一個(gè)方法
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//畫(huà)筆
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(70);
paint.setColor(color);
//畫(huà)扇形
int endAngle = (int) (360*rate);// 新繪制的扇形endAngle都在增大
canvas.drawArc(50,100,450,500, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
// 點(diǎn)擊屏幕 畫(huà)一點(diǎn) 這里的angle就是上面的rate
angle += speed;
// 控制最大值
if (angle>360){
angle = 360;
}
// 刷新
invalidate();
}
return true;
}
}
(二)自動(dòng)展開(kāi)的扇形——Timer
public class AutoFanAnimation extends View {
int angle; //每次增長(zhǎng)之后的值
int speed = 5; //增長(zhǎng)速度
public AutoFanAnimation(Context context) {
super(context);
}
public AutoFanAnimation(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 創(chuàng)建定時(shí)器 每個(gè)0.5s 畫(huà)一次
final Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
angle += speed;
if (angle > 360){
angle = 0; // 重新開(kāi)始
// t.cancel();// 關(guān)閉定時(shí)器
}
invalidate(); // 通知系統(tǒng)調(diào)用ondraw
postInvalidate(); // 子進(jìn)程里面
}
},0,100);
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"自動(dòng)展開(kāi)的扇形");
}
// onDraw方法不能滿足需求浇雹,所以自己寫(xiě)一個(gè)方法
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//畫(huà)筆
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(70);
paint.setColor(color);
//畫(huà)扇形
int endAngle = (int) (360*rate);
canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
}
(三)自動(dòng)展開(kāi)的扇形——valueAnimator屬性動(dòng)畫(huà)
和自動(dòng)展開(kāi)的扇形唯一不同的就是onSizeChanged沉御。
public class ValueAnimator extends View {
int angle; //每次增長(zhǎng)之后的值
int speed = 20; //增長(zhǎng)速度
public ValueAnimator(Context context) {
super(context);
}
public ValueAnimator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 創(chuàng)建ValueAnimator對(duì)象 設(shè)置范圍0-360
android.animation.ValueAnimator va = android.animation.ValueAnimator.ofInt(0,360);
va.setDuration(3000); // 動(dòng)畫(huà)時(shí)間
va.setRepeatCount(android.animation.ValueAnimator.INFINITE);
// 設(shè)置監(jiān)聽(tīng)器 監(jiān)聽(tīng)值的變化
va.addUpdateListener(new android.animation.ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(android.animation.ValueAnimator valueAnimator) {
// 獲取某一刻的值
angle = (int) valueAnimator.getAnimatedValue();
// 刷新
invalidate();
}
});
// 啟動(dòng)
va.start();
}
@Override
protected void onDraw(Canvas canvas) {
drawFanChart(canvas, Color.BLACK, (float) (angle/360.0),"屬性動(dòng)畫(huà)展開(kāi)的扇形");
}
private void drawFanChart(Canvas canvas,int color,float rate,String text){
//畫(huà)筆
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(57);
paint.setColor(color);
//畫(huà)扇形
int endAngle = (int) (360*rate);// 新繪制的扇形endAngle都在增大
canvas.drawArc(50,0,450,400, 0,endAngle, true,paint);
canvas.drawText(text,550,300,paint);
}
}
(四)xml(使用LinearLayout)
<com.example.test.FanAnimation
android:id="@+id/click"
android:layout_width="wrap_content"
android:layout_height="250dp"/>
<com.example.test.AutoFanAnimation
android:layout_width="wrap_content"
android:layout_height="200dp"/>
<com.example.test.ValueAnimator
android:layout_width="wrap_content"
android:layout_height="220dp"/>