0

在我的实现中,我有两张图片,一张叠加在另一张上。因为,我将一个圆形对象移动到顶部图像上,我想让圆形内部的那个区域透明,这样我就可以看到下面的图像。例如,我有两个图像 - 汽车图像及其框架图像。我将汽车图像覆盖在框架图像上,当我在汽车图像上拖动一个圆圈时,它应该显示下面的框架。

我试图搜索很多但没有得到任何指示。在某处我读到我需要使用 alpha 遮罩或使用 porterduff 和 xfermode 的图像遮罩。但我不明白。

具体来说,

我怎样才能使上面的图像透明,我怎样才能只使圆圈内的区域透明?

谢谢你

4

1 回答 1

0

我使用了来自问题PorterduffXfermode: Clear a section of a bitmap 的有用输入。在下面的示例中,触摸区域变为“透明”,并且可以观察down_image下方的部分up_image(两个图像都只是资源中的 jpg 可绘制对象)。

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

  1. 禁用绘图的硬件加速,这将使PorterDuff.Mode.CLEAR视图透明(有关硬件加速效果的更多详细信息,请参阅此处):

    活动:

    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);
        }
    }
    

    绘图视图:

    /**
     * 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;
        }
    }
    
  2. 采用这个解决方案,但看起来它取决于 Android 版本,因为建议的解决方案根本不适用于我的 4.2 设备。

于 2013-07-14T09:49:34.237 回答