自定义视图-马赛克视图

Tags
#Android
这里我是直接继承的ImageView,主要是为了能兼容之前的项目,因为之前是直接用的ImageView。

思路

  1. 根据原图片生成一个全马赛克的图片
  1. 监听手势,得到应该显示的马赛克方块的集合
  1. 根据方块的集合,刷新视图,这里用到了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

© fishyer 2022