Ustaw EditText jako tylko do odczytu

119

Chcę utworzyć EditTextwidok tylko do odczytu . Wygląda na to android:editable="false", że XML do wykonania tego kodu jest , ale chcę to zrobić w kodzie.

W jaki sposób mogę to zrobić?

warna
źródło
3
Warto również zauważyć, że android:editablejest to przestarzałe EditText.
Derek W
Najbardziej niezawodnym sposobem jest użycie UI.setReadOnly(myEditText, true)z tej biblioteki . Jest kilka właściwości, które należy ustawić, które można sprawdzić w kodzie źródłowym .
krakanie
3
Tak, Derek ma rację. Teraz w XML powinieneś użyć android:inputType="none"iandroid:textIsSelectable="true"
Atul

Odpowiedzi:

135

Użyj tego kodu.

Edittext.setEnabled(false);
Nikhil
źródło
34
to nie tylko
`
1
To wyłącza. Bezużyteczne zwłaszcza dla wielowierszowego EditText.
Atul
spróbować tego, ale straciłeś na wartości?
fdurmus77
97

Jeśli setEnabled(false)wówczas editTextwyglądałaby wyłączony (szary, itp). Możesz nie chcieć zmieniać wizualnego aspektu swojego edytora.

Mniej inwazyjnym sposobem byłoby użycie setFocusable(false).

Uważam, że to odpowiada na twoje pytanie bliżej twojego pierwotnego zamiaru.

Flexo
źródło
8
To dobrze, ale użytkownik nadal może „wkleić” w polu tekstowym.
xtrem
14
To działało świetnie dla mnie. Potrzebowałem go, aby był klikalny, więc nie mogłem użyć setEnabled (false). Aby obejść problem z wklejaniem, właśnie zrobiłem android: longClickable = "false"
dt0
3
Jeśli używasz setFocusable(false)(a nawet setFocusableInTouchMode(false)z setClickable(false)), możesz nadal zmieniać wartość swojego editTextnaciśnięcia editTextna kilkaset milisekund i wybierając Pasteopcję, chyba że schowek systemowy jest pusty. Przetestowałem to z najnowszym dostępnym API, czyli 23 .
patryk.beza
To działa, jestem w stanie przewijać i nie widzieć kursora.
miłość na żywo
28

W XMLużyciu:

android:editable="false"

Jako przykład:

<EditText
    android:id="@+id/EditText1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:editable="false" />
MaxEcho
źródło
Według Javadoc The editableatrybut nie wydaje się przestarzałe (a przynajmniej nie w poziomu API 23).
Greg Brown,
8
@MichelJung ma rację. musisz użyćandroid:inputType="none"
Ata Iravani
1
Pytanie ma na celu uczynienie edytowalnym fałszem za pomocą kodu Java, a nie XML!
saeed khalafinejad
7
Próbuję, android:inputType="none"a dane są nadal edytowalne.
BlueMonkMN
24

To działa dla mnie:

EditText.setKeyListener(null);
igorinov
źródło
5
Byłoby dobrze, ale użytkownik nadal może „wkleić” w polu. Kciuki w górę, mimo że wygląda to na włamanie. Żałuję, że nie mają interfejsu API setEditable ().
xtrem
15

Najlepiej jest używać TextViewzamiast tego.

Egor
źródło
8
zgodnie z przepływem aplikacji może być konieczne, aby czasami ją edytować, a czasami nie
Muhammed Refaat
15
editText.setInputType(InputType.TYPE_NULL);

Zgodnie z dokumentacją zapobiega to wyświetlaniu klawiatury programowej. Zapobiega również wklejaniu, umożliwia przewijanie i nie zmienia wizualnego aspektu widoku. Jednak zapobiega to również zaznaczaniu i kopiowaniu tekstu w widoku.

Z moich testów ustawienie setInputTypena TYPE_NULLwydaje się być funkcjonalnym odpowiednikiem amortyzacji android:editable="false". Dodatkowo android:inputType="none"wydaje się nie mieć zauważalnego efektu.

Adrian Toman
źródło
Zgoda, na razie działa i jak powiedziałeś, android:inputType="none"już nie działa.
Goke Obasa
1
Niestety nie zapobiega to wpisywaniu w pole, jeśli wirtualna klawiatura jest już otwarta (tzn. Użytkownik najpierw stuka w edytowalne pole, a potem w to - wirtualna klawiatura nie zamyka się). Nie zapobiega też pisaniu w polu z zewnętrznej klawiatury.
jk7
11

android: editable = "false" został wycofany. Dlatego nie możesz go użyć, aby tekst edycji był tylko do odczytu.

Zrobiłem to za pomocą poniższego rozwiązania. Tutaj użyłem

android: inputType = "none"

android: textIsSelectable = "true"

android: focusable = "false"

Spróbuj :)

<EditText
         android:id="@+id/et_newsgpa_university"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
         android:hint="@string/hint_educational_institute"
         android:textSize="@dimen/regular_text"
         android:inputType="none"
         android:textIsSelectable="true"
         android:focusable="false"
         android:maxLines="1"
         android:imeOptions="actionNext"/>
Chanaka Fernando
źródło
Nie jest to tak naprawdę tylko do odczytu, nadal możesz wkleić wartości do edittext w tym kodzie. android:enabled="false"może być dobrą alternatywą.
eVader
7
editText.setEnabled(false);
editText.setFilters(new InputFilter[] { new InputFilter() {
    public CharSequence filter(CharSequence src, int start, int end,
            Spanned dst, int dstart, int dend) {
        return src.length() < 1 ? dst.subSequence(dstart, dend) : "";
    }
} });

To da ci nieedytowalny filtr EditText. najpierw musisz umieścić żądany tekst w polu editText, a następnie zastosować ten filtr.

DArkO
źródło
2
Dobre rozwiązanie i mniej linii kodu niż TextWatcher. Umożliwia to użytkownikowi zaznaczanie i kopiowanie tekstu, ale nie pozwala na jego zmianę przez wpisywanie lub WYTNIJ lub WKLEJ. Instrukcja return może być uproszczona do po prostureturn dst.subSequence(dstart, dend);
jk7
Mój poprzedni komentarz odnosił się tylko do instrukcji setFilters () bez wyłączania pola EditText.
jk7
Dzięki, to jedyne rozwiązanie, które na mnie działa! To frustrujące, że coś działającego zostało zdeprecjonowane i zastąpione czymś (inputType = "none"), co nadal nie działa i ma niepożądany efekt uboczny (wejście wieloliniowe). Zwróć uwagę, że zmiana sugerowana przez @ jk7 jest istotna, ponieważ przy pierwotnej instrukcji return, jeśli zaznaczysz część oryginalnego tekstu i coś wpiszesz, w końcu zastąpisz wybrany tekst pustym ciągiem zwróconym przez filtr. W tym przypadku długość src jest różna od zera i obowiązuje pusty łańcuch.
Paul L
6

napisanie tych dwóch wierszy jest więcej niż wystarczające do twojej pracy.

yourEditText.setKeyListener(null); 
yourEditText.setEnabled(false);
Vishal Pandey
źródło
O wiele bardziej pomocne jest ustawienie odbiornika na null niż wyłączenie go.
Humberto Castañeda
5

ustawione w XML

android:inputType="none" 
Jitendra Surve
źródło
Próbowałem tego i wynik nadal wydaje się możliwy do edycji.
BlueMonkMN
3

Spróbuj użyć

editText.setEnabled(false);
editText.setClickable(false);
kannappan
źródło
To nadal pozwala na skupienie uwagi, naciskając klawisz tab z klawiatury
AlanKley,
3
android:editable

Jeśli jest ustawiona, określa, że TextViewma metodę wprowadzania. Będzie to tekst tekstowy, chyba że określono inaczej. Ponieważ TextViewjest to domyślnie fałszywe. Ponieważ EditTextjest to domyślnie prawda.

Musi być booleanwartość, albo truealbo false.

Może to być również odniesienie do zasobu (w formularzu @[package:]type:name) lub atrybutu motywu (w formularzu ?[package:][type:]name) zawierającego wartość tego typu.

Odpowiada to edytowalnemu globalnemu symbolowi zasobu atrybutu.

Powiązane metody

jclafuente
źródło
2

Spróbuj zastąpić detektor onLongClick tekstu edycji, aby usunąć menu kontekstowe:

EditText myTextField = (EditText)findViewById(R.id.my_edit_text_id);
myTextField.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        return true;
    }
});
Jimmy Ilenloa
źródło
3
Użyłem androida: editable = "false" i android: focusable = "false", a następnie zastąpiłem goLongclick i otrzymałem wynik, który chciałem
JannGabriel
2

Użyj tego kodu:

editText.setEnabled(false);
editText.setTextColor(ContextCompat.getColor(context, R.color.black);

Wyłączenie editTextzapewnia wygląd i zachowanie tylko do odczytu, ale także zmienia text-colorkolor na szary, więc konieczne jest ustawienie koloru tekstu.

Mary Garcia
źródło
Dodaj również wyjaśnienia.
BlackBeard
1

to jest moja implementacja (trochę długa, ale przydatna dla mnie!): Za pomocą tego kodu możesz ustawić EditView jako tylko do odczytu lub Normalny. nawet w stanie tylko do odczytu tekst może być kopiowany przez użytkownika. możesz zmienić tło, aby wyglądało inaczej niż zwykły tekst edycji.

public static TextWatcher setReadOnly(final EditText edt, final boolean readOnlyState, TextWatcher remove) {
    edt.setCursorVisible(!readOnlyState);
    TextWatcher tw = null;
    final String text = edt.getText().toString();
    if (readOnlyState) {
            tw = new TextWatcher();

            @Override
            public void afterTextChanged(Editable s) {

            }
            @Override
            //saving the text before change
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            // and replace it with content if it is about to change
            public void onTextChanged(CharSequence s, int start,int before, int count) {
                edt.removeTextChangedListener(this);
                edt.setText(text);
                edt.addTextChangedListener(this);
            }
        };
        edt.addTextChangedListener(tw);
        return tw;
    } else {
        edt.removeTextChangedListener(remove);
        return remove;
    }
}

Zaletą tego kodu jest to, że EditText jest wyświetlany jako normalny EditText, ale zawartość nie jest zmienna. Wartość zwracana powinna być zachowana jako zmienna, aby umożliwić powrót ze stanu tylko do odczytu do normalnego.

aby uczynić EditText tylko do odczytu, po prostu umieść go jako:

TextWatcher tw = setReadOnly(editText, true, null);

i aby to było normalne użyj tw z poprzedniego oświadczenia:

setReadOnly(editText, false, tw);
Ali sh
źródło
1

To zadziałało w moim przypadku, biorąc pod uwagę kilka z powyższych sugestii. Sprawia, że ​​TextEdit jest fokusem, ale jeśli użytkownik kliknie lub ustawi fokus, wyświetlimy listę wyborów w PopupWindow. (Zastępujemy zwariowany widżet Spinner). TextEdit xml jest bardzo ogólny ...

public void onCreate(Bundle savedInstanceState) {
    ....  
    fEditState = (EditText) findViewById(R.id.state_edit);

    fEditState.setLongClickable(false);
    fEditState.setKeyListener(null);
    fEditState.setFocusable(true);

    fEditState.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        public void onFocusChange(View v, boolean hasFocus)
        {
            if (hasFocus)
            {
               showStatesPopup();

            }
        }
    });

    fEditState.setOnClickListener(new Button.OnClickListener(){

        public void onClick(View arg0)
        {
           showStatesPopup();
        }
    });
    ....
}

private void showStatesPopup()
{
    // fPopupWindowStates instantiated in OnCreate()

    if (!fPopupWindowStates.isShowing()) {
        // show the list view as dropdown
        fPopupWindowStates.showAsDropDown(fEditState, -5, 0);
    }
}  
Johnny O
źródło
1

Jeśli chcesz tylko skopiować tekst z kontrolki, ale nie możesz go edytować, możesz zamiast tego użyć TextView i ustawić tekst, który można zaznaczyć .

kod:

myTextView.setTextIsSelectable(true);
myTextView.setFocusable(true);
myTextView.setFocusableInTouchMode(true);
// myTextView.setSelectAllOnFocus(true);

xml:

<TextView
    android:textIsSelectable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"     
    ...
/>
<!--android:selectAllOnFocus="true"-->


Dokumentacja setTextIsSelectable mówi:

Kiedy wywołujesz tę metodę, aby ustawić wartość textIsSelectable, ustawia ona flagi focusable, focusableInTouchMode, clickable i longClickable na tę samą wartość ...

Jednak musiałem jawnie ustawić focusable i focusableInTouchMode na true, aby działał z wprowadzaniem dotykowym.

AJBauer
źródło
1

To było dla mnie jedyne w pełni proste rozwiązanie.

editText.setEnabled(false);   // Prevents data entry
editText.setFocusable(false); // Prevents being able to tab to it from keyboard
AlanKley
źródło
0

Nie miałem problemu, aby EditTextPreference był tylko do odczytu, używając:

editTextPref.setSelectable(false);

Działa to dobrze w połączeniu z użyciem pola „podsumowanie” do wyświetlania pól tylko do odczytu (przydatne na przykład do wyświetlania informacji o koncie). Aktualizowanie pól podsumowań dynamicznie pobieranych z http://gmariotti.blogspot.com/2013/01/preferenceactivity-preferencefragment.html

private static final List<String> keyList;

static {
    keyList = new ArrayList<String>();
    keyList.add("field1");
    keyList.add("field2");
    keyList.add("field3");
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);

    for(int i=0;i<getPreferenceScreen().getPreferenceCount();i++){
        initSummary(getPreferenceScreen().getPreference(i));
    }
}

private void initSummary(Preference p) {
    if (p instanceof PreferenceCategory) {
        PreferenceCategory pCat = (PreferenceCategory) p;
        for (int i = 0; i < pCat.getPreferenceCount(); i++) {
            initSummary(pCat.getPreference(i));
        }
    } else {
        updatePrefSummary(p);
    }
}

private void updatePrefSummary(Preference p) {
    if (p instanceof ListPreference) {
        ListPreference listPref = (ListPreference) p;
        p.setSummary(listPref.getEntry());
    }
    if (p instanceof EditTextPreference) {
        EditTextPreference editTextPref = (EditTextPreference) p;
        //editTextPref.setEnabled(false); // this can be used to 'gray out' as well
        editTextPref.setSelectable(false);
        if (keyList.contains(p.getKey())) {
            p.setSummary(editTextPref.getText());
        }
    }
}
Jason Harmon
źródło
0

Ustaw to w pliku EdiTextView xml

android:focusable="false"
Nandakishore Shetty
źródło
1
Pytanie dotyczy tego, jak uczynić go programowym tylko do odczytu, a nie XML.
jk7
0

Jak android:editable=""jest przestarzałe,

ustawienie

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

uczyni go „tylko do odczytu”.

Jednak użytkownicy nadal będą mogli wklejać w pole lub wykonywać inne długie kliknięcia. Aby to wyłączyć, po prostu zastąp onLongClickListener ().
W Kotlinie:

  • myEditText.setOnLongClickListener { true }

wystarczy.

Chad Mx
źródło
0

Moje podejście do tego polegało na utworzeniu niestandardowej klasy TextWatcher w następujący sposób:

class ReadOnlyTextWatcher implements TextWatcher {
    private final EditText textEdit;
    private String originalText;
    private boolean mustUndo = true;

    public ReadOnlyTextWatcher(EditText textEdit) {
        this.textEdit = textEdit;
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        if (mustUndo) {
            originalText = charSequence.toString();
        }
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void afterTextChanged(Editable editable) {
        if (mustUndo) {
            mustUndo = false;
            textEdit.setText(originalText);
        } else {
            mustUndo = true;
        }
    }
}

Następnie wystarczy dodać tego obserwatora do dowolnego pola, które ma być tylko do odczytu, mimo że jest włączone:

editText.addTextChangedListener(new ReadOnlyTextWatcher(editText));
Fran Marzoa
źródło