Событие 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 ответов
Обзор, когда пользователь взаимодействует с любым компонентом пользовательского интерфейса, различные слушатели вызываются в порядке сверху вниз. Если один из слушателей с более высоким приоритетом "потребляет событие", тогда более низкие слушатели не будут вызываться.
В вашем случае эти три слушателя вызываются по порядку:
- OnTouchListener
- OnFocusChangeListener
- OnClickListener
В первый раз, когда пользователь касается EditText, он получает фокус, чтобы пользователь мог печатать. Действие здесь потребляется. Поэтому OnClickListener с более низким приоритетом не вызывается. Каждое последующее касание не меняет фокус, поэтому эти события переходят к OnClickListener.
Кнопки (и другие подобные компоненты) не получают фокус от сенсорного события, поэтому OnClickListener вызывается каждый раз.
По сути, у вас есть три варианта:
Реализуйте 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.Реализуйте OnFocusChangeListener вместе с OnClickListener:
ed1.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if(hasFocus) editTextClicked(); // Instead of your Toast } });
Этот слушатель ловит первое событие касания, когда фокус изменяется, в то время как ваш OnClickListener ловит любое другое событие.
(Это неправильный ответ, но это хороший прием.) Установите для атрибута 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
}