在Android的拖动一个圆圈在它使图像的下方圆圈、拖动、它使、图像

2023-09-04 03:52:07 作者:琉璃眸倾城泪

在我的实现,我有两个图像,一是奠定了对方。正如,我动了一圈对象,可在最上面的图片,我想打圆圈transperent内的区域,这样我就可以看到下面的图像。比如我有两个图像 - 一辆汽车的图像和框架的形象。我覆盖汽车形象在framweork形象,为我拖累了一圈过车的形象,应该显示下框架。

In my implementation, I have two images, one layed over the other. As, I move a circle object over the top image, I want to make that area inside circle transperent, so that I can see the beneath image. For example I have two images - a car image and its framework image. I overlay car image over framweork image and as i drag a circle over car image, it should show the beneath framework.

我试着搜索了很多,但没有得到任何指针。某处我读,我需要使用porterduff和xfermode使用阿尔法蒙或图像屏蔽。但我不明白。

I tried to search a lot but not getting any pointers. Somewhere I read that I need to use alpha masking or image masking using porterduff and xfermode. but I did not understand.

具体而言,

我怎样才能让上面的图片transperent,我怎么只能打圆圈transperent内的区域?

How can I make the above image transperent and how can I only make the area inside circle transperent?

感谢您

推荐答案

我已经用有用的投入问题PorterduffXfermode:清除位图的一个部分。在下面的例子中,接触面积变透明,它是可以观察到 down_image up_image 部分(包括图像在资源只是JPG可绘制)。

I've used helpful inputs from the question PorterduffXfermode: Clear a section of a bitmap. In the example below, touch area becomes 'transparent' and it's possible to observe down_image part beneath up_image (both images are just jpg drawables in resources).

基本上有两种可能的实现方式:

Basically there's two possible implementations:

禁用绘图硬件加速这将使 PorterDuff.Mode.CLEAR 使视图透明的(指的这里了解更多详细的硬件加速效果):

Disabling hardware acceleration of drawing which would make PorterDuff.Mode.CLEAR to make view transparent (refer to here for more details about hardware acceleration effects):

活动:

public class MyActivity extends Activity {
    /** Overlay image */
    private DrawingView mDrawingView = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT);

        // Create the view for the xfermode test
        mDrawingView = new DrawingView(this);

        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        mDrawingView.setLayoutParams(params);

        final RelativeLayout relativeLayout = new RelativeLayout(this);

        relativeLayout.setBackgroundResource(R.drawable.down_image);
        relativeLayout.addView(mDrawingView);

        // Main part of the implementation - make layer drawing software
        if (android.os.Build.VERSION.SDK_INT >= 11) {
            mDrawingView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

        // Show the layout with the test view
        setContentView(relativeLayout);
    }
}

DrawingView:

/**
 * View which makes touch area transparent
 */
public class DrawingView extends View {
    /**  Paint to clear touch area */
    private Paint mClearPaint = null;
    /** Main bitmap */
    private Bitmap mBitmap = null;

    /** X coordinate of touch circle */
    private int mXTouch = -1;
    /** Y coordinate of touch circle */
    private int mYTouch = -1;
    /** Radius of touch circle */
    private int mRadius = 0;

    /**
     * Default constructor
     *
     * @param ct {@link Context}
     */
    public DrawingView(final Context ct) {
        super(ct);

        // Generate bitmap used for background
        mBitmap = BitmapFactory.decodeResource(ct.getResources(), R.drawable.up_image);

        // Generate array of paints
        mClearPaint = new Paint();
        mClearPaint.setARGB(255, 255, 255, 0);
        mClearPaint.setStrokeWidth(20);
        mClearPaint.setStyle(Paint.Style.FILL);

        // Set all transfer modes
        mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        mRadius = getResources().getDimensionPixelSize(R.dimen.radius);
    }

    @Override
    public void onDraw(final Canvas canv) {
        // Background colour for canvas
        canv.drawColor(Color.argb(255, 0, 0, 0));

        // Draw the bitmap leaving small outside border to see background
        canv.drawBitmap(mBitmap, null, new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()), null);

        // Loop, draws 4 circles per row, in 4 rows on top of bitmap
        // Drawn in the order of mClearPaint (alphabetical)
        if (mXTouch > 0 && mYTouch > 0) {
            canv.drawCircle(mXTouch, mYTouch, mRadius, mClearPaint);
        }
    }

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        boolean handled = false;

        // get touch event coordinates and make transparent circle from it
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                mXTouch = (int) event.getX();
                mYTouch = (int) event.getY();
                // TODO: Note, in case of large scene it's better not to use invalidate without rectangle specified
                invalidate();
                handled = true;
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
                mXTouch = -1;
                mYTouch = -1;
                // TODO: Note, in case of large scene it's better not to use invalidate without rectangle specified
                invalidate();
                handled = true;
                break;

            default:
                // do nothing
                break;
        }

        return super.onTouchEvent(event) || handled;
    }
}

采用这种solution,不过貌似这取决于Android版本,因为建议的解决方案还没有工作的我的4.2设备都没有。

Adopt this solution, but looks like it depends on Android version, because suggested solution hasn't worked on mine 4.2 device at all.