我已经非常困难地设法在屏幕上叠加位图。我也可以获得触摸输入,但是它会在屏幕上为每个地方提供触摸输入。
我想知道如何检查触摸是否在我的位图上,这在屏幕上是可见的。
服务和视图类如下。我有想过和想过,但我想不出办法:(
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;
}
}
答案 0 :(得分:15)
考虑直接使用FrameLayout
(或ViewGroup
的任何其他子类)而不是ViewGroup
。因为您当前的onLayout
方法实现不正确,这会导致显示子视图时出现问题。
现在,更接近你的问题了。您应该初始化Rect
并仅存储Bitmap
的左侧,顶部,右侧和底部位置。我可以看到,目前您已初始化r
变量,但未在任何地方使用它。
所以,你可以像这样初始化它:
r = new Rect(100, 100, 100 + bit.getWidth(), 100 + bit.getHeight());
现在在onTouchEvent
,您可以查看:
r.contains((int) event.getX(), (int) event.getY());
答案 1 :(得分:13)
Rect rect = new Rect();
getHitRect(rect);
if (rect.contains((int) event.getX(), (int) event.getY())) {}
你可以使用getHitRect(Rect)。它返回父坐标中的Hit矩形。 Here文档
答案 2 :(得分:13)
这适用于任何视图
@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);
}
答案 3 :(得分:1)
在要检查的按钮上使用带有方法if(r.contains(x, y))
的if语句。当x和y点在矩形r内时,此方法将返回true。您还可以在该类中创建公共方法,因此您可以使用按钮对象引用在ButtonView类外部访问它。
答案 4 :(得分:0)
// We assume MotionEvent is from the direct View parent so we are in the same co-ordindate space
fun View.isWithinBounds(event: MotionEvent): Boolean {
val rect = Rect(x.roundToInt(), y.roundToInt(), (x + width).roundToInt(), (y + height).roundToInt())
return rect.contains(event.x.roundToInt(), event.y.roundToInt())
}
答案 5 :(得分:-1)
当“触摸事件”发生时,它将遍历所有视图的树。 F.E.如果你有线性布局和ImageView,用户触摸ImageView上的屏幕,然后触摸事件拦截,首先它将在LinearLayour处理,然后在ImageView处理。
如果你想阻止事件f.e.在位图上,您应该覆盖onTouchEvent for Bitmap并返回true值。这意味着您处理了此事件,并且它不适用于LinearLayout。
image.setOnTouchListener( new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true; // attentively read documentation for onTouc interface
}
});