onClick事件未触发| Android的

时间:2012-08-03 06:42:01

标签: java android onclick

我用一个活动和一个布局制作了一个非常简单的测试应用程序。第一次按下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 个答案:

答案 0 :(得分:179)

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

在您的情况下,按顺序调用这三个侦听器:

  1. OnTouchListener
  2. OnFocusChangeListener
  3. OnClickListener
  4. 用户第一次触摸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. (这不是一个有效的答案,但这是一个很好的技巧。)在您的XML中将focusable属性设置为false

      android:focusable="false"
      

      现在,OnClickListener将在每次点击时触发。但这会使EditText变得无用,因为用户无法再输入任何文本......

    4. 注意:

      getApplicationContext()可能会造成内存泄漏。除非绝对必要,否则一个好习惯是避免使用它。您可以安全地使用v.getContext()

      希望有所帮助!

答案 1 :(得分:5)

使编辑文字可点击..   在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();
    }
  });

答案 2 :(得分:4)

我可能来不及派对了,但是这里有一段代码剪辑修复了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;
    }
});

答案 3 :(得分:2)

这是因为第一次点击使焦点进入视图。下一次点击会触发点击。

如果要动态膨胀视图,请执行以下操作:

android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="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)

在我遇到这种情况时,我花了一分钟时间想出这一点。我的ImageButton setOnClickListeneronClick似乎无法启动,然后我意识到它实际上位于我的xml布局中的另一个元素下面,所以我转过身来:

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

进入这个:

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

突然之间,ImageButton没有与其他布局重叠,因为它现在稍后被添加到父布局中,现在位于顶部并且每次都有效。祝你好运,当基本的东西突然停止工作时总是很有趣

答案 6 :(得分:0)

避免使用FocusChangeListener,因为当您不需要它时它会表现不正常(例如,当您进入活动时)。只需设置一个OnTouchListenerOnClickListener,就像这样:

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

这将使您的EditText首先获得焦点,并使您的onClick第一次正常运行。

答案 7 :(得分:0)

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

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


});

答案 8 :(得分:0)

简单,可重复使用的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
}