onClick 事件未触发|人造人

2022-08-31 16:30:42

我制作了一个非常简单的测试应用程序,其中包含一个活动和一个布局。第一次按下时不会触发 ,因为它应该如此。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>

如果运行此应用程序,然后单击第二个应用程序,然后返回第一个应用程序,则不会触发 .您可以继续来回选择,它根本不会触发。我需要这个基本功能,但一直想不出一种方法让它工作。想法?editTextonClickonClick

通知

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

澄清

当 获得焦点并单击时,将触发该方法。如果聚焦,然后单击,则不会触发。大问题。editText1onClickeditText2editText1


答案 1

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

在你的例子中,这三个侦听器是按顺序调用的:

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

    每次触摸编辑文本时,都会执行此操作。请注意,侦听器返回 ,这允许事件向下涓滴到内置的 OnFocusChangeListener,这会更改焦点,以便用户可以在 EditText 中键入内容。false

  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 中将可聚焦属性设置为:false

    android:focusable="false"
    

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

注意:

getApplicationContext() 可以创建内存泄漏。一个好的习惯是除非绝对必要,否则避免使用它。您可以放心使用。v.getContext()

希望有所帮助!


答案 2

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