Canvas的保存和恢复的demo
2019-08-20 本文已影响9人
凌川江雪
由于篇幅问题,
笔者把文章
6.4 Android绘图技巧(Primary:Canvas & Layer, 附demo-仪表盘、圆形头像、裁剪动画绘制)
的概念demo代码单独迁到这篇文章这里,
欢迎各位小伙伴惠读指教~
先上代码
这个代码一来是记录一个demo,二来是分享一下代码逻辑的设计思路;
activity_main.xml:
就一个带了id的ViewGroup而已:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/ll_nextParent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</LinearLayout>
MainActivity:
主要的功能都写在代码中的注释里了哈~
public class MainActivity extends AppCompatActivity {
private LinearLayout ll_nextParent;
private LinearLayout.LayoutParams layoutParams;
private CanvasTestView canvasTestView;
private int canvasDrawId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件和点击事件
initViews();
//为了方便调试,定义此方法,输入不同的id,显示不同的自定义View
configCustomViews(1);
}
private void initViews() {
canvasDrawId = 0;
ll_nextParent = findViewById(R.id.ll_nextParent);
layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
testTheCanvas();
}
private void configCustomViews(int drawId) {
switch (drawId) {
case 0:
SpiderView spiderViewOri = new SpiderView(this);
ll_nextParent.addView(spiderViewOri, layoutParams);
break;
case 1:
canvasTestView = new CanvasTestView(this);
ll_nextParent.addView(canvasTestView, layoutParams);
break;
default:
}
}
//这个方法加在initView中,测试canvas的存取
private void testTheCanvas(){
ll_nextParent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
canvasTestView.setDrawId(canvasDrawId);
canvasDrawId ++ ;
}
});
ll_nextParent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
canvasDrawId = 0;
canvasTestView.setDrawId(canvasDrawId);
return false;
}
});
}
}
自定义的CanvasTestView:
-
整个demo的设计思路就是,
把不同的绘制调试代码分别顺序写在case中,
通过MainActivity的点击事件,点击一下就更新全局id,然后重绘,
重绘的时候就会因为id的更新而选择下一套绘制代码进行绘制,
绘制出不同的内容: -
设置一个全局drawId
通过点击事件更改drawId,并重绘
重绘制时根据改变了的不同的drawId
绘制不同的图像
public class CanvasTestView extends View {
private int drawId;
public CanvasTestView(Context context) {
super(context);
drawId = 0;
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
public CanvasTestView(Context context, AttributeSet attrs) {
super(context, attrs);
drawId = 0;
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
public void setDrawId(int drawId) {
this.drawId = drawId;
postInvalidate();
}
public void resetDrwaId() {
drawId = 0;
postInvalidate();
}
/**
* 设置一个全局drawId
* 通过点击事件更改drawId,并重绘
* 重绘制时根据改变了的不同的drawId
* 绘制不同的图像
*
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (drawId) {
case 0:
canvas.drawColor(Color.RED);
canvas.save();
break;
case 1:
canvas.drawColor(Color.RED);
canvas.save();
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
break;
case 2:
canvas.drawColor(Color.RED);
canvas.save();
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
canvas.restore();
canvas.drawColor(Color.BLUE);
break;
case 3:
draw1ColorAnd4Rect(canvas);
break;
case 4:
draw1ColorAnd4Rect(canvas);
canvas.restore();
canvas.drawColor(Color.YELLOW);
break;
case 5:
draw1ColorAnd4Rect(canvas);
canvas.restore();
canvas.restore();
canvas.restore();
canvas.drawColor(Color.YELLOW);
break;
case 6:
draw1ColorAnd4Rect(canvas);
break;
case 7:
draw1ColorAnd4RectWithCount(canvas);
break;
}
}
//抽取相同部分代码
private void draw1ColorAnd4Rect(Canvas canvas) {
canvas.drawColor(Color.RED);
canvas.save();
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
canvas.save();
canvas.clipRect(new Rect(200,200,700,700));
canvas.drawColor(Color.BLUE);
canvas.save();
canvas.clipRect(new Rect(300,300,600,600));
canvas.drawColor(Color.BLACK);
canvas.save();
canvas.clipRect(new Rect(400,400,500,500));
canvas.drawColor(Color.WHITE);
}
//抽取代码
private void draw1ColorAnd4RectWithCount(Canvas canvas) {
canvas.drawColor(Color.RED);
int c1 = canvas.save();
canvas.clipRect(new Rect(100, 100, 800, 800));
canvas.drawColor(Color.GREEN);
int c2 = canvas.save();
canvas.clipRect(new Rect(200,200,700,700));
canvas.drawColor(Color.BLUE);
int c3 = canvas.save();
canvas.clipRect(new Rect(300,300,600,600));
canvas.drawColor(Color.BLACK);
int c4 = canvas.save();
canvas.clipRect(new Rect(400,400,500,500));
canvas.drawColor(Color.WHITE);
canvas.restoreToCount(c2);
canvas.drawColor(Color.YELLOW);
}
}
效果图:
-
点击一次,重绘一次,切换一套绘制代码,(drawId++)
长按则从头开始,(drawId = 0)
结合效果图,
我们可以体会到Canvas的保存和恢复相关的三个方法的作用和使用过程: