需要图片集和源码请点赞关注收藏后评论区留言~~~
一、画布的绘图层次
画布Canvas上的绘图层次都是在同一个图层上进行的,这意味着如果存在重叠区域,后面绘制的图形就必然覆盖前面的图形。绘图是比较复杂的事情,不是直接覆盖这么简单,有些特殊的绘图操作往往需要做与或非等运算。
Android给画布的图层显示指定了许多规则,详细的图层显示规则如下图
当然 光看图层规则的文案还是比较令人费解 下面我们看直观的效果,圆圈是先绘制的下层图形,正方形是后绘制的上层图形,图例展示了运用不同规则时的显示画面
具体到编码而言 需要在当前画布之外再准备一个遮罩画布,遮罩画布绘制上层图形,而当前画布绘制下层图形,同时指定两个画布的混合图层模式,并根据该模式在当前画布盖上遮罩画布
然后在布局文件中添加LayerView节点,并在对应的活动页面调用setMode方法设置绘图模式,运行并测试该App,可观察到图层覆盖效果
代码如下
Java类
package com.example.animation; import androidx.appcompat.app.AppCompatActivity; import android.graphics.PorterDuff; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import com.example.animation.widget.LayerView; public class DrawLayerActivity extends AppCompatActivity { private LayerView lv_mode; // 声明一个层次视图对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_draw_layer); lv_mode = findViewById(R.id.lv_mode); initLayerSpinner(); // 初始化绘图层次类型下拉框 } // 初始化绘图层次类型下拉框 private void initLayerSpinner() { ArrayAdapter<String> modeAdapter = new ArrayAdapter<>(this, R.layout.item_select, descArray); Spinner sp_mode = findViewById(R.id.sp_mode); sp_mode.setPrompt("请选择绘图层次类型"); sp_mode.setAdapter(modeAdapter); sp_mode.setOnItemSelectedListener(new ModeSelectedListener()); sp_mode.setSelection(0); } private String[] descArray = { "只显示轮廓", "SRC 只显示上层图形", "DST 只显示下层图形", "SRC_OVER 重叠部分由上层遮盖下层", "DST_OVER 重叠部分由下层遮盖上层", "SRC_IN 只显示重叠部分的上层图形", "DST_IN 只显示重叠部分的下层图形", "SRC_OUT 只显示上层图形的未重叠部分", "DST_OUT 只显示下层图形的未重叠部分", "SRC_ATOP 只显示上层图形区域,但重叠部分显示下层图形", "DST_ATOP 只显示下层图形区域,但重叠部分显示上层图形", "XOR 不显示重叠部分,其余部分正常显示", "DARKEN 重叠部分按颜料混合方式加深,其余部分正常显示", "LIGHTEN 重叠部分按光照重合方式加亮,其余部分正常显示", "MULTIPLY 只显示重叠部分,且重叠部分的颜色混合加深", "SCREEN 过滤重叠部分的深色,其余部分正常显示"}; private PorterDuff.Mode[] modeArray = { PorterDuff.Mode.CLEAR, PorterDuff.Mode.SRC, PorterDuff.Mode.DST, PorterDuff.Mode.SRC_OVER, PorterDuff.Mode.DST_OVER, PorterDuff.Mode.SRC_IN, PorterDuff.Mode.DST_IN, PorterDuff.Mode.SRC_OUT, PorterDuff.Mode.DST_OUT, PorterDuff.Mode.SRC_ATOP, PorterDuff.Mode.DST_ATOP, PorterDuff.Mode.XOR, PorterDuff.Mode.DARKEN, PorterDuff.Mode.LIGHTEN, PorterDuff.Mode.MULTIPLY, PorterDuff.Mode.SCREEN}; class ModeSelectedListener implements AdapterView.OnItemSelectedListener { public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { if (arg2 == 0) { lv_mode.setOnlyLine(); // 只显示线条轮廓 } else { lv_mode.setMode(modeArray[arg2]); // 设置层次视图的绘图模式 } } public void onNothingSelected(AdapterView<?> arg0) {} } }
XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="绘图模式:" android:textColor="@color/black" android:textSize="17sp" /> <Spinner android:id="@+id/sp_mode" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:spinnerMode="dialog" /> </LinearLayout> <com.example.animation.widget.LayerView android:id="@+id/lv_mode" android:layout_width="match_parent" android:layout_height="300dp" android:background="@color/white" /> </LinearLayout>
创作不易 觉得有帮助请点赞关注收藏~~~