onClick事件没有触发| Android

时间:2023-02-09 14:53:30

I made a very simple test application with one activity and one layout. The onClick doesn't trigger the first time it is pressed, as it should.

我用一个活动和一个布局做了一个非常简单的测试应用程序。onClick不会像它应该的那样在第一次按下时触发。

The activity:

活动:

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

            }

        });
    }

}

The layout:

布局:

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

If you run this application, and click on the second editText and then back on the first one, it will not trigger the onClick. You can keep selecting back and forth and it will not trigger the onClick at all. I need this basic functionality, but haven't been able to think of a way to get it to work. Ideas?

如果运行此应用程序,并单击第二个editText,然后返回第一个editText,它将不会触发onClick。你可以来回选择,它根本不会触发onClick。我需要这个基本的功能,但还没能想出一个让它工作的方法。想法吗?

Notice

I have tried all of the methods recommended on my API level 16 physical device and my API level 8 emulator, but I get the same problem.

我已经尝试了API级16物理设备和API级8模拟器上推荐的所有方法,但是我遇到了同样的问题。

Clarification

When editText1 is focused and is clicked on, then the onClick method fires. If editText2 is focussed, and then editText1 is clicked, it doesn't fire. Big problem.

当editText1集中并被单击时,onClick方法就会触发。如果editText2是focussed,然后单击editText1,那么它就不会触发。大问题。

9 个解决方案

#1


160  

Overview, when a user interacts with any UI component the various listeners are called in a top-down order. If one of the higher priority listeners "consumes the event" then the lower listeners will not be called.

概述,当用户与任何UI组件交互时,以自顶向下的顺序调用各种侦听器。如果一个优先级较高的侦听器“消耗事件”,那么将不调用较低的侦听器。

In your case these three listeners are called in order:

在您的情况下,这三个侦听器依次被调用:

  1. OnTouchListener
  2. OnTouchListener
  3. OnFocusChangeListener
  4. OnFocusChangeListener
  5. OnClickListener
  6. OnClickListener

The first time the user touches an EditText it receives focus so that the user can type. The action is consumed here. Therefor the lower priority OnClickListener is not called. Each successive touch doesn't change the focus so these events trickle down to the OnClickListener.

用户第一次触摸EditText时,它会接收到焦点,以便用户可以输入。这里使用的是操作。因此,对于较低的优先级,不会调用OnClickListener。每一次连续的触摸都不会改变焦点,因此这些事件会逐渐影响到OnClickListener。

Buttons (and other such components) don't receive focus from a touch event, that's why the OnClickListener is called every time.

按钮(和其他类似的组件)不会从触摸事件接收焦点,这就是为什么每次都调用OnClickListener。

Basically, you have three choices:

基本上,你有三个选择:

  1. Implement an OnTouchListener by itself:

    自行实现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;
        }
    });
    

    This will execute every time the EditText is touched. Notice that the listener returns false, this allows the event to trickle down to the built-in OnFocusChangeListener which changes the focus so the user can type in the EditText.

    这将在每次修改EditText时执行。注意,侦听器返回false,这允许事件向下传递到内置的OnFocusChangeListener,它更改了焦点,以便用户可以在EditText中输入。

  2. Implement an OnFocusChangeListener along with the OnClickListener:

    和OnClickListener一起实现OnFocusChangeListener:

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

    This listener catches the first touch event when the focus is changed while your OnClickListener catches every other event.

    当焦点发生改变时,该侦听器将捕获第一个触摸事件,而OnClickListener将捕获所有其他事件。

  3. (This isn't a valid answer here, but it is a good trick to know.) Set the focusable attribute to false in your XML:

    (这不是一个有效的答案,但这是一个很好的技巧。)在XML中将可调焦属性设置为false:

    android:focusable="false"
    

    Now the OnClickListener will fire every time it is clicked. But this makes the EditText useless since the user can no longer enter any text...

    现在OnClickListener将在每次单击时触发。但是这使得EditText无用,因为用户不能再输入任何文本……

Note:

注意:

getApplicationContext() can create memory leaks. A good habit is to avoid using it unless absolutely necessary. You can safely use v.getContext() instead.

getApplicationContext()可以创建内存泄漏。一个好的习惯是在绝对必要的时候避免使用它。您可以安全地使用v.getContext()。

Hope that helps!

希望会有帮助!

#2


6  

make edit text clickable.. In XML android:clickable="true" or in code

让编辑文本可点击. .在XML android中:clickable="true"或在代码中

ed1.setClickable(true);

then do

然后做

ed1.setOnClickListener(new OnClickListener() {

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

#3


3  

I'm probably too late to the party, but here is a code snipped which fixes the issue with onClick() not being called:

我可能已经来不及参加聚会了,但是这里有一个代码片段,它修复了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;
    }
});

#4


0  

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>

#5


0  

Took me a minute to figure this out one time when this happened to me. My ImageButton with a setOnClickListener and onClick didn't seem to fire and then I realized it was actually underneath another element in my xml layout, so I turned this:

有一次,我花了一分钟才弄明白这件事。我的ImageButton带有setOnClickListener和onClick,然后我意识到它实际上在我的xml布局的另一个元素下面,所以我把它变成:

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

into this:

到这个:

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

and suddenly the ImageButton was not being overlapped by the other layout since it was now added later to the parent layout and was now on top and works every time. Good luck, always fun when basic stuff suddenly seems to stop working

突然之间,ImageButton没有被其他布局重叠,因为它后来被添加到父布局中,现在在顶部,每次都可以工作。祝你好运,当最基本的东西突然停止工作时,你总是很开心

#6


0  

Avoid using a FocusChangeListener since it will behave erratically when you don't really need it (eg. when you enter an activity). Just set an OnTouchListener along with your OnClickListener like this:

避免使用FocusChangeListener,因为当你不需要它的时候它会表现得很不稳定。当你进入一个活动)。设置一个OnTouchListener和OnClickListener就像这样:

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

This will cause your EditText to receive focus at first, and your onClick to function properly the first time.

这将使您的EditText首先接收焦点,并使您的onClick首次正常工作。

#7


0  

This happens because the first tap gains the focus into the view. The next tap triggers the click.

之所以会出现这种情况,是因为第一次点击将焦点转移到视图中。下一个点击触发点击。

If you are inflating the view dynamically, what you could do is, on the element set:

如果你动态地放大视图,你可以做的是,在元素集上:

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

If this doesn't work, try applying it on the parent view as well.

如果这不起作用,也可以尝试在父视图中应用它。

#8


0  

Its the most simplest way to work with date picker.

这是使用日期选择器最简单的方法。

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


});

#9


-3  

try this:

试试这个:

public class MainActivity extends Activity implements OnClickListener {
 //rest of your code
}

#1


160  

Overview, when a user interacts with any UI component the various listeners are called in a top-down order. If one of the higher priority listeners "consumes the event" then the lower listeners will not be called.

概述,当用户与任何UI组件交互时,以自顶向下的顺序调用各种侦听器。如果一个优先级较高的侦听器“消耗事件”,那么将不调用较低的侦听器。

In your case these three listeners are called in order:

在您的情况下,这三个侦听器依次被调用:

  1. OnTouchListener
  2. OnTouchListener
  3. OnFocusChangeListener
  4. OnFocusChangeListener
  5. OnClickListener
  6. OnClickListener

The first time the user touches an EditText it receives focus so that the user can type. The action is consumed here. Therefor the lower priority OnClickListener is not called. Each successive touch doesn't change the focus so these events trickle down to the OnClickListener.

用户第一次触摸EditText时,它会接收到焦点,以便用户可以输入。这里使用的是操作。因此,对于较低的优先级,不会调用OnClickListener。每一次连续的触摸都不会改变焦点,因此这些事件会逐渐影响到OnClickListener。

Buttons (and other such components) don't receive focus from a touch event, that's why the OnClickListener is called every time.

按钮(和其他类似的组件)不会从触摸事件接收焦点,这就是为什么每次都调用OnClickListener。

Basically, you have three choices:

基本上,你有三个选择:

  1. Implement an OnTouchListener by itself:

    自行实现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;
        }
    });
    

    This will execute every time the EditText is touched. Notice that the listener returns false, this allows the event to trickle down to the built-in OnFocusChangeListener which changes the focus so the user can type in the EditText.

    这将在每次修改EditText时执行。注意,侦听器返回false,这允许事件向下传递到内置的OnFocusChangeListener,它更改了焦点,以便用户可以在EditText中输入。

  2. Implement an OnFocusChangeListener along with the OnClickListener:

    和OnClickListener一起实现OnFocusChangeListener:

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

    This listener catches the first touch event when the focus is changed while your OnClickListener catches every other event.

    当焦点发生改变时,该侦听器将捕获第一个触摸事件,而OnClickListener将捕获所有其他事件。

  3. (This isn't a valid answer here, but it is a good trick to know.) Set the focusable attribute to false in your XML:

    (这不是一个有效的答案,但这是一个很好的技巧。)在XML中将可调焦属性设置为false:

    android:focusable="false"
    

    Now the OnClickListener will fire every time it is clicked. But this makes the EditText useless since the user can no longer enter any text...

    现在OnClickListener将在每次单击时触发。但是这使得EditText无用,因为用户不能再输入任何文本……

Note:

注意:

getApplicationContext() can create memory leaks. A good habit is to avoid using it unless absolutely necessary. You can safely use v.getContext() instead.

getApplicationContext()可以创建内存泄漏。一个好的习惯是在绝对必要的时候避免使用它。您可以安全地使用v.getContext()。

Hope that helps!

希望会有帮助!

#2


6  

make edit text clickable.. In XML android:clickable="true" or in code

让编辑文本可点击. .在XML android中:clickable="true"或在代码中

ed1.setClickable(true);

then do

然后做

ed1.setOnClickListener(new OnClickListener() {

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

#3


3  

I'm probably too late to the party, but here is a code snipped which fixes the issue with onClick() not being called:

我可能已经来不及参加聚会了,但是这里有一个代码片段,它修复了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;
    }
});

#4


0  

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>

#5


0  

Took me a minute to figure this out one time when this happened to me. My ImageButton with a setOnClickListener and onClick didn't seem to fire and then I realized it was actually underneath another element in my xml layout, so I turned this:

有一次,我花了一分钟才弄明白这件事。我的ImageButton带有setOnClickListener和onClick,然后我意识到它实际上在我的xml布局的另一个元素下面,所以我把它变成:

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

into this:

到这个:

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

and suddenly the ImageButton was not being overlapped by the other layout since it was now added later to the parent layout and was now on top and works every time. Good luck, always fun when basic stuff suddenly seems to stop working

突然之间,ImageButton没有被其他布局重叠,因为它后来被添加到父布局中,现在在顶部,每次都可以工作。祝你好运,当最基本的东西突然停止工作时,你总是很开心

#6


0  

Avoid using a FocusChangeListener since it will behave erratically when you don't really need it (eg. when you enter an activity). Just set an OnTouchListener along with your OnClickListener like this:

避免使用FocusChangeListener,因为当你不需要它的时候它会表现得很不稳定。当你进入一个活动)。设置一个OnTouchListener和OnClickListener就像这样:

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

This will cause your EditText to receive focus at first, and your onClick to function properly the first time.

这将使您的EditText首先接收焦点,并使您的onClick首次正常工作。

#7


0  

This happens because the first tap gains the focus into the view. The next tap triggers the click.

之所以会出现这种情况,是因为第一次点击将焦点转移到视图中。下一个点击触发点击。

If you are inflating the view dynamically, what you could do is, on the element set:

如果你动态地放大视图,你可以做的是,在元素集上:

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

If this doesn't work, try applying it on the parent view as well.

如果这不起作用,也可以尝试在父视图中应用它。

#8


0  

Its the most simplest way to work with date picker.

这是使用日期选择器最简单的方法。

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


});

#9


-3  

try this:

试试这个:

public class MainActivity extends Activity implements OnClickListener {
 //rest of your code
}