OnClickListener-イベントのx、yの場所?


85

Viewから派生したカスタムビューがあります。ビューがクリックされたとき、およびクリックが発生した場所のx、y位置を通知したいのですが。ロングクリックでも同じです。

これを行うように見えます、私はオーバーライドする必要がありますonTouchEvent()OnClickListenerただし、代わりにイベントのx、y位置を取得する方法はありませんか?

そうでない場合、モーションイベントが「実際の」クリックであるかロングクリックであるかなどを判断する良い方法は何ですか?onTouchEvent矢継ぎ早などで多くのイベントを生成し、

回答:


91

ありがとうございました。それがまさに私が探していたものでした。私のコードは次のとおりです。

imageView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
                textView.setText("Touch coordinates : " +
                        String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
            }
            return true;
        }
    });

マークが求めたことを正確に実行します...


4
これらの座標はビューに対してローカルですか?
ナイジェル

7
onTouchハンドラーは、falseタッチイベントをブロックしないように戻るべきではありませんか?(View.OnTouchListener.onTouchは、リスナーがイベントを消費した場合はtrueを返し、それ以外の場合はfalseを返します。)
ehartwell 2014

5
まあ、OnClickListener指を離したときに発火するので「正確に」ではないので、ACTION_UP制限があります。ファイリング(スワイプ)ジェスチャが実行された場合、OnClickListener発火されませんが、ACTION_UP処理されます。
Alex Semeniuk 2014年

クリックした座標にテキストを書き込もうとしています。座標でテキストを(event.getX(), event.getY()) 書いてみましたが、正しい位置に書いてありません。
プリンス

これが私の質問です: stackoverflow.com/questions/40199539/…–
Prince

26

完全な例

他の答えはいくつかの詳細が欠けています。これが完全な例です。

public class MainActivity extends AppCompatActivity {

    // class member variable to save the X,Y coordinates
    private float[] lastTouchDownXY = new float[2];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // add both a touch listener and a click listener
        View myView = findViewById(R.id.my_view);
        myView.setOnTouchListener(touchListener);
        myView.setOnClickListener(clickListener);
    }

    // the purpose of the touch listener is just to store the touch X,Y coordinates
    View.OnTouchListener touchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            // save the X,Y coordinates
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                lastTouchDownXY[0] = event.getX();
                lastTouchDownXY[1] = event.getY();
            }

            // let the touch event pass on to whoever needs it
            return false;
        }
    };

    View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // retrieve the stored coordinates
            float x = lastTouchDownXY[0];
            float y = lastTouchDownXY[1];

            // use the coordinates for whatever
            Log.i("TAG", "onLongClick: x = " + x + ", y = " + y);
        }
    };
}

概要

  • 座標を格納するクラス変数を追加します
  • を使用してX、Y座標を保存します OnTouchListener
  • のX、Y座標にアクセスします OnClickListener

1
2スペースのfloatArrayの代わりに、Point()を使用できます。
ZooMagic 2018

ポイントには整数型のXとYがあります。座標は浮動小数点値です。Pointクラスを使用すると、精度が低下すると思います。Androidは非常に新しく、何かを見逃している可能性があります。
mboada

@mboada、その通りです。PointFの方が良いでしょう。
Suragch

onTouchListenerを回避し、onClickListenerだけを使用する方法があるはずです。どういうわけか、ContextMenuはそれを必要としません。アイテムをクリックして、ビューをアンカーとしてメニューを表示すると、タッチ位置の近くにアイテムを配置する場所がわかります。ここを参照してください:stackoverflow.com/q/57290574/878126。それがどのように可能か知っていますか?もしそうなら、そこで答えることを検討してください。
Androidの開発者

3

onTouchEvent(MotionEvent ev)をオーバーライドします

次に、次のことができます。

ev.getXLocation()

またはそのようなもの。ブッチを持っています。


2
こんにちはトム、はい、onTouchEventを使用できますが、クリックとロングクリックの識別を自分で処理する必要がありますね。OnClickListenerなどでクリックまたはロングクリックが発生した場所を知る方法を提供しないのは意味がありませんか?ありがとう
マーク

21
最後のACTION_UPまたはACTION_MOVEイベントのxとyの位置を記録し、これらの値をOnClickListenerで使用するだけです。
Romain Guy

@RomainGuyただし、クリックを決定するには、2点間の距離も計算する必要があります。(0,0)でACTION_DOWNイベントを受信し、次に(100,100)でACTION_UPイベントを受信した場合、それは間違いなくクリックではありません。
TheRealChx101 2015

@ chx101、RomainGuyが意味したのは(私が思うに)、toucheventで最後のaction_up座標を記録した場合、それらがonclickで使用できる座標であるということでした。ただし、実際にはビューをサブクラス化する必要があると思います。そうしないと、onclickが呼び出されません。stackoverflow.com/questions/19538747/のように、タップをジェスチャー検出器として検出することもできます…回答
Lassi Kinnunen 2016

0

Kotlinで次のような拡張機能を作成できます。

fun View.setOnClickListenerWithPoint(action: (Point) -> Unit) {
    val coordinates = Point()
    val screenPosition = IntArray(2)
    setOnTouchListener { v, event ->
        if (event.action == MotionEvent.ACTION_DOWN) {
            v.getLocationOnScreen(screenPosition)
            coordinates.set(event.x.toInt() + screenPosition[0], event.y.toInt() + screenPosition[1])
        }
        false
    }
    setOnClickListener {
        action.invoke(coordinates)
    }
}

ロングクリックが必要な場合-交換するだけです setOnClickListener

getLocationOnScreen()RecyclerViewのViewHolderの座標が必要なために使用します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.