自定义视图-马赛克视图
Tags
#Android
这里我是直接继承的ImageView,主要是为了能兼容之前的项目,因为之前是直接用的ImageView。
思路
- 根据原图片生成一个全马赛克的图片
- 监听手势,得到应该显示的马赛克方块的集合
- 根据方块的集合,刷新视图,这里用到了Paint的Xfermode(图片混合模式)
(1). 手势图和全马赛克图混合,在相交处绘制马赛克图
(2). 将上一步的图和原图混合,在相交处绘制上一步的图,在不相交处绘制原图,搞定收工!
效果图
./_image/2020-08-03-16-03-57.jpg
图片混合模式
下图以黄圆为dest,蓝矩为src,展示了各种图片混合模式:
./_image/2020-08-03-16-04-16.jpg
这里以mosaicBitmap为dest,以touchBitmap为src,
设置DST_IN模式:在相交处取dest
canvas.drawBitmap(mosaicBitmap, 0, 0, paint);//dest
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));//设置DST_IN模式
canvas.drawBitmap(touchBitmap, 0, 0, paint);//src
源码
package com.che.carcheck.support.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
/**
* 马赛克视图
* <p/>
* 作者:余天然 on 16/5/30 下午6:04
*/
public class MosaicView extends ImageView {
private Bitmap bitmap;//原图
private Bitmap mosaicBitmap;//全马赛克图
private Bitmap mergeBitmap;//合成图
private int strokeWidth;// 画笔宽度px
private List<Rect> mosaicRects;//马赛克集合
public static final int min_mosaic_block_size = 4;//马赛克的最小粒度
private Paint paint;
public MosaicView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
mosaicRects = new ArrayList<>();
strokeWidth = 20;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
int x = (int) event.getX();
int y = (int) event.getY();
//记录应该显示马赛克的矩形集合
int radius = strokeWidth / 2;
int left = Math.max(x radius, 0);
int right = Math.min(x + radius, bitmap.getWidth());
int top = Math.max(y radius, 0);
int bottom = Math.min(y + radius, bitmap.getHeight());
Rect rect = new Rect(left, top, right, bottom);
mosaicRects.add(rect);
// FIXME: 16/5/30 这里本来打算调用onDraw的,不知道setImageBitmap那里怎么出了问题
// invalidate();
updateMosaicList();
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// doDraw(canvas);
}
private void updateMosaic