28

Image of a grid-like layout

I am working on Android Smart TV application:

  • In a view there is a custom keyboard and an EditText.

  • When application launches focus goes to the keyboard.

    Desired:

    • When the user types with keyboard (clicking with a remote) the cursor should also blink inside the editText.

How can I show this effect inside the EditText?

TT--
  • 2,956
  • 1
  • 27
  • 46
nitin tyagi
  • 456
  • 1
  • 4
  • 19
  • Please post some code that you have tried til now. – keshav kowshik May 20 '15 at 09:16
  • @Keshav1234 till now i have made an layout which include custom keyboard and edittext. and manually set the focus on keyboard. when foucs goes to edit text then cusrsor is visible. but my requirment is that cursor should always blink in edit text. – nitin tyagi May 20 '15 at 09:34
  • should i change my approach ? Please suggest. – nitin tyagi May 20 '15 at 10:09
  • I am wondering, is the [IME](https://developer.android.com/guide/topics/text/creating-input-method.html) API available in Android TV, too? If yes, why not just implement your custom keyboard this way? – artkoenig Feb 21 '18 at 15:15

12 Answers12

13

This happens if you set a background for the field. If you want to solve this, set the cursorDrawable to @null.

You should add textCursorDrawable with cursorVisible.

Reference to a drawable that will be drawn under the insertion cursor.

android:cursorVisible="true"
android:textCursorDrawable="@null"
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
  • Just tested on API 27 emulator, cursor is hidden, until remove `android:background="@color/transparent"`. – CoolMind Mar 06 '19 at 13:11
7

You can do this..I hope/think that u have a layout for the buttons u have created, by this u can set a Focus Listener for that layout and inside the onFocusChange method you can check if(layout.hasFocus()) and do this...

For example if your editText is named as et, u can set this to it:

et.setActivated(true);
et.setPressed(true);

I have a small example code for you having two edit text

 et2.setOnFocusChangeListener(new OnFocusChangeListener() {

        @Override
        public void onFocusChange(View v, boolean hasFocus) {

            if(et2.hasFocus()){

                //et1.setCursorVisible(true);
                et1.setActivated(true);
                et1.setPressed(true);

            }
        }
    });
Ajeett
  • 814
  • 2
  • 7
  • 18
DJphy
  • 1,292
  • 1
  • 17
  • 31
  • thanks for your answer..through your code i can see the cursor . but cursor position is fixed. requirment is that when i click on button cursor should move inside editetext. – nitin tyagi May 22 '15 at 09:22
7

You could try something like this:

editText.setText(text);
editText.setPressed(true);
editText.setSelection(editText.getText().length()); // moves the cursor to the end of the text

However, there are 2 problems with this approach:

  1. The cursor will not blink. The logic for the blinking is in the Editor class and cannot be overridden. It requires that the EditText is focused, and only 1 View can be focused at once within a Window - in your case that will be one of the keyboard buttons.

    /**
     * @return True when the TextView isFocused and has a valid zero-length selection (cursor).
     */
    private boolean shouldBlink() {
        if (!isCursorVisible() || !mTextView.isFocused()) return false;
        ...
    }
    
  2. The cursor will not always be visible. The blinking of the cursor is based on the System time - it is visible for half a second, and hidden for the next half a second. The cursor will only be visible if the code I suggested above is called at a point in time when the cursor would be visible according to the System time.

This is why the native keyboard/IME works the way it does. It is a separate Window that allows the EditText to maintain focus and have the blinking cursor functionality, while the user is tapping on Views in a different Window (the keyboard/IME).

That being said, there is a workaround for the problems above - make sure to set shouldBlink to false when you no longer need it though, it's a guaranteed memory leak or crash otherwise:

private void blink() {
    if (shouldBlink) {
        editText.setText(editText.getText());
        editText.setPressed(true);
        editText.setSelection(editText.getText().length());

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (shouldBlink) {
                    blink();
                }
            }
        }, 500);
    }
}
Ovidiu
  • 8,204
  • 34
  • 45
  • Thank you so much! That blink() method is the solution for me! – Lev Leontev Jun 28 '18 at 06:55
  • 1
    Kind of works. Unwelcome UI artifacts as the contents of the edit text are constantly redrawn, and when you type, the cursor moves back and forth from the beginning of the text to the end. – Jeffrey Blattman Dec 19 '18 at 21:11
  • This solution works (but in my case later crashes), but a cursor is constantly redrawn. Also it always tries to move to the right end of `EditText`. – CoolMind Mar 06 '19 at 13:35
6

In your layout xml file add the following line in your edit text:

<requestFocus/>

This will place the cursor in your editText widget.

Hope it helps.

Rohit
  • 2,646
  • 6
  • 27
  • 52
keshav kowshik
  • 2,354
  • 4
  • 22
  • 45
  • if i do that then request goes to EditText. but accrding to my requirment focus should be on KeyBoard View (GridView) and cursor should blink in edit text. – nitin tyagi May 20 '15 at 10:32
  • What do you exactly mean by focus? – keshav kowshik May 20 '15 at 10:34
  • actually i am working on Smart TV application , on which we can move focus from one view to another through remote left , right , up and down button. in my xml there is GridView (9x9 - keyboard which is use for typing in edittext) and an edittext. then when i click on grid then letter shuld type inside edittext and cursor should also blink. – nitin tyagi May 20 '15 at 10:42
5

simply add

editText.requestFocus();

Euler Tiago
  • 134
  • 2
  • 4
2

There is a couple of ways doing it:

1) XML

android:cursorVisible="true"

2) Java

mEditText.setOnClickListener(editTextClickListener);
OnClickListener editTextClickListener = new OnClickListener() {

    public void onClick(View v) {
        if (v.getId() == mEditText.getId()) {
            mEditText.setCursorVisible(true);
        }
    }
};

or

if (mEditText.hasFocus()){
    mEditText.setCursorVisible(true);
}
Ram Koti
  • 2,203
  • 7
  • 26
  • 36
James King
  • 2,425
  • 7
  • 30
  • 45
  • .first i already tried setCursorVisible in xml but no works. and second thing my focus not goes to edit text. please see attached image. focus is always on keyboard. – nitin tyagi May 20 '15 at 13:31
2

I know this is necro, but this was much better than the solutions above. Just extend EditText and add:

  @Override
  public boolean isCursorVisible() {
    return true;
  }

  @Override
  public boolean isFocused() {
    return true;
  }

And in your XML:

  <com.foo.MyEditText
    ...
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:clickable="false"
    android:cursorVisible="true"/>

Now the EditText thinks it is focused and the cursor is visible, but it actually can't be focused.

Jeffrey Blattman
  • 22,176
  • 9
  • 79
  • 134
  • Strange solution. Probably works, I don't know, but on Samsung Galaxy S4 cursor blinks and not visible when EditText is empty. Also Backspace doesn't work. – CoolMind Mar 07 '19 at 14:09
2
    private void setFocusCursor(){
  mBinding.replyConversationsFooter.footerEditText.setFocusable(true);
  `mBinding.replyConversationsFooter.footerEditText.setFocusableInTouchMode(true);`
 `mBinding.replyConversationsFooter.footerEditText.requestFocus();` 
    }

Just call this function in oncreateView() and there you go. We can only set one and only focus on a window.So doing this will help you solve your problem.

1

You can use the following code in your Activity:

//Get the EditText using
EditText et = (EditText)findViewById(R.id.editText); 

//Set setCursorVisible to true
et.setCursorVisible(true);
Chaosit
  • 1,116
  • 7
  • 21
Rohit Sharma
  • 2,017
  • 1
  • 20
  • 22
1
You can explicitly put caret to last position in text:
            int pos = editText.getText().length();
            editText.setSelection(pos);

This will always focus on first character on edittext.

             android:focusable="true"
jessica
  • 1,700
  • 1
  • 11
  • 17
0

Tested on API 27, 28 emulator.

Remove a background attribute, add focusable:

<EditText
    ...
    android:focusable="true"
    android:focusableInTouchMode="true"
    />

In code write: edit.requestFocus(); Though an underline will be visible.

In order to remove an underline, see https://stackoverflow.com/a/52052087/2914140:

edit.getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.white), PorterDuff.Mode.SRC_ATOP);

To change a color of the cursor see https://stackoverflow.com/a/49462015/2914140:

add android:textCursorDrawable="@drawable/shape_cursor", while shape_cursor is:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size
        android:width="1dp"
        android:height="25dp"
        />
    <solid android:color="@color/gray" />
</shape>

It works on API 27, 28 emulator, but on a real device (API 21) cursor disappears. I tried many variants from here and there, but nothing helped.

Then I noticed that when EditText contains at least one symbol, it shows cursor. I added a TextWatcher to add a space when nothing entered.

private lateinit var someText: String

...
edit.requestFocus()
edit.setText(" ")
edit.addTextChangedListener(YourTextWatcher())


private inner class YourTextWatcher : TextWatcher {

    override fun afterTextChanged(s: Editable?) {
        someText = s.toString().trim()
        if (someText.isEmpty()) {
            // To not fall into infinite loop.
            if (s?.length != 1) {
                edit.setText(" ")
            }
        } else {
        }
    }

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}

Also you can add paddings in order to tap inside EditText, if it is small.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
0

I did like this:

var msgEditText = dialog.findViewById(R.id.msg1textView) as EditText

msgEditText.isActivated = true
msgEditText.isPressed = true
msgEditText.requestFocus()
msgEditText.setSelection(view.getText().length)
Michel Fernandes
  • 1,187
  • 9
  • 8