EditText onClickListener w systemie Android

86

Chcę EditText, który po naciśnięciu tworzy DatePicker. Więc piszę następujący kod:

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

    });

Ale kiedy naciskam EditText, akcja jest typowa: kursor czekający na wpisanie tekstu zamiast tego pokazuje okno dialogowe, które chcę.

xger86x
źródło
Zamiast okna dialogowego EditText należy użyć pokrętła.
Ryan R

Odpowiedzi:

129

Klawiatura wydaje się wyskakiwać, gdy tekst EditText staje się aktywny. Aby temu zapobiec, ustaw focusable na false:

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

To zachowanie może się różnić w zależności od smaków systemu operacyjnego Android różnych producentów, ale na testowanych urządzeniach uznałem to za wystarczające. Jeśli klawiatura nadal się pojawia, użycie podpowiedzi zamiast tekstu również wydaje się pomocne:

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

Gdy to zrobisz, Twój odbiornik po kliknięciu powinien działać zgodnie z oczekiwaniami:

myEditText.setOnClickListener(new OnClickListener() {...});
Dillon Kearns
źródło
Wydaje się, że to działa, ale kiedy wpiszesz pole i klikniesz Dalej na klawiaturze, pominie to pole z ustawieniem fokusu na false.
Sterling Diaz
60

Zwykle potrzebujesz maksymalnej zgodności z EditTextnormalnym zachowaniem.

Więc należy nie używać android:focusable="false"jako, tak, widok po prostu nie być aktywowana już który wygląda źle. Na przykład tło do rysowania nie będzie już pokazywać stanu „wciśniętego”.

Zamiast tego powinieneś zrobić:

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

Ustawiając typ wejścia na TYPE_NULL, zapobiegasz wyskakiwaniu klawiatury programowej.

Ustawiając OnClickListeneri OnFocusChangeListener, upewniasz się, że okno dialogowe będzie zawsze otwierane po kliknięciu przez użytkownika w EditTextpolu, zarówno gdy zostanie ono aktywowane (pierwsze kliknięcie), jak i po kolejnych kliknięciach.

Samo ustawienie android:inputType="none"lub setInputType(InputType.TYPE_NULL)nie zawsze wystarczy. W przypadku niektórych urządzeń należy również ustawić android:editable="false"w języku XML, chociaż jest on przestarzały. Jeśli to już nie działa, zostanie po prostu zignorowane (tak jak wszystkie atrybuty XML, które nie są obsługiwane).

krakanie
źródło
Kiedy to zrobię, okno dialogowe otwiera się ponownie po zamknięciu, ponieważ edytor znów staje się aktywny. Jakoś to obejść?
AdamMc331
@ McAdam331 Czy ten EditTextkomponent jest być może jedynym widżetem w Twoim układzie? Czy możesz spróbować dodać coś android:focusable="true"do układu nadrzędnego?
krakanie
1
@caw Dzięki za odpowiedź, ale w końcu udało mi się go uruchomić za pomocą onTouch. Dzięki!
AdamMc331
Otóż ​​to. Pracować w porządku.
XueQing
31

Miałem ten sam problem. Kod jest w porządku, ale upewnij się, że zmienisz ustawioną wartość EditText na false.

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

Mam nadzieję, że pomoże to każdemu, kto miał podobny problem!

Yusuf Hoque
źródło
4
Nie ustawiaj też enabled = "false", co spowoduje wyłączenie onClickListener
OatsMantou
25

Domyślne działanie EditText: przy pierwszym kliknięciu skupia się, a przy drugim kliknięciu obsługuje, onClickListenerwięc musisz wyłączyć fokus. Następnie po pierwszym kliknięciu onClickListenerklamki.

Aby to zrobić, musisz dodać ten android:focusableInTouchMode="false"atrybut do swojego EditText. Otóż ​​to!

Coś takiego:

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusableInTouchMode="false"
        android:inputType="text" />
Akshay Chordiya
źródło
4
Działa, ale EditTextnie można go edytować, a kursor się nie pojawia.
CoolMind
17

Oto rozwiązanie, które wdrożyłem

mPickDate.setOnKeyListener(new View.OnKeyListener() {

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

LUB

mPickDate.setOnFocusChangeListener(new View.OnFocusChangeListener() {

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

    }
});

Sam zobacz różnice. Problem polega na tym, że (jak powiedział RickNotFred) TextView, aby wyświetlić datę i edytować za pośrednictwem DatePicker. TextEdit nie jest używany w swoim głównym celu. Jeśli chcesz, aby DatePicker pojawił się ponownie, musisz wprowadzić delete (1. przypadek) lub de focus (2. przypadek).

Promień

Raymond Chenon
źródło
2
chyba że dodasz onClickListener, który właśnie zrobiłem razem z onFocusChangeListener. To zadziała :-)
neteinstein
Drugie rozwiązanie zadziałało dla mnie, dziękuję! :)
Celtik
9

Jeśli używasz akcji OnClick na EditText, takich jak:

Jawa:

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

});

lub kotlin:

editTextChooseDate.setOnClickListener {
        showDialog(DATEINIT_DIALOG)
    }

Tak, to będzie działać idealnie jeśli umieścisz w xmlswoich EditTextnastępujących linii:

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

Na przykład:

<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"/>

lub dla MaterialDesign

<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>
V marzec
źródło
8

IMHO Nie zgadzam się z oświadczeniem RickNotFreda:

Pojawienie się okna dialogowego, gdy EditText staje się fokusem, wygląda jak niestandardowy interfejs.

Wyświetlenie okna dialogowego do edycji daty, gdy użytkownik naciśnie przycisk EditText, jest bardzo podobne do domyślnego, które polega na wyświetlaniu klawiatury lub klawiatury numerycznej. Fakt, że data jest wyświetlana w EditText sygnalizuje użytkownikowi, że data może ulec zmianie. Wyświetlanie daty jako nieedytowalnego TextView sygnalizuje użytkownikowi, że nie można zmienić daty.

fishjd
źródło
7

Fajny temat. Cóż, zrobiłem to. W pliku XML:

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

W kodzie Java:

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();
    }
};
CoolMind
źródło
6

Poniższe działa idealnie dla mnie.

Najpierw ustaw wejście widgetu wyboru daty na „brak”, aby zapobiec wyskakiwaniu klawiatury:

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

Następnie dodaj te detektory zdarzeń, aby wyświetlić okno dialogowe zawierające selektor dat:

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

Ostatnia rzecz. Aby upewnić się, że wpisane dni, miesiące lub lata są poprawnie skopiowane z selektora dat, zadzwoń datePicker.clearFocus()przed pobraniem wartości, na przykład przez getMonth().

Lukas Batteau
źródło
Prosta poprawka: dla pewności wykonaj discissDialog przed każdym showDialog.
Lukas Batteau,
5

To działa dla mnie:

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

});
Rahim Rahimov
źródło
3

Oto, co zadziałało dla mnie

Ustaw edytowalne na fałsz

<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"

/>

Następnie dodaj detektor zdarzeń dla OnFocusChange

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

@Override
 public void onFocusChange(View v, boolean hasFocus) {
   if (hasFocus){
     showDialog(DATE_DIALOG_ID);
   }
 }
};
Matt
źródło
3
Uważaj na telefony Motorola z systemem Android 2.3.x. Jeśli EditText znajduje się gdzieś w przewijalnym obszarze, Motorola automatycznie ustawi fokus podczas przewijania. Oznacza to, że możesz przewinąć w dół, a kiedy EditText stanie się aktywny, pojawi się okno dialogowe z datą, co jest zaskakujące i złe.
Eric Burke
2

Jak zasugerował Dillon Kearns, ustawienie fokusu na fałszywe działa dobrze. Ale jeśli Twoim celem jest anulowanie klawiatury po kliknięciu EditText, możesz użyć:

mEditText.setInputType(0);
imbrizi
źródło
2

Dlaczego nikt o tym nie wspomniał setOnTouchListener? Używanie setOnTouchListenerjest łatwe i w porządku, a po prostu zwraca wartość true, jeśli odbiornik wykorzystał zdarzenie, w przeciwnym razie zwraca wartość false.

kaczor
źródło