2011-11-23

Drawable#getTransparentRegion on Android (in case of BitmapDrawable)

Drawable#getTransparentRegion is not implemented at all in Android SDK. So we have to override and implement all by my self.

Here is an altenative answer with overriding Button class to avoid firing onClick method when tap transparent regions of a background image.

Strategy Overview


The code of TransparentImageButton


class TransparentImageButton extends Button{

 private View mCovering;

 public void setCoveringView(View cListener){
  mCovering = cListener;
 }

 /**
  * - Call onClick indirectly(super.onTouchEvent()->(in super class) performClick())
  * - In some cases, this may throw StackOverflowException.
  */
 @Override
 public boolean onTouchEvent(MotionEvent cEvent){
  switch(cEvent.getAction()){
   case MotionEvent.ACTION_DOWN:{
    // obtain the current background drawable
    Drawable cCurrentDrawable = super.getBackground().getCurrent();
    if(cCurrentDrawable instanceof BitmapDrawable){
     
     Bitmap cBmp = null;
     
     if(cCurrentDrawable instanceof BitmapDrawable){
      // cast the BitmapDrawable data into cBmp
      cBmp = ((BitmapDrawable) cCurrentDrawable).getBitmap();
     }

     // check whether the dot in drawable at the touched point is transparent or not
     if(null != cBmp && cBmp.getPixel((int)cEvent.getX(), (int)cEvent.getY()) != 0){
      // if not
      mIsPreviousTarget = true;
      return super.onTouchEvent(cEvent);
     }else{
      // if transparent
      mIsPreviousTarget = false;
      if(null != mCovering){
       return mCovering.onTouchEvent(cEvent);
      }
     }
    }
    break;
   }
   default:
    if(mIsPreviousTarget){
     super.onTouchEvent(cEvent);
    }else{
     if(null != mCovering){
      return mCovering.onTouchEvent(cEvent);
     }
    }
    break;
  }
  return false;
 }
 private boolean mIsPreviousTarget = false;

}

2 comments:

  1. hai,

    I also got surprised with getTransparentRegion() not being implemented at all, in one of my apps..I have to get the transparent region of a drawable..Is there any other way for this?

    thanx

    ReplyDelete
  2. @Bhaskar teja

    After I tried more, I found the following code seem to be more general.

    // Generate a bitmap as the base of drawing.
    // The constant of 3rd arguments must be contains A(alpha channel)
    // (getBottom() etc.. are the method of Button class)
    cBmp = Bitmap.createBitmap(
    getBottom() - getTop(), getRight() - getLeft(),
    Bitmap.Config.ARGB_4444
    );
    // Draw a drawable on the bitmap.
    cDrawable.draw(new Canvas(cBmp));

    // Check whether an arbitrary position is transparent or not.
    // Specify the check position in first(X) and second(Y) arguments of Bitmap#getPixel
    if(null != cBmp &&
    (cEvent.getY() < cBmp.getHeight() && cEvent.getX() < cBmp.getWidth()) &&
    cBmp.getPixel((int)cEvent.getX(), (int)cEvent.getY()) != 0)
    {
    // If the checked position is transparent
    }


    It worked fine for me with even 9-patch drawable.
    I think the above code works in class methods extended from Drawable.
    In Drawable, it is getBounds().height() that nealy equals to getBottom() - getTop().

    ReplyDelete