48

In the layout you can set the EditText widget to be non-editable via the android:editable attribute.

How can I do this in code? I need to make the EditText widget to be editable depending on conditions.

Nikhil
  • 16,194
  • 20
  • 64
  • 81
AngryHacker
  • 59,598
  • 102
  • 325
  • 594

14 Answers14

45
editText.setFocusable(false);
editText.setClickable(false);

this ensure the EditText control can't be selected and focused, so it can't be edited.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
Gerry
  • 459
  • 1
  • 4
  • 2
32

I just tried this myself,

To disable editing text:

.setFocusable(false);

this also sets setFocusableInTouchMode to false!

To enable editing text:

setFocusableInTouchMode(true);

this also sets setFocusable to true;

atpanos
  • 473
  • 6
  • 9
16

The best way to do this is with this single line of code:

textView.setKeyListener(null);

The docs say for this method:

Sets the key listener to be used with this TextView. This can be null to disallow user input.

Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
  • 1
    This may work, but what if you need to switch between editable and non-editable due to some criteria? You'd have to create your own KeyListener in order to set it back to editable, which feels wrong. – John Jun 15 '11 at 14:12
  • Has other side effects, like killing selection for copy, too. – James Moore Jul 02 '11 at 00:55
  • What Christopher suggested should work. It allows you to select and copy text from the field just the same as if you had defined the field not editable from the xml (I don't know what James is talking about, but it works fine at least on Android 2.2.). Looking at the source code that's pretty much what is done when the xml attribute enabled is set to false for any TextView. As per the documentation you may need to call setFocusable(true) after calling setKeyListener(null). – Timo Dec 10 '11 at 23:14
  • 1
    @John You can call `getKeyListener()` first and stash it for later use can't you (if it was previously set)? Or perhaps map the getInputType to some key listener manually. Or just force some known good key listener. E.g. you should be able to set (didn't test it) the default TextKeyListener with this: `textView.setKeyListener(TextKeyListener.getInstance());` – Timo Dec 10 '11 at 23:20
  • KeyListener docs: "Key presses on soft input methods are not required to trigger the methods in this listener, and are in fact discouraged to do so. The default android keyboard will not trigger these for any key to any application targetting Jelly Bean or later, and will only deliver it for some key presses to applications targetting Ice Cream Sandwich or earlier." – stephen Feb 15 '13 at 17:52
13

I think an InputFilter that rejects all changes is a good solution:

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

Edit: dlazar suggested (below) to change the return to dst.subSequence(dstart, dend) to overcome behavior that removes words.

sfmirtalebi
  • 370
  • 7
  • 16
Josef Pfleger
  • 74,165
  • 16
  • 97
  • 99
6
android:editable="false" 
android:inputType="none" 

in your xml or

EditText mEdit = (EditText) findViewById(R.id.yourid);
mEdit.setEnabled(false);

or

EditText mEdit = (EditText) findViewById(R.id.yourid);
mEdit.setKeyListener(null);
Deepzz
  • 4,573
  • 1
  • 28
  • 52
abhi
  • 759
  • 6
  • 15
6

You can try this:

        mEditText.setFocusable(false);
        mEditText.setClickable(false);
        mEditText.setFocusableInTouchMode(false);
        mEditText.setLongClickable(false);
        mEditText.setInputType(InputType.TYPE_NULL);

This will completely disable EditText, disable long press if you don't want user to open edit text options.

oriolparra
  • 212
  • 6
  • 21
Babasaheb
  • 683
  • 6
  • 20
3

[Posting a new answer, since I can't comment on Josef's answer.]

The input filter works fine, but it has a subtle bug in it: typing over a selection will delete all the text.

For example, say you have the text "foo" in the EditText. If you select it all (e.g., by double-clicking on it) and type 'a', the text will disappear. This is because the InputFilter will be called as:

filter("a", 0, 1, "foo", 0, 3);

The proposed input filter will return the empty string in this case (because src.length() < 1 is false), which explains the missing text.

The solution is to simply return dst.subSequence(dstart, dend) in the filter function. This will work fine even for deletions.

dlazar
  • 31
  • 1
3

I guess

Edittext.setEnabled(false); 

through code

and

android:enabled="false"

through xml.Also check this post on SO.

They should work and you can enable again programatically Edittext.setEnabled(true);

Community
  • 1
  • 1
Anirudh Sharma
  • 7,968
  • 13
  • 40
  • 42
  • I dont want to take the ownership of that answer, I just made the correction which was necessary to make it work, ok. In rails in my code the ID of both text and drop down generates automatically and they are same, so I need to add classes and compare using class, mind, it...even if I am a beginner, I dont need any credits of others....I am commenting here as I dont have any other way to contact you, thank you bye. http://stackoverflow.com/a/34760933/5239247 – Praveen George Jan 13 '16 at 12:33
3

I do not see a related method for that attribute in the EditText class. However, there are other similar things you could use such as android:focus/setFocusable(boolean) or create another TextView whose android:editable="false" and use setVisiblilty() to switch between the editable and not editable views. If you use View.GONE the user will never know there are two EditTexts.

If your feeling ambitious you could probably do something with the EditText's onTextChanged listener like having it react with a setText.

Will
  • 19,789
  • 10
  • 43
  • 45
  • Considering the flaky nature of the KeyListeners (relative to soft keyboard), I was discouraged from messing with those or the edit text properties. I consider this the most robust answer. – stephen Feb 15 '13 at 18:32
3

Have you tried setText(java.lang.CharSequence, android.widget.TextView.BufferType) ? It's described as:

Sets the text that this TextView is to display (see setText(CharSequence)) and also sets whether it is stored in a styleable/spannable buffer and whether it is editable.

(emphasis mine)

Philipp Reichart
  • 20,771
  • 6
  • 58
  • 65
pjz
  • 41,842
  • 6
  • 48
  • 60
  • Thanks for the effort, but I just tried and it makes no difference whatsoever. Furthermore, there isn't any documentation on what the enum values even mean. – AngryHacker Mar 20 '09 at 00:59
1

I wanted to also point out an alternative solution that works nicely if you are creating new instances of an EditView. You can override the method getDefaultEditable() as suggested by the docs to return false. E.g.

EditText view = new EditText(DiscountCalculator.this) {
    public boolean getDefaultEditable() {
        return false;
    }
};
Timo
  • 3,335
  • 30
  • 25
0

The only solution I have found for this scenario is to create 2 layouts. One is editable and one is not. You may have to create more than 2 layouts based on various conditions. Store the conditions in SharedPreferences or other means and load the relevant layout based on conditions after restarting the Activity. Here's an example:

in onCreate() of the activity:

    configuration = new Configuration(this.getSharedPreferences(Configuration.SHARED_PREFERENCES_FILE_NAME, Context.MODE_PRIVATE));
    manualSettingsMode = configuration.isManualSettingsMode();
    if(manualSettingsMode){
        setContentView(R.layout.editableconfigurationsettings);
    }else {
        setContentView(R.layout.configurationsettings);
    }

The activity can be restarted based on testing for condition and calling functions as:

private void setManualEditing(){
    configuration.set_isManualSettingsMode(true);
    this.recreate();
}

private void setAutoEditing(){
    configuration.set_isManualSettingsMode(false);
    this.recreate();
}

Hope this helps. There really has to be a better solution, but this is what I've been doing. Ideally, one would be able to do this on individual fields and not have to reload the activity / layouts. -bobby

-1

try this:

 mEditText.setFilters(new InputFilter[]{new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (XXX) {
                return "";
            } else {
                return null;
            }
        }
    }});
kajibu
  • 174
  • 1
  • 7
-1

I think the correct way to achieve the desired effect is:

mEditView.setText("my text", BufferType.NORMAL);

If you want to switch between editable and non-editable you can do the following:

// Switch to non-editable
mEditView.setText(mEditView.getText(), BufferType.NORMAL);

// Switch back to editable
mEditView.setText(mEditView.getText(), BufferType.EDITABLE);
forgemo
  • 4,634
  • 5
  • 22
  • 25
  • Try substituting mEditView.getText().toString() instead, and see if that works. I think this might actually work for you. – Kevin Coppock Jan 21 '11 at 16:43
  • I think this only effects on the buffer and that doesn't make the field in the ui uneditable as then I suppose it will just contain immutable buffer that it gets discarded if there are any changes. – Timo Dec 10 '11 at 22:25
  • Agreed, this doesn't help much, prevents user from modifying input contents but in a really silly way. – devmiles.com Jan 23 '12 at 22:12