2

私のビューの onTouch メソッド:

public boolean onTouch(View view, MotionEvent event) {
        Log.d("Touch", "Touch");

        int mNewX = (int) Math.floor(event.getX());
        int mNewY = (int) Math.floor(event.getY());

        boolean isPositionFree = isPositionFree(mNewX, mNewY);

        if (!isPositionFree) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                int i = 0;
                for (Point point : points) { 
                    if (point.spotted) {
                        points.remove(i);
                        invalidate();
                        break;
                    }
                    i++;
                }
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                int i = 0;
                for (Point point : points) { 
                    if (point.spotted) {
                        points.remove(i);
                        Point p = new Point(mNewX, mNewY, point.TYPE);
                        points.add(i, p);
                        invalidate();
                        break;
                    }
                    i++;
                }
            }
        }
}

キャンバスには複数のアイテムがあります。それらの位置は「ポイント」に保存されます。それらは、これらの「ポイント」の位置を介して onDraw メソッドでキャンバスに描画されます。これは、Point point.x および point.y を意味します。

これで、アイテム (キャンバス上のポイント) をクリックすると、そのアイテムが消えるはずです。次に、MotionEvent.ACTION_MOVE が true のときに、event.getX() と event.getY() に応じてポイントを移動したい。

メソッド「isPositionFree(newX,newY)」は、point.x と point.y が newX と newY (画面上で触れた位置) と等しいかどうかをチェックします。

位置が取得された場合 (つまり、クリックした場所に項目があることを意味します)、motionevent-IF に到達します。

ここで問題が発生します。実際にポイントを移動する前に、コードがポイントを削除してしまいます。この問題を何時間も解決できる方法が見つかりませんでした。:/ onTouch は常に最初から呼び出されるため、ACTION_DOWN と ACTION_MOVE が同時に発生することはないため、難しいと思います。

これに対する修正を知っていますか?

前もって感謝します、セバスチャン

4

3 に答える 3

3

動作するようになりました。

同じ問題を抱えている人は、このサンプル コードを参考にしてください :)

最初に宣言したこと

Vector<Point> points = new Vector<Point>();

Bitmap[] monsterTypes = new Bitmap[3];

Vector<Integer> distanceMovedX = new Vector<Integer>();
Vector<Integer> distanceMovedY = new Vector<Integer>();

int mNewX = -1;
int mNewY = -1;

OnTouch メソッド

public boolean onTouch(View view, MotionEvent event) {

        mNewX = (int) FloatMath.floor(event.getX());
        mNewY = (int) FloatMath.floor(event.getY());

        boolean touchedPoint = touchedPoint(mNewX, mNewY);

        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:

            distanceMovedX.add(mNewX);
            distanceMovedY.add(mNewY);
            break;
        case MotionEvent.ACTION_UP:

            isMoveEvent = isMoveEvent();
            if (isMoveEvent) {
                for (Point point : points) {

                    if (point.spotted) {

                        // Your code
                    } 
                    i++;
                }
            } else {
                if (touchedPoint) {
                    for (Point point : points) { 
                        if (point.spotted) {

// Your code
                        }
                    }
                }
            }
            distanceMovedX.clear();
            distanceMovedY.clear();
            return true;
        }
        return true;
    }

touchedPoint-メソッド

public boolean touchedPoint(int mNewX, int mNewY) {
        boolean touchedPoint = false;
        int height = 0;
        int width = 0;

        for (Point point : points) {
            height = monsterTypes[point.TYPE - 1].getHeight();
            width = monsterTypes[point.TYPE - 1].getWidth();

            if (point.x + width < mNewX || point.x > mNewX + width
                    || point.y + height < mNewY || point.y > mNewY + height) {
                touchedPoint = false;
                point.spotted = false;
            } else {
                touchedPoint = true;
                point.spotted = true;
                return touchedPoint;
            }
        }
        return touchedPoint;
    }

isMoveEvent メソッド

public boolean isMoveEvent() {
        boolean isMoveEvent = false;
        boolean isMoveEventX = false;
        boolean isMoveEventY = false;

        for (int i = 0; i <= (points.size() -1); i++) {
            Log.d("point", "for loop entered");

            if (!distanceMovedY.isEmpty()) {
                Log.d("point.x", "distanceMovedY is not empty");
                int dMY = distanceMovedY.get(distanceMovedY.size() - 1) - distanceMovedY.get(0);

                if ((dMY > 50 || dMY <= 0) && dMY != 0) {
                    Log.d("point.y", "is move event");
                    Log.d("point.y", "dMY: " + dMY);
                    isMoveEventY = true;
                } else {
                    Log.d("point.x", "is no move event");
                    Log.d("point.x", "dMY: " + dMY);
                    isMoveEvent = false;
                    return isMoveEvent;
                }
            }
            if (!distanceMovedX.isEmpty()) {
                Log.d("point.x", "distanceMovedX is not empty");
                int dMX = distanceMovedX.get(distanceMovedX.size() - 1) - distanceMovedX.get(0);

                if (dMX <= 50 && dMX >= -50 && dMX != 0) {
                    Log.d("point.x", "is move event");
                    Log.d("point.x", "dMX: " + dMX);
                    isMoveEventX = true;
                } else {
                    Log.d("point.x", "is no move event");
                    Log.d("point.x", "dMX: " + dMX);
                    isMoveEvent = false;
                    return isMoveEvent;
                }
            }
            if (isMoveEventX && isMoveEventY) {
                Log.d("point", "is move event");
                isMoveEvent = true;
                return isMoveEvent;
            }
        }
        Log.d("point", "is no move event");
        return isMoveEvent;
    }

ポイントクラス

クラス ポイント { int x, y; int タイプ; ブール値の斑点; ブール値の halfSpotted;

public Point() {
}

public Point(int x, int y, int t) {
    this.x = x;
    this.y = y;
    this.TYPE = t;
}

@Override
public String toString() {
    return x + ", " + y;
}

}

説明:

ポイント: クラス ポイントを取得しました。ベクターで宣言されたすべてのポイントは、キャンバス上の x 座標と y 座標です。クリックした位置を確認するのに役立ちます。

MonsterTypes: 私が使用するさまざまなグラフィックです。キャンバスに描画するグラフィックを 1 つだけ使用する場合は、必要に応じて変更します

distanceMovedX & Y: 「ACTION_MOVE」のすべての X 座標と Y 座標を保存します。pos 0 (最初にタッチしたポイント) から pos Z (ACTION_UP が発生した最後のタッチ ポイント) まで。元のXとYの位置ではありませんが。posZ - pos0 の結果です。これらの値を使用して、移動した距離の後に「onMove」を呼び出し、「onClick」を呼び出す距離の下で決定できます。

mNewX & Y: onTouch-Method の現在の位置。指を動かすたびに newX と Y が上書きされます。

方法:

onTouch(): まず、mNewX と Y を現在タッチされている位置に上書きします。次に、既存のスポット (私の場合は 48px*48px の領域) をクリックしたかどうかを確認します。次に、取得した距離を ACTION_MOVE に記録します。その後、ACTION_UP に進み、moveEvent または clickEvent を実行したかどうかを確認します。

touchedPoint(): キャンバス上の既存のポイントに触れたかどうかを計算します。true または false を返します

isMoveEvent(): 特定の距離を移動したかどうかを確認します。私の場合、50px以上下に移動したいです。-50px または +50px の横への移動は許可されていません。移動イベントではない場合、最後に触れたスポットは、指定された距離内にある必要があります (私の場合、ポイントの 48px*48px の範囲内)。

それでおしまい。そのオプションを理解するだけで何日もかかりました;/それを恥じています...私はそれをかなり速くコーディングしましたが、私は再び気分が良くなります:D

于 2012-08-12T22:24:36.097 に答える
0

私はちょうどいくつかのウォークアラウンドを提案しています:

クリック時にポイントを削除する代わりに、現在ポイントを削除しているクラスでプライベートポイントを作成し、新しい変数ポイントを削除するポイントに設定するだけです...

次に、アクションまたはアクション移動で使用した後、最後に使用する場所で、プライベート変数が null でないかどうかを確認し、そうであれば削除してから、null に設定します。

于 2012-08-10T18:25:39.520 に答える
-1

switch case ステートメントを使用してみてください。

指のアクションを切り替える:

case(ACTION_MOVE)
{
//move code
return false;
}
case(ACTION_TOUCH)
{
//dissappear code
return false;
}

上記のコードは疑似コードですが、ドットに触れる前にドットを動かしているかどうかをチェックすることに注意してください。このようにして、ドットは最初に削除されるのではなく、最初に移動を試みます。

ありがとう、アレックス

于 2012-08-10T18:53:31.693 に答える