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ę.


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

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).


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!


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

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ń


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>

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.


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

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().


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

});

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

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

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.