OnClickListener - x, y olay yeri?


85

Görünüm'den türetilen özel bir görünümüm var. Görünüm tıklandığında ve tıklamanın meydana geldiği x, y konumu ile ilgili olarak bilgilendirilmek istiyorum. Uzun tıklamalar için aynı.

Görünüşe göre bunu yapmak istiyorum, geçersiz kılmam gerekiyor onTouchEvent(). OnClickListenerYine de olayın x, y konumunu an'dan almanın bir yolu yok mu?

Değilse, bir hareket olayının 'gerçek' tıklama yerine uzun tıklama vb. Olduğunu söylemenin iyi bir yolu nedir? onTouchEventPeş peşe vb birçok olaylar üretir

Yanıtlar:


92

Teşekkür ederim. Tam olarak aradığım buydu. Kodum şimdi:

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;
        }
    });

Mark'ın istediğini tam olarak yapan ...


4
Bu koordinatlar görünüme göre yerel mi?
Nigel

7
OnTouch işleyicisinin falsedokunma olaylarını engellememesi için geri dönmesi gerekmez mi? (View.OnTouchListener.onTouch, dinleyici olayı tüketmişse doğru, aksi takdirde yanlış döndürür.)
ehartwell

5
Pekala, "tam olarak" değil, çünkü OnClickListenerparmak bırakıldığında ateşleniyor, bu yüzden ACTION_UPama sınırlamalarla: çırpma (kaydırma) hareketi yapılmışsa, OnClickListenerateşlenmez, ancak ACTION_UPyine de işleme alınacaktır.
Alex Semeniuk

Tıklanan koordinatlara metin yazmaya çalışıyorum. Koordinatlarda metin yazmayı denedim (event.getX(), event.getY()) ama doğru konumda yazmıyor.
Prens


26

Tam örnek

Diğer cevaplarda bazı detaylar eksik. İşte tam bir örnek.

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);
        }
    };
}

Özet

  • Koordinatları saklamak için bir sınıf değişkeni ekleyin
  • X, Y koordinatlarını bir OnTouchListener
  • X, Y koordinatlarına erişim OnClickListener

1
2 boşluklu float Array yerine, bir Nokta () kullanılabilir.
ZooMagic

Nokta, X ve Y türünde tam sayıya sahiptir. Koordinatlar yüzer değerlerdir. Point sınıfını kullanırsam, hassasiyeti kaybedeceğimi düşünüyorum .... Android'de çok yeniyim ve bir şeyleri kaçırmış olabilirim.
mboada

@mboada, haklısın. PointF daha iyi olurdu.
Suragch

OnTouchListener'dan kaçınmanın ve sadece onClickListener'ı kullanmanın bir yolu olmalı. Her nasılsa, ContextMenu'nun buna ihtiyacı yok. Bir öğeye tıkladıktan ve görünümü bir çapa olarak gösteren menüyü gösterdikten sonra, onu nereye koyacağını bilir, dokunma konumuna yakın. Buraya bakın: stackoverflow.com/q/57290574/878126 . Bunun nasıl mümkün olduğunu biliyor musun? Öyleyse, lütfen orada yanıtlamayı düşünün.
android geliştiricisi

3

OnTouchEvent'i geçersiz kıl (MotionEvent ev)

O zaman şunları yapabilirsiniz:

ev.getXLocation()

Ya da böyle bir şey. Bir kasap alın.


2
Merhaba Tom, evet onTouchEvent'i kullanabiliriz, ancak daha sonra tıklamalar ile uzun tıklamalar arasında ayrım yapmamız gerekiyor, değil mi? Size, OnClickListener vb.'de tıklamanın veya uzun tıklamanın nerede gerçekleştiğini bilmenin bir yolunu sağlamayacakları mantıklı değil mi? Teşekkürler
Mark

21
Tek yapmanız gereken, son ACTION_UP veya ACTION_MOVE olayının x & y konumunu kaydetmek ve bu değerleri OnClickListener'ınızda kullanmaktır.
Romain Guy

@RomainGuy Ancak bir tıklamayı belirlemek için iki nokta arasındaki mesafeyi de hesaplamalısınız. (0,0) 'da ACTION_DOWN olayını ve ardından (100,100)' de ACTION_UP olayını alırsanız, bu kesinlikle bir tıklama değildir.
TheRealChx101

@ chx101, RomainGuy'un kastettiği (sanırım), sadece touchevent'te son action_up koordinatlarını kaydettiğinizde, bunlar onclick'te kullanabileceğiniz koordinatlardır. ancak bunun pratikte görünümü alt sınıflara ayırması gerektiğini veya onclick çağrılmadığını düşünüyorum. ayrıca stackoverflow.com/questions/19538747/… 'de olduğu gibi musluğu bir hareket algılayıcı olarak algılayabilirsiniz. answer
Lassi Kinnunen

0

Kotlin'de şu şekilde bir uzantı işlevi yapabilirsiniz:

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)
    }
}

Uzun bir tıklamaya ihtiyacınız varsa - sadece değiştirin setOnClickListener

Kullandığım getLocationOnScreen()Ben RecyclerView en ViewHolder koordinatlarını gerektiğinden

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.