Android 创建圆形的ImageView,因此单击将仅在圆形区域上工作
嗨,我正在创建一个应用程序 比如说 它不应在圆外响应,但ImageView是矩形的,因此它正在响应 我相信你能理解这个问题Android 创建圆形的ImageView,因此单击将仅在圆形区域上工作,android,android-layout,android-view,Android,Android Layout,Android View,嗨,我正在创建一个应用程序 比如说 它不应在圆外响应,但ImageView是矩形的,因此它正在响应 我相信你能理解这个问题 ImageView是矩形的,但它的图像是圆形的,但我只想检测单击圆形图像…您可以将视图附加到图像视图。在这种情况下,侦听器只有一个名为OnTouchListener#onTouch(视图v,MotionEvent)的方法。事件参数具有允许获取触摸坐标的方法。 当您获得相对于ImageView大小的触摸坐标时,您可以检查以下不等式是否为true:(x-x0)^2+(y-y0
ImageView是矩形的,但它的图像是圆形的,但我只想检测单击圆形图像…您可以将
视图附加到图像视图。在这种情况下,侦听器只有一个名为OnTouchListener#onTouch(视图v,MotionEvent)
的方法。事件
参数具有允许获取触摸坐标的方法。
当您获得相对于ImageView
大小的触摸坐标时,您可以检查以下不等式是否为true
:(x-x0)^2+(y-y0)^2您似乎必须计算用户是否在圆形视图内触摸。这必须通过覆盖定制ImageView类的touch事件来实现,我假设您已经编写了该类
起初我以为画一个圆形区域就足够了,但事实并非如此
伪代码:
public class CustomImageView implements ImageView
{
private Point centerPoint;
private float radius;
@Override
protected void onDraw(Canvas canvasF)
{
Drawable drawable = getDrawable();
if(centerPoint == null)
{
centerPoint = new Point (getWidth() / 2, getHeight() / 2);
/*
* if radius extends to edges, but if circular code
* exists already then we should already know what the
* radius is at this point I would assume.
*/
radius = getWidth() / 2;
}
/*
* remaining draw code for manipulating a circle.
*/
}
private boolean isInsideCircle(Point touchedPoint)
{
int distance = (int) Math.round(Math.pow(touchedPoint.x - centerPoint.x, 2) + Math.pow(touchedPoint.y - centerPoint.y, 2));
if(distance < Math.pow(radius, 2))
{
return true;
}
else
{
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
Point touchedPoint = new Point(Math.round(event.getX()), Math.round(event.getY()));
if(isInsideCircle(touchedPoint))
{
return super.onTouchEvent(event);
}
return true;
}
}
公共类CustomImageView实现ImageView
{
专用点中心点;
私有浮动半径;
@凌驾
受保护的空白onDraw(帆布画布)
{
Drawable Drawable=getDrawable();
如果(中心点==null)
{
中心点=新点(getWidth()/2,getHeight()/2);
/*
*如果半径延伸到边,但如果圆代码
*已经存在,那么我们应该已经知道
*半径就是我假设的这个点。
*/
半径=getWidth()/2;
}
/*
*用于操作圆的剩余绘图代码。
*/
}
专用布尔值isInsideCircle(点接触点)
{
int距离=(int)Math.round(Math.pow(touchedPoint.x-centerPoint.x,2)+Math.pow(touchedPoint.y-centerPoint.y,2));
if(距离<数学功率(半径,2))
{
返回true;
}
其他的
{
返回false;
}
}
@凌驾
公共布尔onTouchEvent(运动事件)
{
点接触点=新点(Math.round(event.getX()),Math.round(event.getY());
if(isInsideCircle(接触点))
{
返回super.onTouchEvent(事件);
}
返回true;
}
}
现在,我可能会将其添加到ImageView类中,以扩展它,并仅在需要时在图像中提供触摸事件
如果图像一直延伸到边缘,则半径更容易确定。否则,需要做一些额外的工作来计算实际区域的半径。感谢您的支持,基于您的支持,我已经通过下面的方式完成了,它工作得非常完美
ImageView imgView = (ImageView) findViewById(R.id.imageView1);
imgView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//CIRCLE : (x-a)^2 + (y-b)^2 = r^2
float centerX, centerY, touchX, touchY, radius;
centerX = v.getWidth() / 2;
centerY = v.getHeight() / 2;
touchX = event.getX();
touchY = event.getY();
radius = centerX;
System.out.println("centerX = "+centerX+", centerY = "+centerY);
System.out.println("touchX = "+touchX+", touchY = "+touchY);
System.out.println("radius = "+radius);
if (Math.pow(touchX - centerX, 2)
+ Math.pow(touchY - centerY, 2) < Math.pow(radius, 2)) {
System.out.println("Inside Circle");
return false;
} else {
System.out.println("Outside Circle");
return true;
}
}
});
ImageView imgView=(ImageView)findViewById(R.id.imageView1);
imgView.setOnTouchListener(新视图.OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
//圆:(x-a)^2+(y-b)^2=r^2
浮动中心X、中心Y、接触X、接触Y、半径;
centerX=v.getWidth()/2;
centerY=v.getHeight()/2;
touchX=event.getX();
touchY=event.getY();
半径=中心x;
System.out.println(“centerX=“+centerX+”,centerY=“+centerY”);
System.out.println(“touchX=“+touchX+”,touchY=“+touchY”);
System.out.println(“半径=”+半径);
if(数学功率(touchX-centerX,2)
+数学功率(接触中心,2)<数学功率(半径,2)){
System.out.println(“内圆”);
返回false;
}否则{
System.out.println(“外圆”);
返回true;
}
}
});
根据Siddhpura Amit的回答,我刚刚发现,通过这种方法,触摸不会得到ACTION\u CANCEL事件,因此当您移出“内圆”区域时,视图不会保持不变。
我使用了以下变通方法来解决这个问题:
ImageView imgView = (ImageView) findViewById(R.id.imageView1);
imgView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//CIRCLE : (x-a)^2 + (y-b)^2 = r^2
float centerX = v.getWidth() / 2;
float centerY = v.getHeight() / 2;
float touchX = event.getX();
float touchY = event.getY();
float radius = centerX;
Log.d(TAG, "centerX = "+centerX+", centerY = "+centerY);
Log.d(TAG, "touchX = "+touchX+", touchY = "+touchY);
Log.d(TAG, "radius = "+radius);
if (Math.pow(touchX - centerX, 2) + Math.pow(touchY - centerY, 2) < Math.pow(radius, 2)) {
Log.d(TAG, "Inside Circle");
} else {
Log.d(TAG, "Outside Circle");
if (event.getAction() != MotionEvent.ACTION_CANCEL) {
event.setAction(MotionEvent.ACTION_CANCEL);
v.dispatchTouchEvent(event);
return true;
}
}
return false;
}
});
ImageView imgView=(ImageView)findViewById(R.id.imageView1);
imgView.setOnTouchListener(新视图.OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
//圆:(x-a)^2+(y-b)^2=r^2
float centerX=v.getWidth()/2;
浮动中心=v.getHeight()/2;
float touchX=event.getX();
float touchY=event.getY();
浮动半径=中心;
Log.d(标记“centerX=“+centerX+”,centerY=“+centerY”);
Log.d(标签“touchX=“+touchX+”,touchY=“+touchY”);
Log.d(标签“radius=“+radius”);
if(Math.pow(touchX-centerX,2)+Math.pow(touch-centerY,2)
排除图像透明区域的简单解决方案
注意:使用PNG图像
mImageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (view == null) return false;
Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
if (motionEvent.getX() < bmp.getWidth() && motionEvent.getY() < bmp.getHeight()) {
//Get color at point of touch
int color = bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY());
bmp.recycle();
if (color == Color.TRANSPARENT) {
//do not proceed if color is transparent
return false;
} else {
//proceed if color is not transparent
return true;
}
}
}
return false;
}
});
public void setDrawingCache(View view){
view.setDrawingCacheEnabled(true);
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache(true);
}
mImageView.setOnTouchListener(新视图.OnTouchListener(){
@凌驾
公共布尔onTouch(视图、运动事件、运动事件){
if(motionEvent.getAction()==motionEvent.ACTION\u向下){
if(view==null)返回false;
位图bmp=Bitmap.createBitmap(view.getDrawingCache()
public boolean onTouchImageTransparent(View view, MotionEvent motionEvent){
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
if (motionEvent.getX() < bmp.getWidth() && motionEvent.getY() < bmp.getHeight()) {
//Get color at point of touch
int color = bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY());
bmp.recycle();
if (color == Color.TRANSPARENT) {
//do not proceed if color is transparent
Log.d("onTouch","Click on Background PNG");
return false;
} else {
//proceed if color is not transparent
Log.d("onTouch","Click on Image");
return true;
}
}else{
Log.d("onTouch","Click on somewhere else");
return false;
}
}else{
Log.d("onTouch","Click on Background");
}
return false;
}
ImageView mImageView = findViewById(R.id.imageView);
setDrawingCache(mImageView);
mImageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(onTouchImageTransparent(view,motionEvent)){
//action goes here
}
return onTouchImageTransparent(view,motionEvent);
}
});
public class OvalTouchAreaFilter implements View.OnTouchListener {
private boolean mIgnoreCurrentGesture;
public TouchAreaFilter() {
mIgnoreCurrentGesture = false;
}
public boolean isInTouchArea(View view, float x, float y) {
int w = view.getWidth();
int h = view.getHeight();
if(w <= 0 || h <= 0)
return false;
float xhat = 2*x / w - 1;
float yhat = 2*y / h - 1;
return (xhat * xhat + yhat * yhat <= 1);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent event) {
int action = event.getActionMasked();
if(action == MotionEvent.ACTION_DOWN) {
mIgnoreCurrentGesture = !this.isInTouchArea(view, event.getX(), event.getY());
return mIgnoreCurrentGesture;
}
boolean ignoreCurrentGesture = mIgnoreCurrentGesture;
if(action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)
mIgnoreCurrentGesture = false;
return ignoreCurrentGesture;
}
}
View button = findViewById(R.id.my_button);
button.setOnTouchListener(new OvalTouchAreaFilter());