自己定義控件時(shí)經(jīng)常遇到重寫View的draw()方法萝挤,draw()方法經(jīng)常設(shè)計(jì)到save()和restore()這兩個(gè)方法.這兩個(gè)相互匹配出現(xiàn)的猜年,作用是用來(lái)保存畫布的狀態(tài)和取出保存的狀態(tài)的。
save():用來(lái)保存canvas的狀態(tài),save()方法之后的代碼恩敌,能夠調(diào)用canvas的平移瞬测、放縮、旋轉(zhuǎn)、裁剪等操作月趟!
restore():用來(lái)恢復(fù)canvas之前保存的狀態(tài),防止save()方法代碼之后對(duì)canvas運(yùn)行的操作灯蝴。繼續(xù)對(duì)興許的繪制會(huì)產(chǎn)生影響。通過(guò)該方法能夠避免連帶的影響孝宗!
public class MyView extends View {
public MyView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GREEN);
//canvas變換操作不會(huì)對(duì)前面造成影響
canvas.clipRect(new Rect(100, 200, 500, 500));
canvas.drawColor(Color.BLUE);
}
}
canvas.drawColor(Color.GREEN);
//canvas變換操作不會(huì)對(duì)前面造成影響
canvas.clipRect(new Rect(100, 200, 500, 500));
canvas.drawColor(Color.BLUE);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(200,200,500,paint);
我們發(fā)現(xiàn)canvas裁剪產(chǎn)生的畫布穷躁,繪制,不會(huì)對(duì)非裁剪的區(qū)域造成影響因妇。
canvas.drawColor(Color.GREEN);
//保存畫布當(dāng)前的狀態(tài)(保存到畫布棧里面了)
canvas.save();
//canvas變換操作不會(huì)對(duì)前面造成影響
canvas.clipRect(new Rect(100, 100, 500, 500));
canvas.drawColor(Color.BLUE);
//恢復(fù)畫布
canvas.restore();
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(100, 100, 100, paint);
canvas.drawColor(Color.GREEN);
//保存畫布當(dāng)前的狀態(tài)
canvas.save();
//canvas變換操作不會(huì)對(duì)前面造成影響
canvas.clipRect(new Rect(100, 100, 500, 500));
canvas.drawColor(Color.BLUE);
canvas.save();
//恢復(fù)畫布
//canvas.restore();
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(100, 100, 100, paint);
canvas.restore();
paint.setColor(Color.YELLOW);
canvas.drawCircle(150,150,100,paint);
結(jié)論:畫板是以棧的形式進(jìn)行存儲(chǔ)
搜索動(dòng)畫實(shí)際案例
public abstract class BaseController {
public static final int STATE_ANIM_NONE = 0;
public static final int STATE_ANIM_START = 1;
public static final int STATE_ANIM_STOP = 2;
public static final int DEFAULT_ANIM_TIME = 5000;
public static final float DEFAULT_ANIM_STARTF = 0;
public static final float DEFAULT_ANIM_ENDF = 1;
private MySearchView mySearchView;
public int mState = STATE_ANIM_NONE;
public abstract void draw(Canvas canvas,Paint paint);
public void startAnim(){
}
public void resetAnim(){
}
public int getWidth(){
return mySearchView.getWidth();
}
public int getHeight(){
return mySearchView.getHeight();
}
public void setSearchView(MySearchView mySearchView){
this.mySearchView = mySearchView;
}
public float mpro = -1;
public ValueAnimator startViewAnimation(){
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1);
valueAnimator.setDuration(800L);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mpro = (float) animation.getAnimatedValue();
mySearchView.invalidate();
}
});
valueAnimator.start();
mpro = 0;
return valueAnimator;
}
}
繪制類
public class Controller1 extends BaseController {
private String mColor = "#4CAF50";
private int cx, cy, cr;
private RectF mRectF;
private int j = 15;
public Controller1() {
mRectF = new RectF();
}
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.drawColor(Color.parseColor(mColor));
switch (mState) {
case STATE_ANIM_NONE:
drawNormalView(paint, canvas);
break;
case STATE_ANIM_START:
drawStartAnimView(paint, canvas);
break;
case STATE_ANIM_STOP:
// drawNormalView(paint, canvas);
drawStopAnimView(paint, canvas);
break;
}
}
private void drawStopAnimView(Paint paint, Canvas canvas) {
}
private void drawStartAnimView(Paint paint, Canvas canvas) {
canvas.save();
//0~1
if (mpro <= 0.5f) {
/**
* 繪制圓和把手
*/
/**
*
* -360 ~ 0 需要變換的范圍
* 0 ~ 0.5 實(shí)際的變化范圍
* 轉(zhuǎn)換公式:360*(mpro*2-1)
*/
canvas.drawArc(
mRectF,
45,
360 * (mpro * 2 - 1),
false,
paint);
canvas.drawLine(
mRectF.right - j,
mRectF.bottom - j,
mRectF.right + cr - j,
mRectF.bottom + cr - j,
paint);
} else {
/**
* 繪制圓和把手
*/
canvas.drawLine(
mRectF.right - j + cr * (mpro * 2 - 1),
mRectF.bottom - j + cr * (mpro * 2 - 1),
mRectF.right - j + cr,
mRectF.bottom + cr - j,
paint);
}
canvas.drawLine(
(mRectF.right - j + cr) * (1 - mpro * 0.8f),
mRectF.bottom + cr - j,
mRectF.right - j + cr,
mRectF.bottom + cr - j,
paint);
canvas.restore();
mRectF.left = cx - cr + mpro * 250;
mRectF.right = cx + cr + mpro * 250;
mRectF.top = cy - cr;
mRectF.bottom = cy + cr;
}
private void drawNormalView(Paint paint, Canvas canvas) {
cr = getWidth() / 20;
cx = getWidth() / 2;
cy = getHeight() / 2;
mRectF.left = cx - cr;
mRectF.right = cx + cr;
mRectF.top = cy - cr;
mRectF.bottom = cy + cr;
canvas.save();
paint.reset();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
canvas.rotate(45, cx, cy);
canvas.drawLine(cx + cr, cy, cx + cr * 2, cy, paint);
// canvas.drawArc(
// mRectF,
// 0, //起始角度问潭,相對(duì)X軸正方向
// 360, //畫多少角度的弧度
// false, //boolean,false :只用一個(gè)弧度線;true:閉合的邊
// paint);
// canvas.restore();
canvas.drawArc(
mRectF,
0,
360,
false,
paint);
canvas.restore();
}
@Override
public void startAnim() {
super.startAnim();
mState = STATE_ANIM_START;
startViewAnimation();
}
@Override
public void resetAnim() {
// TODO Auto-generated method stub
super.resetAnim();
mState = STATE_ANIM_STOP;
startViewAnimation();
}
}
public class MySearchView extends View {
private Paint mPaint;
private BaseController mController;
public MySearchView(Context context) {
super(context);
}
public MySearchView(Context context,
@Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStrokeWidth(5);
}
public void setController(BaseController controller) {
this.mController = controller;
mController.setSearchView(this);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mController.draw(canvas,mPaint);
}
public void startAnimation(){
if(mController!=null){
mController.startAnim();
}
}
public void resetAnimation(){
if(mController!=null){
mController.resetAnim();
}
}
}
public class MainActivity extends AppCompatActivity {
private MySearchView searchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
searchView = (MySearchView) findViewById(R.id.sv);
searchView.setController(new Controller1());
}
public void start(View view) {
searchView.startAnimation();
}
public void reset(View view) {
searchView.resetAnimation();
}
}