ok, i've found a working solution for any type of view.
some notes:
sadly it uses a bitmap of the size of the view, but only for a tiny amount of time.
after that, it holds where it's considered on the visible area and where it's considered outside of the visible area.
i could make it more memory friendly by making an array of integers, which have flags. currently it's a simple boolean array.
i could check the bitmap's alpha values in JNI instead, and avoid having the (short) time where i have both the bitmap and the array together.
if anyone could help making it better, it could be really great.
here's the code:
public class MainActivity extends Activity
{
boolean[] _inVisibleAreaMap;
private int _width,_height;
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View view=findViewById(R.id.imageView1);
view.setDrawingCacheEnabled(true);
runJustBeforeBeingDrawn(view,new Runnable()
{
@Override
public void run()
{
final Bitmap bitmap=view.getDrawingCache();
_width=bitmap.getWidth();
_height=bitmap.getHeight();
_inVisibleAreaMap=new boolean[_width*_height];
for(int y=0;y<_width;++y)
for(int x=0;x<_height;++x)
_inVisibleAreaMap[y*_width+x]=Color.alpha(bitmap.getPixel(x,y))!=0;
view.setDrawingCacheEnabled(false);
bitmap.recycle();
}
});
view.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(final View v,final MotionEvent event)
{
final int x=(int)event.getX(),y=(int)event.getY();
boolean isIn=x>=0&&y>=0&&x<_width&&y<_height;
// if inside bounding box , check if in the visibile area
if(isIn)
isIn=_inVisibleAreaMap[y*_width+x];
if(isIn)
Log.d("DEBUG","in");
else Log.d("DEBUG","out");
return true;
}
});
}
private static void runJustBeforeBeingDrawn(final View view,final Runnable runnable)
{
final ViewTreeObserver vto=view.getViewTreeObserver();
final OnPreDrawListener preDrawListener=new OnPreDrawListener()
{
@Override
public boolean onPreDraw()
{
runnable.run();
final ViewTreeObserver vto=view.getViewTreeObserver();
vto.removeOnPreDrawListener(this);
return true;
}
};
vto.addOnPreDrawListener(preDrawListener);
}
}
in case the imageView has set its width&height to wrap_content, and it really got the size it needs, only then you can use Adnan Zahid solution, which could be written this way:
public class MainActivity extends Activity
{
private int _width,_height;
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image=(ImageView)findViewById(R.id.imageView1);
final Bitmap bitmap=((BitmapDrawable)image.getDrawable()).getBitmap();
_width=bitmap.getWidth();
_height=bitmap.getHeight();
image.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(final View v,final MotionEvent event)
{
final int x=(int)event.getX(),y=(int)event.getY();
boolean isIn=x>=0&&y>=0&&x<_width&&y<_height;
if(isIn)
{
final int pixel=bitmap.getPixel((int)event.getX(),(int)event.getY());
final int alphaValue=Color.alpha(pixel);
isIn=alphaValue!=0;
}
if(isIn)
Log.d("DEBUG","in");
else Log.d("DEBUG","out");
return true;
}
});
}
}
EDIT: Alternative to runJustBeforeBeingDrawn: https://stackoverflow.com/a/28136027/878126