当焦点不在EditText上时,在EditText内显示光标

28

网格状布局的图像

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

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

  • 当应用程序启动时,焦点会移到键盘上。

    期望的:

    • 当用户使用键盘 (通过遥控器点击) 输入时,光标也应该闪烁在 editText 内部。

如何在 EditText 内显示这个效果?


请发布一些您目前尝试过的代码。 - keshav kowshik
@Keshav1234 到目前为止,我已经制作了一个布局,其中包含自定义键盘和编辑框。并手动将焦点设置在键盘上。当焦点转移到编辑文本时,光标是可见的。但我的要求是,光标应始终在编辑文本中闪烁。 - nitin tyagi
我应该改变我的方法吗?请给予建议。 - nitin tyagi
我在想,IME API 在 Android TV 上是否可用?如果是,为什么不用这种方式实现自定义键盘呢? - artkoenig
12个回答

14

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

您应该添加textCursorDrawablecursorVisible

引用将在插入光标下绘制的可绘制对象。

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

刚在API 27模拟器上测试了一下,光标被隐藏了,直到移除android:background="@color/transparent" - CoolMind

7
你可以尝试这样做:

您可以尝试以下方法:

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

然而,这种方法存在两个问题:
  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.
这就是本地键盘/输入法的工作方式。它是一个单独的窗口,允许EditText保持焦点并具有闪烁的光标功能,同时用户在不同的窗口(键盘/输入法)中点击视图。
话虽如此,上述问题有一个解决方法——确保在不再需要时将shouldBlink设置为false,否则会出现内存泄漏或崩溃的问题。
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);
    }
}

非常感谢!blink() 方法对我来说是解决方案! - Lev Leontev
1
有点能用。不过UI上出现了一些不受欢迎的瑕疵,因为编辑文本的内容不断被重绘,当你输入时,光标会来回移动,从文本的开头到结尾。 - Jeffrey Blattman
这个解决方案有效(但在我的情况下会崩溃),但是光标一直在重绘。并且它总是试图移动到EditText的右端。 - CoolMind

7

您可以这样做...我希望/认为您已经创建了按钮的布局,通过这个布局,您可以为其设置一个焦点监听器,在onFocusChange方法中,您可以检查if(layout.hasFocus())并执行以下操作...

例如,如果您的editText命名为et,则可以将其设置为:

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

我为您准备了一个小示例代码,其中有两个编辑框。

 et2.setOnFocusChangeListener(new OnFocusChangeListener() {

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

            if(et2.hasFocus()){

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

            }
        }
    });

感谢您的回答。通过您的代码,我可以看到光标。但是光标位置是固定的。要求是当我点击按钮时,光标应该移动到编辑框内部。 - nitin tyagi

6
在你的布局xml文件中,在你的EditText中添加以下行:
<requestFocus/>

这将把光标放置在您的editText小部件中。 希望对您有所帮助。

如果我这样做,那么请求会发送到EditText。但是根据我的要求,焦点应该在键盘视图(GridView)上,并且光标应该在编辑文本中闪烁。 - nitin tyagi
你所说的“focus”具体指什么? - keshav kowshik
实际上,我正在开发智能电视应用程序,可以通过遥控器的左、右、上和下按钮在不同视图之间移动焦点。我的XML文件中有一个GridView(9x9 - 用于在EditText中输入的键盘)和一个EditText。当我点击网格时,字母应该输入到EditText中,并且光标也应该闪烁。 - nitin tyagi

5

simply add

editText.requestFocus();


2
有几种方法可以实现这个:
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);
}

首先,我已经尝试在XML中使用setCursorVisible,但没有效果。其次,我的焦点不会转到编辑文本。请参见附图。焦点始终在键盘上。 - nitin tyagi

2

我知道这是个老帖子,但这个解决方案比上面的方案好多了。只需扩展EditText并添加以下内容:

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

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

在您的XML文件中:

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

现在,EditText认为它已经获得了焦点并且光标是可见的,但实际上它无法获得焦点。

奇怪的解决方案。可能可行,但我不确定,在三星Galaxy S4上,当EditText为空时,光标会闪烁并且不可见。此外,退格键无法正常工作。 - CoolMind

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

只需在oncreateView()中调用此函数,就可以实现这一点。我们只能在一个窗口上设置一个焦点。因此,这样做将有助于解决您的问题。


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

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

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

1
它在我的情况下不起作用。我已经在XML和代码中设置了它,但仍然无法工作。 - nitin tyagi

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

这将始终聚焦于EditText的第一个字符。
             android:focusable="true"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接