本文来看看如何在视图上挖一个孔,让视图层下层的视图可以展示出来。
核心方法
- clipRect(@NonNull RectF rect, @NonNull Region.Op op)
- clipRect(@NonNull Rect rect, @NonNull Region.Op op)
- clipRect(@NonNull Rect rect)
- clipOutRect(@NonNull Rect rect)
- clipPath(@NonNull Path path, @NonNull Region.Op op)
- clipPath(@NonNull Path path)
- clipOutPath(@NonNull Path path)
参数类型Region.Op为枚举类型,直接影响裁剪区域。
public enum Op {
DIFFERENCE(0),
INTERSECT(1),
UNION(2),
XOR(3),
REVERSE_DIFFERENCE(4),
REPLACE(5);
Op(int nativeInt) {
this.nativeInt = nativeInt;
}
@UnsupportedAppUsage
public final int nativeInt;
}
从API级别**{@value Build.VERSION_CODES#P}开始,只有{@link Region.Op#INTERSECT}**和
{@link Region.Op#DIFFERENCE}是有效的,传入其他参数会抛异常IllegalArgumentException,
如果想测试其他参数,请将build.gradle文件中的targetSdkVersion改为28以下。
各参数区别如下:
- DIFFERENCE:差集(A - A∩B),前面裁剪区域相对于后面裁剪区域的差集,也就是前面的裁剪区域去掉前面的裁剪区域和后面的裁剪区域相交的区域以后,前面裁剪区域剩下的部分
- INTERSECT:交集(A∩B),也就是前面的裁剪区域和后面的裁剪区域相交的区域
- UNION:并集(A∪B),也就是前面的裁剪区域和后面的裁剪区域合并以后的区域
- XOR:对称差集(A∪B - A∩B),前面裁剪区域和后面裁剪区域合并起来的区域去掉相交的区域所得到的区域
- REVERSE_DIFFERENCE:差集(B - A∩B),后面裁剪区域相对于前面裁剪区域的差集,后面的裁剪区域去掉前面的裁剪区域和后面的裁剪区域相交的区域以后,后面的裁剪区域剩下的部分
- REPLACE:直接使用后面的裁剪区域
示例
以下示例展示了视频或者图片裁剪区域选择的控件简单的移动功能。
public class DigHoleView extends View {
private static final int SIZE = 400;
private float mTouchX, mTouchY;
private RectF mHoleRegion = new RectF();
public DigHoleView(Context context) {
this(context, null);
}
public DigHoleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DigHoleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mHoleRegion.set((getMeasuredWidth() - SIZE) / 2.0f, (getMeasuredHeight() - SIZE) / 2.0f, (getMeasuredWidth() + SIZE) / 2.0f, (getMeasuredHeight() + SIZE) / 2.0f);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
// canvas.clipRect(0, 0, getWidth(), getHeight());
canvas.clipRect(mHoleRegion, Region.Op.DIFFERENCE);
canvas.drawColor(Color.argb(190, 0, 0, 0));
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
mTouchX = event.getX();
mTouchY = event.getY();
return mHoleRegion.contains(mTouchX, mTouchY);
} else if (MotionEvent.ACTION_MOVE == event.getAction()) {
float dx = event.getX() - mTouchX;
float dy = event.getY() - mTouchY;
mTouchX = event.getX();
mTouchY = event.getY();
mHoleRegion.offset(dx, dy);
invalidate();
}
return super.onTouchEvent(event);
}
}
感谢大家的支持,如有错误请指正,如需转载请标明原文出处!