Событие onClick не запускается | Android

Я сделал очень простое тестовое приложение с одним заданием и одним макетом. onClick не срабатывает при первом нажатии, как должно.

Активность:

package com.example.mytest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText ed1 = (EditText) findViewById(R.id.editText1);

        ed1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG)
                        .show();

            }

        });
    }

}

Расположение:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:ems="10" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/editText1"
        android:ems="10" />

</RelativeLayout>

Если вы запустите это приложение, и нажмите на второй editText и затем вернуться к первому, он не будет вызывать onClick, Вы можете продолжать выбирать вперед и назад, и это не вызовет onClick совсем. Мне нужна эта базовая функциональность, но я не смог придумать, как заставить ее работать. Идеи?

уведомление

Я перепробовал все методы, рекомендованные для физического устройства API уровня 16 и эмулятора API уровня 8, но у меня возникла та же проблема.

осветление

когда editText1 фокусируется и нажимается, затем onClick метод пожаров. Если editText2 фокусируется, а затем editText1 нажата, не срабатывает Большая проблема.

9 ответов

Решение

Обзор, когда пользователь взаимодействует с любым компонентом пользовательского интерфейса, различные слушатели вызываются в порядке сверху вниз. Если один из слушателей с более высоким приоритетом "потребляет событие", тогда более низкие слушатели не будут вызываться.

В вашем случае эти три слушателя вызываются по порядку:

  1. OnTouchListener
  2. OnFocusChangeListener
  3. OnClickListener

В первый раз, когда пользователь касается EditText, он получает фокус, чтобы пользователь мог печатать. Действие здесь потребляется. Поэтому OnClickListener с более низким приоритетом не вызывается. Каждое последующее касание не меняет фокус, поэтому эти события переходят к OnClickListener.

Кнопки (и другие подобные компоненты) не получают фокус от сенсорного события, поэтому OnClickListener вызывается каждый раз.

По сути, у вас есть три варианта:

  1. Реализуйте OnTouchListener самостоятельно:

    ed1.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(MotionEvent.ACTION_UP == event.getAction())
                editTextClicked(); // Instead of your Toast
            return false;
        }
    });
    

    Это будет выполняться каждый раз при касании EditText. Обратите внимание, что слушатель возвращается false это позволяет событию перетекать во встроенный OnFocusChangeListener, который изменяет фокус, так что пользователь может ввести EditText.

  2. Реализуйте OnFocusChangeListener вместе с OnClickListener:

    ed1.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
                editTextClicked(); // Instead of your Toast
        }
    });
    

    Этот слушатель ловит первое событие касания, когда фокус изменяется, в то время как ваш OnClickListener ловит любое другое событие.

  3. (Это неправильный ответ, но это хороший прием.) Установите для атрибута focusable значение false в вашем XML:

    android:focusable="false"
    

    Теперь OnClickListener будет срабатывать при каждом нажатии. Но это делает EditText бесполезным, так как пользователь больше не может вводить текст...

Замечания:

getApplicationContext() может создавать утечки памяти. Хорошая привычка - избегать использования без крайней необходимости. Вы можете безопасно использовать v.getContext() вместо.

Надеюсь, это поможет!

Я, вероятно, слишком поздно для вечеринки, но вот фрагмент кода, который исправляет проблему с onClick() не вызывается:

ed1.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP && !v.hasFocus()) {
            // onClick() is not called when the EditText doesn't have focus,
            // onFocusChange() is called instead, which might have a different 
            // meaning. This condition calls onClick() when click was performed
            // but wasn't reported. Condition can be extended for v.isClickable()
            // or v.isEnabled() if needed. Returning false means that everything
            // else behaves as before.
            v.performClick();
        }
        return false;
    }
});

Сделать редактируемый текст кликабельным.. в XML android:clickable="true" или в коде

ed1.setClickable(true);

тогда делай

ed1.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
      Toast.makeText(getBaseContext(), "1",Toast.LENGTH_SHORT).show();
    }
  });

Это происходит потому, что первое нажатие фокусируется на виде. Следующее нажатие вызывает щелчок.

Если вы надуваете представление динамически, то вы можете сделать это на наборе элементов:

android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"

Если это не работает, попробуйте применить его и к родительскому представлению.

Это самый простой способ работы со сборщиком даты.

private DatePickerDialog datePickerDialog;
EditText etJoiningDate;
etJoiningDate=(EditText)findViewById(R.id.etJoiningDate);

etJoiningDate.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

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

                final Calendar cldr = Calendar.getInstance();
                int day = cldr.get(Calendar.DAY_OF_MONTH);
                int month = cldr.get(Calendar.MONTH);
                int year = cldr.get(Calendar.YEAR);
                // date picker dialog
                datePickerDialog = new DatePickerDialog(TestActivity.this,
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                                etJoiningDate.setText(dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);
                            }
                        }, year, month, day);
                datePickerDialog.show();

                break;
        }


        return false;
    }


});

Простое, многоразовое решение Kotlin

Я начал с двух пользовательских функций расширения:

val MotionEvent.up get() = action == MotionEvent.ACTION_UP

fun MotionEvent.isIn(view: View): Boolean {
    val rect = Rect(view.left, view.top, view.right, view.bottom)
    return rect.contains((view.left + x).toInt(), (view.top + y).toInt())
}

Затем послушайте прикосновения к Edittext. Это сработает только в том случае, если исходное событие ACTION_DOWN было изначально в Edittext и все еще есть.

myEdittext.setOnTouchListener { view, motionEvent ->
    if (motionEvent.up && motionEvent.isIn(view)) {
        // Talk your action here
    }
    false
}

Избегайте использования FocusChangeListener поскольку он будет вести себя беспорядочно, когда он вам действительно не нужен (например, когда вы входите в действие). Просто установите OnTouchListener вместе с вашим OnClickListener как это:

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            view.requestFocus();
            break;
    }
    return false;
}

Это заставит ваш EditText сначала получить фокус, а ваш onClick правильно функционировать в первый раз.

Мне понадобилась минутка, чтобы понять это однажды, когда это случилось со мной. мой ImageButton с setOnClickListener а также onClick похоже, не сработало, и тогда я понял, что это на самом деле под другим элементом в моем XML-макете, поэтому я перевернул это:

 <RelativeLayout>
     <ImageButton>
     <LinearLayout></LinearLayout>
 </RelativeLayout>

в это:

 <RelativeLayout>
     <LinearLayout></LinearLayout>
     <ImageButton>
 </RelativeLayout>

и внезапно ImageButton не перекрывался с другим макетом, так как теперь он был добавлен позже в родительский макет и теперь был наверху и работает каждый раз. Удачи, всегда весело, когда основные вещи вдруг перестают работать

public class TestProject extends Activity implements OnClickListener {
TextView txtmsg;
EditText ed1, ed2;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    txtmsg = (TextView) findViewById(R.id.txtmsg);
    ed1 = (EditText) findViewById(R.id.edt1);
    ed2 = (EditText) findViewById(R.id.edt2);

    ed1.setOnClickListener(this);
    ed2.setOnClickListener(this);
}

@Override
public void onClick(View v) {


    if(v==ed1){
        txtmsg.setText("1");
        Toast.makeText(this, "first",Toast.LENGTH_SHORT).show();
    }
    if(v==ed2){
        txtmsg.setText("2");
        Toast.makeText(this, "second",Toast.LENGTH_SHORT).show();
    }

}

}

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <EditText
        android:id="@+id/edt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:ems="10" />

    <EditText
        android:id="@+id/edt2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/edt1"
        android:layout_marginTop="14dp"
        android:ems="10" />

    <TextView
        android:id="@+id/txtmsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/edt2"
        android:layout_below="@+id/edt2"
        android:layout_marginRight="22dp"
        android:layout_marginTop="160dp"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

Попробуй это:

public class MainActivity extends Activity implements OnClickListener {
 //rest of your code
}
Другие вопросы по тегам