关于android:当焦点不在EditText上时,在EditText中显示Cursor

Showing Cursor inside EditText when focus is not on EditText

Image of a grid-like layout

我正在开发Android智能电视应用程序:

  • view中有一个自定义键盘和一个EditText

  • 应用程序启动时焦点转到键盘。

    期望:

    • 当用户键入键盘(用遥控器单击)时,光标也应在EditText内闪烁。

如何在EditText中显示此效果?


如果为该字段设置背景,则会发生这种情况。如果要解决此问题,请将cursorDrawable设置为@null

您应该使用cursorVisible添加textCursorDrawable

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

1
2
android:cursorVisible="true"
android:textCursorDrawable="@null"


你可以这样做。我希望/我认为你有一个你已经创建的按钮的布局,你可以为这个布局设置一个焦点监听器,在onFocusChange方法中你可以检查是否(layout.hasFocus())和做这个...

例如,如果你的edittext被命名为et,你可以将其设置为:

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

我有一个小例子代码,你有两个编辑文本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 et2.setOnFocusChangeListener(new OnFocusChangeListener() {

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

            if(et2.hasFocus()){

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

            }
        }
    });

希望这可以帮助...


你可以尝试这样的事情:

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

但是,这种方法存在两个问题:

  • 光标不会闪烁。闪烁的逻辑在Editor类中,不能被覆盖。它要求EditText是聚焦的,并且在一个窗口中只能一次聚焦一个View - 在你的情况下它将是一个键盘按钮。

    1
    2
    3
    4
    5
    6
    7
    /**
     * @return True when the TextView isFocused and has a valid zero-length selection (cursor).
     */
    private boolean shouldBlink() {
        if (!isCursorVisible() || !mTextView.isFocused()) return false;
        ...
    }
  • 光标不会始终可见。光标的闪烁基于系统时间 - 它可见半秒钟,并在下半秒钟内隐藏。只有在根据系统时间光标可见的时间点调用上面建议的代码时,才能看到光标。
  • 这就是本机键盘/ IME以其工作方式工作的原因。它是一个单独的窗口,允许EditText保持焦点并具有闪烁的光标功能,同时用户在另一个窗口(键盘/ IME)中点击视图。

    话虽如此,上面的问题有一个解决方法 - 确保在不再需要时将shouldBlink设置为false,但这是一个保证内存泄漏或崩溃的情况:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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);
        }
    }


    有几种方法可以做到:

    1)XML

    1
    android:cursorVisible="true"

    2)Java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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);
    }


    在布局xml文件中,在编辑文本中添加以下行:

    1
    <requestFocus/>

    这会将光标放在editText小部件中。

    希望能帮助到你。


    1
    2
    3
    4
    5
        private void setFocusCursor(){
      mBinding.replyConversationsFooter.footerEditText.setFocusable(true);
      `mBinding.replyConversationsFooter.footerEditText.setFocusableInTouchMode(true);`
     `mBinding.replyConversationsFooter.footerEditText.requestFocus();`
        }

    只需在oncreateView()中调用此函数即可。
    我们只能设置一个并且只关注一个窗口。这样做可以帮助您解决问题。


    我知道这是坏死的,但这比上面的解决方案要好得多。只需扩展EditText并添加:

    1
    2
    3
    4
    5
    6
    7
    8
    9
      @Override
      public boolean isCursorVisible() {
        return true;
      }

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

    在您的XML中:

    1
    2
    3
    4
    5
    6
      <com.foo.MyEditText
        ...
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        android:cursorVisible="true"/>

    现在EditText认为它是聚焦的并且光标是可见的,但它实际上无法聚焦。


    1
    You can explicitly put caret to last position in text:
    1
    2
                int pos = editText.getText().length();
                editText.setSelection(pos);

    This will always focus on first character on edittext.

    1
                 android:focusable="true"

    您可以在Activity中使用以下代码:

    1
    2
    3
    4
    5
    //Get the EditText using
    EditText et = (EditText)findViewById(R.id.editText);

    //Set setCursorVisible to true
    et.setCursorVisible(true);


    在API 27,28仿真器上测试。

    删除background属性,添加focusable

    1
    2
    3
    4
    5
    <EditText
        ...
        android:focusable="true"
        android:focusableInTouchMode="true"
        />

    在代码中写:edit.requestFocus();虽然可以看到下划线。

    要删除下划线,请参阅https://stackoverflow.com/a/52052087/2914140:

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

    要更改光标的颜色,请参阅https://stackoverflow.com/a/49462015/2914140:

    添加android:textCursorDrawable="@drawable/shape_cursor",而shape_cursor是:

    1
    2
    3
    4
    5
    6
    7
    8
    <?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>

    它适用于API 27,28仿真器,但在真实设备(API 21)上,光标消失。我从这里到那里尝试了很多变种,但没有任何帮助。

    然后我注意到当EditText包含至少一个符号时,它显示光标。当没有输入时,我添加了TextWatcher来添加空格。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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) {}
    }

    此外,您可以添加填充以便在EditText内轻敲,如果它很小。