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ć?



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

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.


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

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

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.


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.


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

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.


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

O wiele bardziej pomocne jest ustawienie odbiornika na null niż wyłączenie go.
Humberto Castañeda


3

Spróbuj użyć

editText.setEnabled(false);
editText.setClickable(false);

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


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

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.


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

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

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.


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

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

0

Ustaw to w pliku EdiTextView xml

android:focusable="false"

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.


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