【问题标题】:Making beneath image by dragging a circle over it in android通过在android中拖动一个圆圈来制作下面的图像
【发布时间】:2013-06-25 05:12:04
【问题描述】:

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

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

具体来说,

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

谢谢

【问题讨论】:

    标签: android android-imageview


    【解决方案1】:

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

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

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

      活动:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多