OnTouch работает, но OnClickListener нет? - PullRequest
19 голосов
/ 12 марта 2011

Я создал виджет / элемент управления, который я могу использовать повторно, добавив RelativeLayout.Затем в одном из моих занятий я создал несколько таких виджетов в цикле.Однако я столкнулся с проблемой, когда хотел, чтобы каждый виджет отвечал на щелчок.

Я обнаружил, что настройка OnTouchListener работает:

 this.setOnTouchListener(new OnTouchListener(){
        public boolean onTouch(View arg0, MotionEvent arg1) {
           //Triggers debug message
        }       
    });

, а OnClickListener - нет:

  this.setOnClickListener(new View.OnClickListener(){
        public void onClick(View v) {
           //Doesn't trigger debug message  
        }

    });

Почему это?

Ответы [ 8 ]

49 голосов
/ 12 марта 2011

Вы должны убедиться, что TouchListener не «потребляет» событие касания.Если вы вернете true из метода onTouch(), Android сочтет его использованным и не передаст его другим различным сенсорным обработчикам (которые, как я предполагаю, будет включать ClickListener).

Вы должны сделать:

this.setOnTouchListener(new OnTouchListener(){
    public boolean onTouch(View arg0, MotionEvent arg1) {
        //Triggers debug message
        return false;
    }       
});
16 голосов
/ 12 марта 2011

Вот несколько вещей, которые нужно проверить, чтобы убедиться, что ваши просмотры кликабельны:

View.setClickable()
View.setEnabled()
View.setFocusable()
View.setFocusableInTouchMode()

В зависимости от того, какое поведение вы надеетесь получить, вам нужно установить один или несколько из них на,Поскольку вы получаете события onTouch, я предполагаю, что вам нужно установить ClickCable.Но я должен был бы увидеть код создания представления, чтобы быть уверенным.

15 голосов
/ 12 марта 2011

Правильно ли вы возвращаете логическое значение onTouch?

Из документов:

onTouch () - Возвращает логическое значение, указывающее, является ли ваш слушательпотребляет это событие.Важно то, что это событие может иметь несколько действий, которые следуют друг за другом.Таким образом, если вы возвращаете false при получении события действия вниз, вы указываете, что вы не использовали событие и также не заинтересованы в последующих действиях из этого события.Таким образом, вас не будут призывать к каким-либо другим действиям внутри события, таким как жест пальцем или событие возможного действия вверх.

РЕДАКТИРОВАТЬ

Нашел решение в этом вопросе и попробовал сам.

Вам нужно использовать return super.onTouchEvent(event); в своем коде onTouchEvent.После добавления этого OnClickListener начал работать.

5 голосов
/ 26 апреля 2012

Для выполнения этого возврата ложь в вашем onTouch(), например:

this.setOnTouchListener(new OnTouchListener(){    
        public boolean onTouch(View arg0, MotionEvent arg1) {   
            return false;
        }       
});
2 голосов
/ 03 февраля 2014

Вы можете реализовать onClickListener через onTouchListener:

webView.setOnTouchListener(new View.OnTouchListener() {

        public final static int FINGER_RELEASED = 0;
        public final static int FINGER_TOUCHED = 1;
        public final static int FINGER_DRAGGING = 2;
        public final static int FINGER_UNDEFINED = 3;

        private int fingerState = FINGER_RELEASED;


        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            switch (motionEvent.getAction()) {

                case MotionEvent.ACTION_DOWN:
                    if (fingerState == FINGER_RELEASED) fingerState = FINGER_TOUCHED;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                case MotionEvent.ACTION_UP:
                    if(fingerState != FINGER_DRAGGING) {
                        fingerState = FINGER_RELEASED;

                        // Your onClick codes

                    }
                    else if (fingerState == FINGER_DRAGGING) fingerState = FINGER_RELEASED;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                case MotionEvent.ACTION_MOVE:
                    if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING) fingerState = FINGER_DRAGGING;
                    else fingerState = FINGER_UNDEFINED;
                    break;

                default:
                    fingerState = FINGER_UNDEFINED;

            }

            return false;
        }
    });
1 голос
/ 09 октября 2013

Если вам нужны события onClick и onTouch в одном представлении, используйте GestureDetector .

1 голос
/ 12 марта 2012

Если по какой-то причине вы переопределяете метод onMotionEvent () и вам необходимо вернуть true / false, вы можете вручную вызвать обратный вызов OnClickListener (), вызвав this.performClick () внутри переопределенного onMotionEvent () непосредственно передвы возвращаете истину / ложь.

0 голосов
/ 08 ноября 2018

Если вы попытались вернуть false:

this.setOnTouchListener(new OnTouchListener(){
    public boolean onTouch(View arg0, MotionEvent arg1) {
        return false;
    }       
});

, и это не сработало, попробуйте это решение, если вы используете ScrollView.Добавьте LinearLayout внутри ScrollView.Установите кликабельность на true в нем.Вызовите setOnClickListener и setOnTouchListener из LinearLayout.

<ScrollView
android:id="@+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbarStyle="outsideOverlay">

<LinearLayout
    android:id="@+id/linearlayout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <content... />

</LinearLayout>
</ScrollView>


LinearLayout linearlayout = findViewById(R.id.linearlayout);
linearlayout.setOnClickListener...
linearlayout.setOnTouchListener...
...