给定任何形状(实心圆、星形、三角形、带透明区域的位图等),我想知道是否有可能(使用最新的 Android API)知道用户是否点击了视图,或者在视图之外.
例如,如果我有一个圆形按钮,我想知道用户是否点击了圆圈内,而不是在圆圈外。
是否可以?
如果不是,也许我可以轮询触摸事件的像素,如果它是透明的,则忽略它,如果不是,将其作为点击事件处理?
给定任何形状(实心圆、星形、三角形、带透明区域的位图等),我想知道是否有可能(使用最新的 Android API)知道用户是否点击了视图,或者在视图之外.
例如,如果我有一个圆形按钮,我想知道用户是否点击了圆圈内,而不是在圆圈外。
是否可以?
如果不是,也许我可以轮询触摸事件的像素,如果它是透明的,则忽略它,如果不是,将其作为点击事件处理?
ImageView image=(ImageView) findViewById(R.id.imageView1);
image.setOnTouchListener(this);
Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int pixel = bitmap.getPixel((int)event.getX(), (int)event.getY());
int alphaValue=Color.alpha(pixel);
return true;
}
通过这种方式,您可以获得所触摸像素的 alpha 值。现在您可以轻松检查触摸的像素是否透明。
我也想做类似的事情,最后我用 FrameLayout 进行了调整。FrameLayout 允许您在彼此之上添加多个视图。
添加一个框架布局。在其中您可以添加一个“视图”并将其高度和宽度设置为 match_parent。在视图顶部,添加您想要的按钮。
然后在您的代码中,获取 View 的引用并在其上设置 onClickListener 以便每当用户触摸该 View 时,您就可以处理该事件。在其他按钮上设置点击侦听器。
现在只需处理您的触摸事件。您现在将知道用户是否单击了按钮或按钮外部(用户单击了视图)。
如果要创建透明或半透明按钮,请查看https://stackoverflow.com/a/11689915/1117338。我希望这有帮助。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout root = (FrameLayout)findViewById(R.id.root);
root.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == ID){
// Your code
}
return true;
}
});
}
好的,我找到了适用于任何类型视图的有效解决方案。
一些注意事项:
遗憾的是,它使用了视图大小的位图,但只使用了很短的时间。
之后,它保持在可见区域上的位置和可见区域之外的位置。
我可以通过制作一个带有标志的整数数组来使其对内存更加友好。目前它是一个简单的布尔数组。
我可以改为在 JNI 中检查位图的 alpha 值,并避免我将位图和数组放在一起的(短)时间。
如果有人可以帮助使它变得更好,那真的很棒。
这是代码:
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);
}
}
如果 imageView 已经将它的 width&height 设置为 wrap_content,并且它确实得到了它需要的大小,那么只有这样你才能使用Adnan Zahid 解决方案,它可以这样写:
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;
}
});
}
}
编辑:替代 runJustBeforeBeingDrawn:https ://stackoverflow.com/a/28136027/878126