【问题标题】:Custom object click issue in androidandroid中的自定义对象点击问题
【发布时间】:2012-03-21 16:07:09
【问题描述】:

我在 android 中创建了一个自定义视图来在屏幕上显示球。现在我想要的是,当我触摸那个球时,它应该分成四个部分爆炸,每个部分应该移动不同的四个方向,即上、下、左、右。我知道我必须设置触摸监听器来检测球上的触摸但是如何创建爆炸效果?这个问题现在解决了。我在屏幕上显示了多个球,以便用户可以点击它并爆炸它们。

这是我的自定义视图:

public class BallView extends View {
    private float x;
    private float y;
    private final int r;
    public BallView(Context context, float x1, float y1, int r) {
        super(context);
        this.x = x1;
        this.y = y1;
        this.r = r;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(x, y, r, mPaint);
    }

}

SmallBall 具有类似的属性,除了一个是方向和一个在方向上移动它的爆炸方法和一个动画标志来停止它的移动。

private final int direction;
private boolean anim;

public void explode() {
    // plus or minus x/y based on direction and stop animation if anim flag is false
    invalidate();
}

我的布局xml如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/main_view"
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:background="#FF66FF33" />

我将 BallView 和 SmallBall 添加到活动类中,如下所示:

final FrameLayout mainFrameLayout = (FrameLayout) findViewById(R.id.main_frame_layout);

SmallBall[] smallBalls = new SmallBall[4];
smallBalls[0] = new SmallBall(getApplicationContext(), 105, 100, 10, 1, false);
smallBalls[0].setVisibility(View.GONE);
mainFrameLayout .addView(smallBalls[0]);
// create and add other 3 balls with different directions.

BallView ball = new BallView(getApplicationContext(), 100, 100, 25, smallBalls);
listener = new MyListener(ball);
ball.setOnClickListener(listener);

mainFrameLayout.addView(ball);

我在不同的位置添加了多个 BallView 及其相关的 SmallBall 数组。现在,无论我在屏幕上最后添加的位置单击哪里,会发生什么 BallView 开始爆炸。在倒数第二个之后,依此类推。所以这里有两个问题:

  1. 为什么无论我点击屏幕的哪个位置,它都会调用 onClick/onTouch 事件?当我单击特定的 BallView 时,它应该只调用侦听器事件。
  2. 其次是为什么 BallView 开始以与添加到布局的方式相反的方式爆炸?

我的监听类:

public void onClick(View v) {
        BallView ballView = (BallView) v;
        ballView.setVisibility(View.GONE);
        //get small balls associated with this ball.
        //loop through small ball and call their explode method.
    }

由于有问题的字符限制,我已经修剪了代码。

【问题讨论】:

  • 您在为爆炸效果编码时遇到了什么问题?你想要零件运动的动画还是爆炸图形?如果你能提供一张图片或你想要实现的东西就更好了。
  • @Creator:我想要的是当有人点击任何球时,它会爆炸成四个小球,并且每面墙应该朝四个方向之一移动。我不确定要使用什么,因为我是 android 新手。可能是爆炸部分的动画将是一个不错的选择。

标签: android click effect


【解决方案1】:

好的,问题出在将BallViewSmalBall 创建为View 对象期间。我想我可以很好地解释这一点,所以请耐心等待:

一个好的开始是分层蛋糕。想想站在厨房里做一个这样的蛋糕:一次加一层。首先是巧克力层,然后是香草层,然后是另一个巧克力层。听起来不错?好的。

因此,在Canvas 上绘制了很多圆圈,另外,Ball 对象被添加为Views。请注意,Canvas 仅表示用户可以与之交互的矩形,并与代码中的 View 相关联——FrameLayout。出于所有意图和目的,Canvas 完全填充了FrameLayout。在您的应用程序中,Canvas 是蛋糕的底层——填充了ContentView(或平底锅)的宽度和高度。

m.addView(View v) 的每次调用实质上都是在m 中已包含许多View 对象之上放置一个新的View v。就蛋糕而言,每次调用addView 都会为我们的千层蛋糕增加一层。

在您的项目中,您想在蛋糕上添加一层,但不想让它填满整个平底锅。你想在上面放几颗草莓,你不想要一整层草莓。

因此,默认情况下,您的 BallView 对象会占据整个屏幕。每一个都堆积在下一个之上,填满了整个画布。当你点击时,它会删除最后一个——因为最后一个在顶部,并且占据了整个画布的宽度和高度——实际上是用户可以唯一的球可能会点击。

所以你必须告诉你的BallViewView 对象与你在Canvas 对象上绘制的圆圈大小相同。

所以,这里有几个问题:

您只能使用RelativeLayout 进行绝对定位。如果您希望BallView 用户可以单击以位于画布上绘制的圆圈的顶部,您需要一种方法来告诉BallView 它的位置,并动态更改该位置。当前您正在使用FrameLayout,这是Canvas 所必需的——因此在您的XML 中添加一个全屏&lt;RelativeLayout&gt;。然后,在您的代码中,将 BallView 对象添加到此 RelativeLayout 中。

然后,最后:

去这里:

Set the absolute position of a view

祝你好运!

【讨论】:

  • 感谢。设置布局参数会有所帮助。很好的解释。
【解决方案2】:

这一切正在发生,因为您没有指定 Ball 对象的 LayoutParameters。这里发生的情况是,当您将 Ball 对象添加到 Layout 时,它会占用整个布局的空间,这就是它对单击屏幕上的任意位置做出反应的原因。

现在是第二个问题,原因是一样的。假设板块的情况,它总是以 LIFO 方式弹出。在这里,所有 Ball 对象都覆盖了整个屏幕,因此将它们视为盘子,因此您所做的就是将盘子放在彼此的顶部。这就是为什么它首先对最后一个球的 onClick 方法做出反应,然后是倒数第二个等等。

因此,在为 Ball 对象设置适当的 Layout 参数后,您的这两个问题都会得到解决。

【讨论】:

    【解决方案3】:

    我认为您不需要在画布中对所有这些进行硬编码。您可以在 Touch Listener 中调用 ball.setVisibility(View.GONE) 并通过使用 smallBall.setVisibility(View.Visible) 为每个小球显示 4 个额外的球。这样你就可以隐藏大球并显示小球。 现在对于运动效果,每个 smallBall 中都可以有一个需要传递方向的方法,您可以像这样调用它 smallBall.explode(direction)。方法实现可以是

    explode(int direction){//can be String
      if(direction=NORTH)
         y--;
      //other condition checks
    }
    

    explode 方法将根据传递的方向开始改变它们的 x 和 y 坐标。 我希望这会给你一个关于如何实现它的提示。

    【讨论】:

    • 谢谢。我会试试这个并告诉你。
    • 如何反复调用爆炸,让小球动起来?还有一件事我正在向 FrameLayout 添加球,现在如何在调用 ball.setVisibility(View.GONE); 后向该布局添加小球。
    • 把它放在smallBall的onDraw()方法中,如果里面有invalidate()调用,每次都会自动调用。只要记住有一个布尔标志或条件来触发explode()并在你想要的时候停止它。
    • 还有一件事我正在向 FrameLayout 添加小球,现在如何在调用 ball.setVisibility(View.GONE); 后向该布局添加小球?
    • 我在ball的onTouchListener中写了.setVisibility(View.GONE)。现在,当我触摸一个球时,屏幕上的所有球都会被隐藏。为什么会这样?
    猜你喜欢
    • 2010-11-10
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    相关资源
    最近更新 更多