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
がクリックされると、それはしない発火します。大問題。
概要、ユーザーがUIコンポーネントを操作すると、さまざまなリスナーがトップダウンの順序で呼び出されます。優先度の高いリスナーの1つが「イベントを消費する」場合、低いリスナーは呼び出されません。
あなたの場合、これらの3つのリスナーは順番に呼び出されます:
ユーザーが初めてEditTextにタッチすると、ユーザーが入力できるようにフォーカスを受け取ります。 アクションはここで消費されます。したがって、優先度の低いOnClickListenerは呼び出されません。連続してタッチするたびにフォーカスは変更されないため、これらのイベントはOnClickListenerにトリクルダウンします。
ボタン(および他のそのようなコンポーネント)はタッチイベントからフォーカスを受け取らないため、OnClickListenerが毎回呼び出されます。
基本的に、3つの選択肢があります:
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を入力できるようにフォーカスを変更します。
OnClickListenerとともにOnFocusChangeListenerを実装します。
_ed1.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
editTextClicked(); // Instead of your Toast
}
});
_
このリスナーは、フォーカスが変更されたときに最初のタッチイベントをキャッチし、OnClickListenerは他のすべてのイベントをキャッチします。
(これはここでは有効な答えではありませんが、知っておくと良いでしょう。)XMLでfocusable属性をfalse
に設定します。
_Android:focusable="false"
_
OnClickListenerは、クリックされるたびに毎回起動します。しかし、ユーザーはテキストを入力できなくなるため、EditTextは役に立たなくなります...
注:
getApplicationContext()
はメモリリークを引き起こす可能性があります。絶対に必要な場合を除き、使用することは避けてください。代わりにv.getContext()
を安全に使用できます。
お役に立てば幸いです!
編集テキストをクリック可能にします。XMLAndroid:clickable="true"
またはコード内
ed1.setClickable(true);
それから
ed1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getBaseContext(), "1",Toast.LENGTH_SHORT).show();
}
});
私はおそらくパーティーには遅すぎますが、ここでは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;
}
});
これは、最初のタップがビューにフォーカスを移動するために発生します。次のタップでクリックがトリガーされます。
ビューを動的に拡大する場合は、次を実行します。
Android:clickable="true"
Android:focusable="false"
Android:focusableInTouchMode="false"
これが機能しない場合は、親ビューにも適用してみてください。
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>
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が親レイアウトに後で追加され、最上位になり、毎回機能するようになったため、突然ImageButtonが他のレイアウトと重なりませんでした。幸運、基本的なものが突然動作しなくなったように見えるときはいつも楽しい
日付ピッカーを操作する最も簡単な方法です。
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;
}
});