java 如何判断 X 和 Y 坐标是否在我的按钮内?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17931816/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 19:39:32  来源:igfitidea点击:

How to tell if an X and Y coordinate are inside my button?

javaandroid

提问by Liam W

I have managed, with great difficulty, to make a bitmap overlay the screen. I can also get touch input, however it gets touch input for EVERYWHERE on the screen.

我已经很困难地设法使位图覆盖在屏幕上。我也可以获得触摸输入,但是它可以在屏幕上的任何地方获得触摸输入。

I want to know how I would be able to check if the touch was on my bitmap, which is visible on the screen.

我想知道如何检查触摸是否在位图上,位图在屏幕上可见。

The service and view class is below. I have thought and thought, but I couldn't think of a way to do it :(

服务和视图类如下。我想了又想,但我想不出办法来做到这一点:(

package <package>;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;

public class MyService extends Service {
    ButtonView mView;
    Bitmap bit;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        bit = BitmapFactory.decodeResource(getResources(), R.drawable.button);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                this);
        builder.setContentTitle("Ingress Tools Running");
        builder.setContentText("Click to stop Ingress Tools");
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(
                this, StopActivity.class), 0));
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(1, builder.build());

        mView = new ButtonView(this, bit);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FILL_PARENT,
                WindowManager.LayoutParams.FILL_PARENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT;
        params.setTitle("Load Average");
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getBaseContext(), "onDestroy", Toast.LENGTH_LONG).show();
        if (mView != null) {
            ((WindowManager) getSystemService(WINDOW_SERVICE))
                    .removeView(mView);
            mView = null;
        }
    }
}

class ButtonView extends ViewGroup {
    private Paint mLoadPaint;
    private Rect r;
    private Bitmap bit;

    public ButtonView(Context context, Bitmap bit) {
        super(context);
        Toast.makeText(context, "HUDView", Toast.LENGTH_LONG).show();

        mLoadPaint = new Paint();
        mLoadPaint.setAntiAlias(true);
        mLoadPaint.setTextSize(10);
        mLoadPaint.setARGB(255, 255, 0, 0);
        r = new Rect();
        r.set(380, 134, 468, 213);
        this.bit = bit;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //canvas.drawColor(Color.BLACK);

        canvas.drawBitmap(bit, 100, 100, null);
    }

    @Override
    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int area = bit.getWidth() * bit.getHeight();


        //if (event.getY() <= maxY && event.getX() <= maxX) {
            Toast.makeText(getContext(), "Open tools: ", Toast.LENGTH_LONG)
                    .show();

        //}
        return true;

    }
}

回答by AMD

this works for any view

这适用于任何视图

@Override
    public boolean dispatchTouchEvent(MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_UP) {
                if (inViewInBounds(myButtonView, (int) event.getRawX(), (int) event.getRawY())) {
                    // User moved outside bounds
                    Log.e("dispatchTouchEvent", "you touched inside button");
                } else {
                    Log.e("dispatchTouchEvent", "you touched outside button");
                }

        }
        return super.dispatchTouchEvent(event);
    }

 Rect outRect = new Rect();
    int[] location = new int[2];


 private boolean inViewInBounds(View view, int x, int y) {
        view.getDrawingRect(outRect);
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
        return outRect.contains(x, y);
    }

回答by Dmitry Zaytsev

Consider using FrameLayout(or any other subclass of ViewGroup) instead of ViewGroupdirectly. Because your current implementation of onLayoutmethod is not correct, which will lead you to problems with displaying of child views.

考虑使用FrameLayout(或 的任何其他子类ViewGroup)而不是ViewGroup直接使用。因为您当前的onLayout方法实现不正确,这将导致您在显示子视图时出现问题。

Now, closer to your question. You should ininitialize Rectand just store left, top, right and bottom position of your Bitmap. As I can see, currently you're initialized rvariable, but not using it anywhere.

现在,更接近你的问题。您应该初始化Rect并只存储您的Bitmap. 正如我所看到的,目前您已初始化r变量,但未在任何地方使用它。

So, you can initialize it like this:

所以,你可以像这样初始化它:

r = new Rect(100, 100, 100 + bit.getWidth(), 100 + bit.getHeight());

Now in onTouchEventyou can just check:

现在onTouchEvent你可以检查:

r.contains((int) event.getX(), (int) event.getY());

回答by Blackbelt

Rect rect = new Rect(); 
getHitRect(rect);
if (rect.contains((int) event.getX(), (int) event.getY())) {}

you can use getHitRect(Rect). it returns the Hit rectangle in parent's coordinates. Herethe documentation

你可以使用 getHitRect(Rect)。它返回父坐标中的命中矩形。这里的文档

回答by MGorgon

Use if statement with method if(r.contains(x, y))on that button which you want to check. This method will return true, when x and y point is inside rectangle r. You can also make public method within that class, so you can access it outside ButtonView class with button object reference.

if(r.contains(x, y))在要检查的按钮上使用 if 语句和方法。当 x 和 y 点在矩形 r 内时,此方法将返回 true。您还可以在该类中创建公共方法,以便您可以使用按钮对象引用在 ButtonView 类之外访问它。

回答by Sergey Brazhnik

When the "touch event" happens, it's going through all view's tree. F.e. if you have Linear layout and ImageView on it and user touchs the screen on ImageView, then touch event intercepts and firstly it'll be handled at LinearLayour and then at the ImageView.

当“触摸事件”发生时,它会遍历所有视图的树。Fe 如果你有线性布局和 ImageView 并且用户在 ImageView 上触摸屏幕,然后触摸事件拦截,首先它会在 LinearLayour 处理,然后在 ImageView。

If you want to block event f.e. on the bitmap, then you should override onTouchEvent for Bitmap and return true value. This will mean that you handled this event and it won't be available for LinearLayout.

如果要阻止位图上的事件 fe,则应覆盖位图的 onTouchEvent 并返回 true 值。这意味着您处理了此事件,并且它不适用于 LinearLayout。

image.setOnTouchListener( new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                return true;  // attentively read documentation for onTouc interface
            }
        });