android - 在 android ImageView 上创建一个 "drag and clear mask"

标签 android image-processing view imageview touch

让我解释一下这是什么意思:

首先有两个相同大小的 ImageView ,第一个是 mask ,它重叠在第二个是照片上。

pusdeo 布局

<RelativeLayout>
<image view  (mask) match parent>
<image view (photo) match parent>
</RelativeLayout>

因此,当应用程序启动时,它是一个完整的黑色页面。然后用户开始在屏幕上拖动,就像扫出面具并显示面具后面的照片。示例照片是这样的:

enter image description here

只关注最上面的图片,看起来像这样,照片上面有一个 mask ,只有当用户在屏幕上拖动时,它才会清除 mask 并显示后面的照片。如何实现,我需要使用 cavans/其他库吗?

感谢帮助

最佳答案

这是一个代码示例。重要的部分是 1)它使用与 ImageView 重叠的自定义 View ; 2)它使用位图 Canvas 进行实际绘图(需要才能清除像素); 3)绘画使用了特殊的CLEAR传输模式。

输出:

enter image description here

绘图 View .java:

package com.example.drawingwithmask;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class DrawView extends View implements OnTouchListener {

    private Paint bmPaint = new Paint();
    private Paint drawPaint = new Paint();
    private Path path = new Path();
    private Canvas cv = null;
    private Bitmap bm = null;
    private boolean firstTimeThru = true;


    public DrawView(Context context) {
        super(context);
        init();
    }

    public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public void init() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setOnTouchListener(this);
}

    @Override
    public void onDraw(Canvas canvas) {
        // Set everything up the first time anything gets drawn:
        if (firstTimeThru) {
            firstTimeThru = false;

            // Just quickly fill the view with a black mask:
            canvas.drawColor(Color.BLACK);

            // Create a new bitmap and canvas and fill it with a black mask:
            bm = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888);
            cv = new Canvas();
            cv.setBitmap(bm);
            cv.drawColor(Color.BLACK);

            // Specify that painting will be with fat strokes:
            drawPaint.setStyle(Paint.Style.STROKE);
            drawPaint.setStrokeWidth(canvas.getWidth() / 15);

            // Specify that painting will clear the pixels instead of paining new ones:
            drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        }

        cv.drawPath(path, drawPaint);
        canvas.drawBitmap(bm, 0,  0, bmPaint);

        super.onDraw(canvas);
    }

    public boolean onTouch(View view, MotionEvent event) {
        float xPos = event.getX();
        float yPos = event.getY();

        switch (event.getAction()) {

        // Set the starting position of a new line:
        case MotionEvent.ACTION_DOWN:
            path.moveTo(xPos, yPos);
            return true;

        // Draw a line to the ending position:
        case MotionEvent.ACTION_MOVE:
            path.lineTo(xPos, yPos);
            break;

        default:
            return false;
        }

        // Call onDraw() to redraw the whole view:
        invalidate();
        return true;}
}

Activity 布局:

<ImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/ic_launcher" />

<com.example.drawingwithmask.DrawView
    android:id="@+id/draw"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

主 Activity .java:

包 com.example.drawingwithmask;

导入android.app.Activity; 导入 android.os.Bundle;

public class MainActivity extends Activity {
    DrawView drawView = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);

        drawView = (DrawView) findViewById(R.id.draw);
    }
}

附录:

这里有一种方法可以估计是否已达到特定的 mask 清除阈值。我通过从 MOTION_MOVE 事件案例中调用 checkProgress() 来测试它。这可能不是最好的方法,甚至可能不是好的方法,但它至少以 STEPS^2(呈现的 400)像素检查为代价提供了估计。

final int STEPS = 20;
final double THRESHOLD = 0.70;

private void checkProgress() {

    int sum = 0;
    for (int x = 0; x < bm.getWidth(); x += bm.getWidth() / STEPS)
        for (int y = 0; y < bm.getHeight(); y += bm.getHeight() / STEPS)
            if (bm.getPixel(x, y) != Color.BLACK)
                sum++;

    double progress = (double) sum / (STEPS * STEPS);
    Log.v(TAG, "Cleared: " + progress);

    if (progress >= THRESHOLD)
        Log.i(TAG, "Done!");
}

关于android - 在 android ImageView 上创建一个 "drag and clear mask",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25502258/

相关文章:

android - 如何修复 Android Studio 中的 Flutter doctor 错误

启用/禁用 wifi 时 Android 应用程序崩溃

image-processing - FFT 卷积 - 非常低的 PSNR

java - 如何从 strings.xml 文件向数组插入字符串

android - 网站背景图像在 PC 上运行完美,但它们不会出现在移动设备上

r - 如何在不加载内存文件的情况下以像素为单位获取图像宽度和高度

matlab - 使用 matlab 计算图像中的圆形对象

当 View 显示时 Android View.isShown() 返回 false

python - django按当前用户过滤投票

PostgreSQL 查看嵌入的 if 语句