Android 高階UI9 Canvas save和restore例項解析
save():用來儲存canvas的狀態,save()方法之後的程式碼,能夠呼叫canvas的平移、放縮、旋轉、裁剪等操作! restore():用來恢復canvas之前儲存的狀態,防止save()方法程式碼之後對canvas執行的操作。繼續對興許的繪製會產生影響。透過該方法能夠避免連帶的影響!
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變換操作不會對前面造成影響
canvas.clipRect(new Rect(100, 200, 500, 500));
canvas.drawColor(Color.BLUE);
}
}
複製程式碼
canvas.drawColor(Color.GREEN);
//canvas變換操作不會對前面造成影響
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);
複製程式碼
我們發現canvas裁剪產生的畫布,繪製,不會對非裁剪的區域造成影響。
canvas.drawColor(Color.GREEN);
//儲存畫布當前的狀態(儲存到畫布棧裡面了)
canvas.save();
//canvas變換操作不會對前面造成影響
canvas.clipRect(new Rect(100, 100, 500, 500));
canvas.drawColor(Color.BLUE);
//恢復畫布
canvas.restore();
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(100, 100, 100, paint);
複製程式碼
canvas.drawColor(Color.GREEN);
//儲存畫布當前的狀態
canvas.save();
//canvas變換操作不會對前面造成影響
canvas.clipRect(new Rect(100, 100, 500, 500));
canvas.drawColor(Color.BLUE);
canvas.save();
//恢復畫布
//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);
複製程式碼
結論:畫板是以棧的形式進行儲存
搜尋動畫實際案例
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 實際的變化範圍
* 轉換公式: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, //起始角度,相對X軸正方向
// 360, //畫多少角度的弧度
// false, //boolean,false :只用一個弧度線;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();
}
}
複製程式碼
更多Android技術分享可以關注@我,也可以加入QQ群號:1078469822,學習交流Android開發技能。
作者:冬日毛毛雨
來源:掘金
商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69983917/viewspace-2794283/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- canvas save()和restore()CanvasREST
- canvas restore()CanvasREST
- canvas save()Canvas
- canvas translate()、scale()和rotate()方法程式碼例項Canvas
- canvas 例項之鬧鐘Canvas
- Android外掛化快速入門與例項解析(VirtualApk)AndroidAPK
- canvas刮刮樂程式碼例項Canvas
- canvas載入效果程式碼例項Canvas
- canvas繪製扇形程式碼例項Canvas
- Canvas中的剪刀手講解與實戰——Android高階UICanvasAndroidUI
- Canvas中的繪圖師講解與實戰——Android高階UICanvas繪圖AndroidUI
- canvas原型鐘錶效果程式碼例項Canvas原型
- canvas繪製網格程式碼例項Canvas
- canvas氣泡上浮效果程式碼例項Canvas
- 高階單例模式單例模式
- Argo 安裝和 workflow 例項配置檔案解析Go
- jQuery Ajax 例項 全解析jQuery
- Android探索之旅 | AIDL原理和例項講解AndroidAI
- Golang中命名引數的高階使用技巧與例項分析Golang
- canvas繪製機器貓程式碼例項Canvas
- canvas繪製拋物線程式碼例項Canvas線程
- canvas繪製箭頭效果程式碼例項Canvas
- MyCat分片:水平拆分例項解析和程式碼實現!
- npm install -save 和 -save-devNPMdev
- Vue原始碼解析:Vue例項Vue原始碼
- java狀態模式例項解析Java模式
- Web安全之CSRF例項解析Web
- [Android]Gank 元件化例項AppAndroid元件化APP
- canvas繪製圓形鐘錶程式碼例項Canvas
- 探索高階 JVM 選項JVM
- 類和例項
- React 穿透獲取被高階元件裝飾的目標元件例項React穿透元件
- Android高階知識點Android
- 高階 Android 工程師的進階之路Android工程師
- 解析JavaScript設計模型Iterator例項JavaScript模型
- Mybatis原始碼解析2—— 例項搭建MyBatis原始碼
- python 類和例項Python
- 高可用架構例項:在多雲和多區域中穿行架構