Android'de EditText onClickListener


86

Basıldığında bir DatePicker oluşturan bir EditText istiyorum. Bu yüzden şu kodu yazıyorum:

    mEditInit = (EditText) findViewById(R.id.date_init);
    mEditInit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showDialog(DATEINIT_DIALOG);
        }

    });

Ama Metni Düzenle'ye bastığımda tipik bir eylem: metin yazmayı bekleyen bir imleç bunun yerine istediğim Diyaloğu gösteriyor.


Metni Düzenle iletişim kutusu yerine bir değer değiştirici kullanmalısınız.
Ryan R

Yanıtlar:


129

EditText odak kazandığında klavye açılır gibi görünüyor. Bunu önlemek için odaklanabilirliği yanlış olarak ayarlayın:

<EditText
    ...
    android:focusable="false"
    ... />

Bu davranış, farklı üreticilerin Android işletim sistemi çeşitlerine göre değişebilir, ancak test ettiğim cihazlarda bunu yeterli buldum. Klavye hala açılıyorsa, metin yerine ipuçları kullanmak da yardımcı olabilir:

myEditText.setText("My text");    // instead of this...
myEditText.setHint("My text");    // try this

Bunu yaptıktan sonra, tıklama dinleyiciniz istendiği gibi çalışmalıdır:

myEditText.setOnClickListener(new OnClickListener() {...});

Bu işe yarıyor gibi görünüyor, ancak bir alana yazıp klavyede İleri'yi tıkladığınızda, alanı yanlışa odaklanarak atlar.
Sterling Diaz

60

Normalde, EditTextnormal davranışıyla maksimum uyumluluk istersiniz .

Eğer gereken Yani değil kullanmak android:focusable="false"gibi evet, görünüm sadece kötü görünüyor ki artık odaklanabilir olmayacaktır. Arka plan çizilebilir, örneğin artık "basılı" durumunu göstermeyecektir.

Bunun yerine yapmanız gereken şey şudur:

myEditText.setInputType(InputType.TYPE_NULL);
myEditText.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // showMyDialog();
    }
});
myEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // showMyDialog();
        }
    }
});

Giriş türünü olarak ayarlayarak, TYPE_NULLyazılım klavyesinin açılmasını engellersiniz.

Ayarlayarak OnClickListenerve OnFocusChangeListener, kendi iletişim daima açılacaktır emin zaman içine kullanıcı tıkladığında EditTextalanında, hem de odak (İlk tıklama) ve müteakip tıklamalarının kazanır zaman.

Sadece ayarlamak android:inputType="none"veya setInputType(InputType.TYPE_NULL)her zaman yeterli değildir. Bazı cihazlar android:editable="false"için, kullanımdan kaldırılmış olmasına rağmen XML olarak da ayarlamalısınız . Artık çalışmıyorsa, sadece yok sayılacaktır (desteklenmeyen tüm XML öznitelikleri gibi).


Bunu yaptığımda, iletişim kutusu kapandıktan sonra yeniden açılıyor çünkü edittext yeniden odak kazanıyor. Bunun etrafında herhangi bir yolu var mı?
AdamMc331

@ McAdam331 Bu EditTextbileşen mizanpajınızdaki tek bileşen olabilir mi? android:focusable="true"Ebeveyn düzeninize eklemeyi deneyebilir misiniz ?
2016

1
@caw Yanıt verdiğiniz için teşekkürler, ancak onTouch kullanarak çalışmaya başladım. Teşekkürler!
AdamMc331

Bu kadar. İyi çalışıyor.
XueQing

31

Ben de aynı sorunu yaşadım. Kodda sorun yok, ancak EditText'in odaklanabilir değerini false olarak değiştirdiğinizden emin olun.

<EditText
android:id="@+id/date"
android:focusable="false"/>

Umarım bu, benzer bir sorunu olan herkese yardımcı olur!


4
Ayrıca, onClickListener
OatsMantou

25

Varsayılan çalışma EditText: İlk tıklamada odaklanır ve ikinci tıklamada işler, onClickListenerböylece odağı devre dışı bırakmanız gerekir. Sonra ilk tıklamada onClickListenerişleyecektir.

Bunu yapmak için bunu eklemelisin android:focusableInTouchMode="false" özniteliği EditText. Bu kadar!

Bunun gibi bir şey:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />

4
Çalışır, ancak EditTextdüzenlenemez hale gelir ve imleç görünmez.
CoolMind

17

İşte uyguladığım çözüm

mPickDate.setOnKeyListener(new View.OnKeyListener() {

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        showDialog(DATE_DIALOG_ID);
        return false;
    }
});

VEYA

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        showDialog(DATE_DIALOG_ID);

    }
});

Farkları kendiniz görün. O zamandan beri sorun var (RickNotFred'in söylediği gibi) TextView, tarihi görüntülemek ve DatePicker aracılığıyla düzenleme yapmak. TextEdit, birincil amacı için kullanılmaz. DatePicker'ın yeniden açılmasını istiyorsanız, delete (1. durum) veya odak (2. durum) girmeniz gerekir.

Ray


2
bir onFocusChangeListener ile birlikte yaptığım bir onClickListener eklemediğiniz sürece. Bu işe yarayacak :-)
neteinstein

İkinci çözüm benim için çalıştı, teşekkürler! :)
Çeltik

10

EditText'te OnClick eylemini aşağıdaki gibi kullanırsanız:

java:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});

veya kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

Bu nedenle, aşağıdaki satırlardan xmlbirini koyarsanız mükemmel çalışacaktır EditText:

android: inputType = "none"
android: focusable = "false"
android: cursorVisible = "false"

Örneğin:

<EditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"
            android:cursorVisible="false"/>

veya MaterialDesign için

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/layoutEditTextChooseDate"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

    <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/date_init" 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:hint="Select Date"
            android:inputType="none"
            android:focusable="false"                      
            android:cursorVisible="false"/>

</com.google.android.material.textfield.TextInputLayout>

8

IMHO RickNotFred'in açıklamasına katılmıyorum:

Bir EditText odak aldığında bir iletişim kutusu açmak standart olmayan bir arayüz gibi görünüyor.

Kullanım bir EditText'e bastığında tarihi düzenlemek için bir iletişim kutusu görüntülemek, bir klavye veya sayısal tuş takımı görüntülemek olan varsayılana çok benzer . Tarihin EditText ile görüntülenmesi kullanıcıya tarihin değiştirilebileceğini bildirir. Tarihin düzenlenemez bir TextView olarak görüntülenmesi kullanıcıya tarihin değiştirilemeyebileceğini bildirir.


7

Güzel konu. Ben de yaptım. XML dosyasında:

<EditText
    ...
    android:editable="false"
    android:inputType="none" />

Java kodunda:

txtDay.setOnClickListener(onOnClickEvent);
txtDay.setOnFocusChangeListener(onFocusChangeEvent);

private View.OnClickListener onOnClickEvent = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        dpDialog.show();
    }
};
private View.OnFocusChangeListener onFocusChangeEvent = new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus)
            dpDialog.show();
    }
};

6

Aşağıdakiler benim için mükemmel çalışıyor.

Yazılım klavyesinin açılmasını önlemek için önce tarih seçici widget'ınızın girişini 'yok' olarak ayarlayın:

<EditText android:inputType="none" ... ></EditText>

Ardından, tarih seçiciyi içeren iletişim kutusunu göstermek için şu olay dinleyicilerini ekleyin:

// Date picker
EditText dateEdit = (EditText) findViewById(R.id.date);
dateOfBirthEdit.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            showDialog(DIALOG_DATE_PICKER);
        }
        return false;
    }
});

dateEdit.setOnFocusChangeListener(new OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            showDialog(DIALOG_DATE_PICKER);
        } else {
            dismissDialog(DIALOG_DATE_PICKER);
        }
    }
});

Son bir şey. Yazılan günlerin, ayların veya yılların tarih seçiciden doğru bir şekilde kopyalandığından emin olmak datePicker.clearFocus()için değerleri almadan önce, örneğin aracılığıyla arayın getMonth().


Basit çözüm: Emin olmak için her showDialog'dan önce dismissDialog yapın.
Lukas Batteau

5

Bu Benim İçin Çalışıyor:

mEditInit = (EditText) findViewById(R.id.date_init);
mEditInit.setKeyListener(null);
mEditInit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
            {
                mEditInit.callOnClick();
            }
        }
    });
mEditInit.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showDialog(DATEINIT_DIALOG);
    }

});

3

İşte benim için işe yarayan şey

Düzenlenebilirliği yanlış olarak ayarla

<EditText android:id="@+id/dob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Date of Birth"
android:inputType="none"
android:editable="false"

/>

Ardından OnFocusChange için bir olay dinleyicisi ekleyin

private  View.OnFocusChangeListener onFocusChangeDOB= new View.OnFocusChangeListener() {

@Override
 public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus){
     showDialog(DATE_DIALOG_ID);
   }
 }
};

3
Android 2.3.x çalıştıran Motorola telefonlarına dikkat edin. EditText kaydırılabilir bir alandaysa, Motorola kaydırdığınızda odağı otomatik olarak hareket ettirir. Bu, aşağı kaydırabileceğiniz anlamına gelir ve Metni Düzenle odak kazandığında, şaşırtıcı ve kötü olan tarih iletişim kutunuz açılır.
Eric Burke

2

Dillon Kearns'ın önerdiği gibi, odaklanılabilirliği yanlışa çevirmek işe yarar. Ancak amacınız EditText tıklandığında klavyeyi iptal etmekse, şunu kullanmak isteyebilirsiniz:

mEditText.setInputType(0);

2

Neden kimse bahsetmedi setOnTouchListener? Kullanımı setOnTouchListenerkolay ve uygundur ve dinleyici olayı tüketmişse sadece true, aksi takdirde false döndürür.


0

OnFocusChangeListener kullanan çözümlerle ilgili sorun, herhangi bir odak kazancını tıklama olarak yorumlamalarıdır. Bu% 100 doğru değil: EditText'iniz bir tıklamadan başka bir şeyden odaklanabilir.

Eğer varsa kesinlikle tıklama önem ve (ne olursa olsun odak) sürekli tıklayın algılamak istiyorum, bir de kullanabilirsiniz GestureDetector:

editText.setOnConsistentClickListener { /* do something */ }

fun EditText.setOnConsistentClickListener(doOnClick: (View) -> Unit) {
    val gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapUp(event: MotionEvent?): Boolean {
            doOnClick(this@setOnConsistentClickListener)
            return false
        }
    })

    this.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent) }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.