59

1 つのアクティビティと 1 つのレイアウトを持つ非常に単純なテスト アプリケーションを作成しました。は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>

このアプリケーションを実行し、2 番目のものをクリックしてeditTextから最初のものに戻っても、onClick. 前後に選択し続けることができ、まったくトリガーされませんonClick。この基本的な機能が必要ですが、機能させる方法が思い浮かびませんでした。アイデア?

知らせ

API レベル 16 の物理デバイスと API レベル 8 エミュレーターで推奨されるすべての方法を試しましたが、同じ問題が発生します。

明確化

editText1フォーカスされてクリックされると、onClickメソッドが起動します。editText2がフォーカスされてからeditText1クリックされた場合、発火しません。大問題。

4

9 に答える 9

213

概要:ユーザーが任意の UI コンポーネントを操作すると、さまざまなリスナーがトップダウンの順序で呼び出されます。優先度の高いリスナーの 1 つが「イベントを消費する」場合、優先度の低いリスナーは呼び出されません

あなたの場合、次の 3 つのリスナーが順番に呼び出されます。

  1. OnTouchListener
  2. OnFocusChangeListener
  3. OnClickListener

ユーザーが初めて EditText に触れると、ユーザーが入力できるようにフォーカスが与えられます。アクションはここで消費されます。 そのため、優先度の低い OnClickListener は呼び出されません。連続する各タッチはフォーカスを変更しないため、これらのイベントは OnClickListener まで細流します。

ボタン (およびその他のコンポーネント) は、タッチ イベントからフォーカスを受け取らないため、毎回 OnClickListener が呼び出されます。

基本的に、次の 3 つの選択肢があります。

  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。これにより、ユーザーが EditText を入力できるようにフォーカスを変更する組み込みの OnFocusChangeListener にイベントが細流化されます。

  2. OnClickListener とともに OnFocusChangeListener を実装します。

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

    このリスナーは、フォーカスが変更されたときに最初のタッチ イベントをキャッチし、OnClickListener は他のすべてのイベントをキャッチします。

  3. false(これはここでは有効な回答ではありませんが、知っておくと便利な方法です。) XML でfocusable 属性を次のように設定します。

    android:focusable="false"
    

    これで、クリックされるたびに OnClickListener が起動します。しかし、これにより、ユーザーはテキストを入力できなくなるため、EditText は役に立たなくなります...

ノート:

getApplicationContext()メモリ リークが発生する可能性があります。どうしても必要な場合を除き、使用を避けることをお勧めします。代わりに安全に使用できますv.getContext()

それが役立つことを願っています!

于 2012-08-03T16:43:26.097 に答える
5

編集テキストをクリック可能にします。XMLandroid:clickable="true" またはコードで

ed1.setClickable(true);

その後、

ed1.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
      Toast.makeText(getBaseContext(), "1",Toast.LENGTH_SHORT).show();
    }
  });
于 2012-08-03T06:47:18.703 に答える
5

私はおそらくパーティーに遅すぎますが、 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;
    }
});
于 2016-05-05T13:36:16.533 に答える
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>
于 2012-08-03T10:12:56.553 に答える
0

FocusChangeListener本当に必要のないとき (たとえば、アクティビティに入るとき) に不規則に動作するため、 a の使用は避けてください。OnTouchListener次のように設定するだけOnClickListenerです:

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

これにより、最初に EditText がフォーカスを受け取り、最初にonClick正しく機能します。

于 2016-11-07T19:37:41.453 に答える