nitin tyagi
nitin tyagi

Reputation: 466

Showing Cursor inside EditText when focus is not on EditText

Image of a grid-like layout

I am working on Android Smart TV application:

How can I show this effect inside the EditText?

Upvotes: 28

Views: 46812

Answers (12)

Michel Fernandes
Michel Fernandes

Reputation: 1275

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)

Upvotes: 0

DJphy
DJphy

Reputation: 1302

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

            }
        }
    });

Upvotes: 7

Euler Tiago
Euler Tiago

Reputation: 154

simply add

editText.requestFocus();

Upvotes: 6

CoolMind
CoolMind

Reputation: 28845

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.

Upvotes: 0

Maddy_Rockstar
Maddy_Rockstar

Reputation: 39

    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.

Upvotes: 2

Jeffrey Blattman
Jeffrey Blattman

Reputation: 22647

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.

Upvotes: 2

Ovidiu
Ovidiu

Reputation: 8714

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

Upvotes: 8

IntelliJ Amiya
IntelliJ Amiya

Reputation: 75798

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"

Upvotes: 15

James King
James King

Reputation: 2445

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

Upvotes: 2

Jaspreet Kaur
Jaspreet Kaur

Reputation: 1720

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"

Upvotes: 1

Rohit Sharma
Rohit Sharma

Reputation: 2017

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

Upvotes: 1

keshav kowshik
keshav kowshik

Reputation: 2374

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.

Upvotes: 6

Related Questions