34

I'm searching for a way to prevent the user from moving the cursor position anywhere. The cursor should always stay at the end of the current EditText value. In addition to that the user should not be able to select anything in the EditText. Do you have any idea how to realize that in Android using an EditText?

To clarify: the user should be able to insert text, but only at the end.

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
Louis
  • 2,140
  • 4
  • 19
  • 18

5 Answers5

53

I had the same problem. This ended up working for me:

public class CustomEditText extends EditText {

    @Override
    public void onSelectionChanged(int start, int end) {

        CharSequence text = getText();
        if (text != null) {
            if (start != text.length() || end != text.length()) {
                setSelection(text.length(), text.length());
                return;
            }
        }

        super.onSelectionChanged(start, end);
    }

}
mikejonesguy
  • 9,779
  • 2
  • 35
  • 49
  • 1
    Yes I ended up with somewhat similar. I am not that much satisfied with this solution as there is still this blue handle, but it's OK as long as I don't know any better approach. Thanks anyway. – Louis Oct 30 '12 at 15:39
  • May i suggest to removed the `return` so we definitively call `super` each time? Why? When someone adjusts this code to his needs it is easy to produce a bug: My users may select all letters except the first two. Selecting multiple letters and then moving the right side of the selection breaks your solution, but works fine with mine :) – m.reiter Sep 10 '21 at 07:51
9

Try this:

mEditText.setMovementMethod(null);
Jason Lin
  • 239
  • 3
  • 4
7

This will reset cursor focus to the last position of the text

editText.setSelection(editText.getText().length());

This method will disable cursor move on touch

public class MyEditText extends EditText{

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
         final int eventX = event.getX();
         final int eventY = event.getY();
         if( (eventX,eventY) is in the middle of your editText)
         {
              return false;
         }
         return true;
    }
}

And You can use either the xml attribute

android:cursorVisible

or the java function

setCursorVisible(boolean)

to disable blinking cursor of edittext

Hein
  • 2,675
  • 22
  • 32
  • Note that you still have to worry about arrow keys/trackball/D-pad changing the cursor position -- that might be handled by some sort of `onKeyDown()` shenanigans. And, this does not *disable* selection, and I do not know if that is possible. – CommonsWare Jun 23 '12 at 15:07
  • Thank you but this is not exactly the solution I was looking for. The problem with disabling all touch events on the view is that then you can't focus the view at all. And I'd like to have a blinking cursor - just the possibility to move the cursor should be disabled. – Louis Jun 23 '12 at 15:36
1

It sounds like the best way to do this is to make your own CustomEditText class and override/modify any relevant methods. You can see the source code for EditText here.

public class CustomEditText extends EditText {

    @Override
    public void selectAll() {
        // Do nothing
    }

    /* override other methods, etc. */

}
Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
0

Yes, I know how to do it =) just do it:

Copy the helper class:

class SelectionSpanWatcher(
  private val listener: OnChangeSelectionListener
) : SpanWatcher {

  override fun onSpanAdded(text: Spannable?, what: Any?, start: Int, end: Int) {
    /* do nothing */
  }

  override fun onSpanRemoved(text: Spannable?, what: Any?, start: Int, end: Int) {
    /* do nothing */
  }

  override fun onSpanChanged(text: Spannable?, what: Any?, oStart: Int, oEnd: Int, nStart: Int, nEnd: Int) {
    when (what) {
      SELECTION_START -> listener.onSelectionChanged(Selection.START, oStart, oEnd, nStart, nEnd)
      SELECTION_END   -> listener.onSelectionChanged(Selection.END, oStart, oEnd, nStart, nEnd)
    }
  }

  enum class Selection {
    START,
    END
  }

  fun interface OnChangeSelectionListener {
    fun onSelectionChanged(selection: Selection, oStart: Int, oEnd: Int, nStart: Int, nEnd: Int)
  }
}

Then copy extension method:

fun Editable.setOnSelectionChangedListener(listener: OnChangeSelectionListener?) {
  getSpans(0, length, SelectionSpanWatcher::class.java)
    .forEach { span -> removeSpan(span) }

  if (listener != null) {
    setSpan(SelectionSpanWatcher(listener), 0, length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
  }
}

Then use the copied code as follows (used androidx.core.widget.addTextChangedListener from android-ktx):

editText.addTextChangedListener(afterTextChanged = { editable ->
  editable?.setOnSelectionChangedListener { _, _, _, _, _ ->
    editText.postOnAnimation {
      editText.setSelection(editText.text.length)
    }
  }
})
maXp
  • 1,428
  • 1
  • 15
  • 23