gpt4 book ai didi

java - 检测在 SurfaceView 上绘制的 View 上的触摸

转载 作者:太空狗 更新时间:2023-10-29 16:41:32 24 4
gpt4 key购买 nike

我正在开发一款游戏并遇到了一些麻烦,我可能没有正确地执行此操作,因为我是 Android 图形方面的新手。

我有一个 SurfaceView 和一个 ArrayList,它们是我自己的 Card 对象,它扩展了 View。我重写了 Card 对象的 onDraw 方法,然后在 SurfaceView 的 onDraw 中绘制了所有内容。绘图部分正常工作。

我现在尝试使用 onTouchListener 检测何时触摸单个卡片,我为每张卡片设置监听器,但它检测到触摸,就好像被触摸的 View 是 表面 View 。可能我的整个思考方式都是错误的,所以我征求你的意见。

部分代码:

public GameSurfaceView(Context context) {
super(context);
GAME_STATE = GameState.LOADING;
this.context = context;
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
}

表面 View onDraw():

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(30, 180, 30);
for (Card card : user.getTableCards()) {
card.draw(canvas);
}
}

卡片的onDraw():

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(getBitmap(), x, y, null);
}

和onTouch

@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TOUCH", "Class: " + v.getClass().toString());
if (v.getClass() == Card.class) {
Log.d("CARD", "Touched: " + ((Card) v).getValue());
}
return true;
}

我总是在记录 SurfaceView 类。这甚至是做类似事情的正确方法吗?我需要检测对同一类的单个对象的触摸..

我目前通过向每张卡片添加类型为 Rect 的成员然后循环并检查触摸的 x 和 y 是否包含在该矩形中来实现这一点,但这似乎很昂贵方式,迭代每张卡片(即使最多 52 张)并检查它..

谢谢

最佳答案

你混淆了两个不同的概念,我将在 A) 和 B) 中解释。

你有两个选择:

A) 如果您想继续使用 SurfaceView(这可能是游戏的正确选择,因为它可以让您更好地控制事物的绘制方式),您的 Card 对象应该扩展 Drawable,而不是 View。 Drawable 是一个愚蠢的类,您只需将其绘制到 Canvas 或传递给小部件作为它们的背景等。Android 不需要了解更多。在这种情况下,您需要像您描述的那样自己检查击中了哪张牌。 Android 无法为您处理此问题。你用 View 而不是 Drawable 来做这件事,这是错误的!或者至少是一种巨大的浪费。请参阅下文了解如何正确处理 View 。

B) 使用 View ,它将为您处理触摸事件和许多其他事情。

View 是一个复杂的类,它应该存在于android 的 View 层次结构中。您使用它的方式会丢弃它的大部分功能 - 当您直接在 Canvas 上绘制 View 时,android 根本不知道该 View ,因此它无法处理触摸事件。

正确的基于 View 的卡片实现可能如下所示:使用 View 组作为基础,这是您在 setContentView() 中设置的内容。此 ViewGroup 可以只是一个 LinearLayout,或者如果您希望能够在您的卡片上设置任意位置和大小,您可以使用 AbsoluteView,尽管这已被弃用。

然后使用 addView() 将您的卡片添加到 ViewGroup。 Card View 在其中的定位由传递给 addView() 的 LayoutParams 对象控制。这样 android 就知道它的存在,并将像这样处理触摸事件:

  • 触摸事件首先转到您的 ViewGroup
  • ViewGroup onTouchEvent 会将事件向下发送到它的子级 onTouchEvent(已通过 addView() 添加)。所以你只需在你的 Card 类中覆盖这个方法。您本能地知道调用了哪个 Card 的 onTouchEvent,因为它是在对象本身上调用的。
  • 在您的 Card 的 onTouchEvent 中,您还通过返回 true 让父级知道您已经处理了触摸事件。如果您不这样做,家长可以改为处理该事件。

非常清楚:您没有将 View 添加到 SurfaceView,事实上,您不能,因为它不是 ViewGroup。它只是一个复杂的 View 对象,允许您在其中执行任意绘图操作。但它始终是 View 层次结构的叶子,并且只能处理它自己的 onTouchEvents,它不会将它向下发送给子级,因为它没有。

关于java - 检测在 SurfaceView 上绘制的 View 上的触摸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17034251/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com