OnClickListener - x, y vị trí của sự kiện?


85

Tôi có một chế độ xem tùy chỉnh bắt nguồn từ Chế độ xem. Tôi muốn được thông báo khi chế độ xem được nhấp và vị trí x, y của nơi nhấp chuột xảy ra. Tương tự cho các lần nhấp chuột lâu.

Có vẻ như để làm điều này, tôi cần ghi đè onTouchEvent(). Tuy nhiên, không có cách nào để lấy vị trí x, y của sự kiện từ an OnClickListener?

Nếu không, cách tốt để biết liệu một sự kiện chuyển động có phải là nhấp chuột 'thực' hay nhấp chuột lâu, v.v. không? Việc onTouchEventtạo ra nhiều sự kiện liên tiếp nhanh chóng, v.v.

Câu trả lời:


91

Cảm ơn bạn. Đó chính xác là những gì tôi đang tìm kiếm. Mã của tôi bây giờ là:

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

điều này thực hiện chính xác những gì Mark yêu cầu ...


4
Những coords này là địa phương để xem?
Nigel

7
Trình xử lý onTouch có nên trả về falseđể không chặn các sự kiện chạm không? (View.OnTouchListener.onTouch trả về true nếu người nghe đã tiêu thụ các sự kiện, sai khác.)
ehartwell

5
Chà, không phải "chính xác" là do OnClickListenerđược bắn khi ngón tay được thả ra, vì vậy, ACTION_UPnhưng có giới hạn: nếu cử chỉ fling (vuốt) được thực hiện thì OnClickListenerkhông được kích hoạt nhưng ACTION_UPvẫn sẽ được xử lý.
Alex Semeniuk

Tôi đang cố viết văn bản trên tọa độ được nhấp. Tôi đã thử viết văn bản tại các tọa độ (event.getX(), event.getY()) nhưng nó không viết đúng vị trí.
Prince

Đây là câu hỏi của tôi: stackoverflow.com/questions/40199539/…
Prince

26

Đầy đủ ví dụ

Các câu trả lời khác bị thiếu một số chi tiết. Đây là một ví dụ đầy đủ.

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

Tóm lược

  • Thêm một biến lớp để lưu trữ các tọa độ
  • Lưu tọa độ X, Y bằng cách sử dụng OnTouchListener
  • Truy cập các tọa độ X, Y trong OnClickListener

1
Thay vì một Mảng float 2 dấu cách, một Point () có thể được sử dụng.
ZooMagic

Điểm có X và Y kiểu số nguyên. Các tọa độ là giá trị thực. Nếu tôi sử dụng lớp Point, tôi nghĩ rằng tôi sẽ mất độ chính xác .... Tôi rất mới trong Android và có thể tôi đã bỏ lỡ điều gì đó.
mboada 30/07/19

@mboada, Bạn nói đúng. PointF sẽ tốt hơn.
Suragch

Nên có một cách để tránh onTouchListener và chỉ sử dụng onClickListener. Bằng cách nào đó, ContextMenu không cần nó. Khi nhấp vào một mục và hiển thị menu với chế độ xem như một mỏ neo, nó sẽ biết phải đặt nó ở đâu, gần vị trí chạm. Xem tại đây: stackoverflow.com/q/57290574/878126 . Bạn có biết làm thế nào nó có thể? Nếu vậy, vui lòng xem xét trả lời ở đó.
nhà phát triển android

3

Ghi đè onTouchEvent (MotionEvent ev)

Sau đó, bạn có thể làm:

ev.getXLocation()

Hoặc điều tương tự. Có một cái mông.


2
Xin chào Tom, vâng, chúng ta có thể sử dụng onTouchEvent, nhưng sau đó chúng ta cần tự mình xử lý phân biệt giữa các lần nhấp và các lần nhấp dài, phải không? Sẽ không hợp lý khi họ không cung cấp cho bạn cách biết vị trí của lần nhấp hoặc lần nhấp dài diễn ra trong OnClickListener, v.v.? Cảm ơn
Đánh dấu

21
Tất cả những gì bạn phải làm là ghi lại vị trí x & y của sự kiện ACTION_UP hoặc ACTION_MOVE cuối cùng và sử dụng các giá trị này trong OnClickListener của bạn.
Romain Guy

@RomainGuy Nhưng bạn cũng phải tính toán khoảng cách giữa hai điểm để xác định một lần nhấp. Nếu bạn nhận được sự kiện ACTION_DOWN ở (0,0) và sau đó sự kiện ACTION_UP ở (100,100) thì đó chắc chắn không phải là một lần nhấp.
TheRealChx101

@ chx101, ý của RomainGuy (tôi nghĩ) là nếu bạn chỉ cần dùng touchhevent ghi lại các tọa độ action_up cuối cùng thì đó là các tọa độ bạn có thể sử dụng trong onclick. tuy nhiên tôi nghĩ rằng điều đó sẽ cần phân lớp chế độ xem trong thực tế, nếu không onclick không được gọi. bạn cũng có thể phát hiện chạm như một công cụ phát hiện cử chỉ như trong câu trả lời stackoverflow.com/questions/19538747/…
Lassi Kinnunen,

0

Bạn có thể tạo một hàm mở rộng trong Kotlin, như sau:

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

Nếu bạn cần một cú nhấp chuột dài - chỉ cần thay thế setOnClickListener

Tôi sử dụng getLocationOnScreen()vì tôi cần tọa độ cho ViewHolder của RecyclerView

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.