Canvas是一个容器,如果把Canvas理解成画板,那么我们的“层”就像张张夹在画板上的透明的纸,而这些纸对应到Android则是一个个封装在Canvas中的Bitmap。
除了save()方法Canvas还给我们提供了一系列的saveLayerXXX方法给我们保存画布,与save()方法不同的是,saveLayerXXX方法会将所有的操作存到一个新的Bitmap中而不影响当前Canvas的Bitmap,而save()方法则是在当前的Bitmap中进行操作,并且只能针对Bitmap的形变和裁剪进行操作,saveLayerXXX方法则无所不能
让蓝色、红色方块同时旋转
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.customview.MainActivity" > <com.example.customview.CustomeView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
package com.example.customview; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
package com.example.customview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class CustomeView extends View { private Paint mPaint;// 画笔对象 private int mViewWidth, mViewHeight;// 控件宽高 public CustomeView(Context context, AttributeSet attrs) { super(context, attrs); // 实例化画笔对象并设置其标识值 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { /* * 获取控件宽高 */ mViewWidth = w; mViewHeight = h; } @Override protected void onDraw(Canvas canvas) { canvas.rotate(30); /* * 绘制一个红色矩形 */ mPaint.setColor(Color.RED); canvas.drawRect(mViewWidth / 2F - 200, mViewHeight / 2F - 200, mViewWidth / 2F + 200, mViewHeight / 2F + 200, mPaint); /* * 保存画布并绘制一个蓝色的矩形 */ canvas.save(); mPaint.setColor(Color.BLUE); canvas.drawRect(mViewWidth / 2F - 100, mViewHeight / 2F - 100, mViewWidth / 2F + 100, mViewHeight / 2F + 100, mPaint); canvas.restore(); } }
save()和restore()是用来规定操作的范围的。
如果有save()和restore(),那么平移、缩放、旋转等操作只对save()和restore()作用域之间的代码有效。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响
让蓝色方块旋转
@Override protected void onDraw(Canvas canvas) { /* * 绘制一个红色矩形 */ mPaint.setColor(Color.RED); canvas.drawRect(mViewWidth / 2F - 200, mViewHeight / 2F - 200, mViewWidth / 2F + 200, mViewHeight / 2F + 200, mPaint); /* * 保存画布并绘制一个蓝色的矩形 */ canvas.save(); mPaint.setColor(Color.BLUE); // 旋转画布 canvas.rotate(30); canvas.drawRect(mViewWidth / 2F - 100, mViewHeight / 2F - 100, mViewWidth / 2F + 100, mViewHeight / 2F + 100, mPaint); canvas.restore(); }
@Override protected void onDraw(Canvas canvas) { /* * 绘制一个红色矩形 */ mPaint.setColor(Color.RED); canvas.drawRect(mViewWidth / 2F - 200, mViewHeight / 2F - 200, mViewWidth / 2F + 200, mViewHeight / 2F + 200, mPaint); /* * 保存画布并绘制一个蓝色的矩形 */ canvas.saveLayer(0, 0, mViewWidth, mViewHeight, null, Canvas.ALL_SAVE_FLAG); mPaint.setColor(Color.BLUE); // 旋转画布 canvas.rotate(30); canvas.drawRect(mViewWidth / 2F - 100, mViewHeight / 2F - 100, mViewWidth / 2F + 100, mViewHeight / 2F + 100, mPaint); canvas.restore(); }
@Override protected void onDraw(Canvas canvas) { /* * 绘制一个红色矩形 */ mPaint.setColor(Color.RED); canvas.drawRect(mViewWidth / 2F - 200, mViewHeight / 2F - 200, mViewWidth / 2F + 200, mViewHeight / 2F + 200, mPaint); /* * 保存画布并绘制一个蓝色的矩形 */ canvas.saveLayerAlpha(mViewWidth / 2F - 100, mViewHeight / 2F - 100, mViewWidth / 2F + 100, mViewHeight / 2F + 100, 0x55, Canvas.ALL_SAVE_FLAG); mPaint.setColor(Color.BLUE); // 旋转画布 canvas.rotate(5); canvas.drawRect(mViewWidth / 2F - 100, mViewHeight / 2F - 100, mViewWidth / 2F + 100, mViewHeight / 2F + 100, mPaint); canvas.restore(); }