Android 高级UI9 Canvas save和restor

作者: 香沙小熊 | 来源:发表于2019-03-09 20:59 被阅读14次

    Android 高级UI 目录

    自己定义控件时经常遇到重写View的draw()方法,draw()方法经常设计到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 高级UI9 Canvas save和restor

        本文链接:https://www.haomeiwen.com/subject/aslouqtx.html