Android EditText 光标显示在结尾处问题

需求

  1. 进入页面时,EditText不自动获取焦点(没有光标显示)
  2. 第一次点击EditText区域时,光标显示在结尾处,并且出现软键盘
  3. 第二次点击EditText指定位置,光标移动到指定位置,用户进行编辑

代码

  • 布局
<RelativeLayout
    android:focusable="false"
    android:focusableInTouchMode="true">
    
    <EditText android:background="@null" />
    
</RelativeLayout>

效果

  • 实现了 需求:1
  • 第一次点击EditText区域时,键盘显示,但是光标位置是用户点击的位置,不在结尾处,除非用户点击的位置就是结尾处。

问题

  • 如何实现 需求:2
阅读 7.4k
2 个回答

问题已经解决了

这个问题的 关键点setSelection() 方法的执行时机

先说下如何解决

  • 布局中不需要做任何多余的设置
<RelativeLayout
    <!-- 这两个设置不需要了,因为接下来要在程序总设定 -->
    android:focusable="false"
    android:focusableInTouchMode="true" />
    <EditText />
</RelativeLayout>
  • Java代码部分
public class MainActivity extends AppCompatActivity {
    private boolean isFirst = true; // 是否是第一次点击 EditText
    private InputMethodManager mIMM; // 第一次点击时,软键盘不自动弹出,所以要手动弹出
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mIMM = (InputMethodManager) (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        mEditText = findViewById(R.id.xxx);
        
        // 关键部分
        mEditText.setFocusable(false);
        mEditText.setOnClickListener( v -> {
            if(isFirst) {
                mEditText.setFocusableInTouchMode(true);
                mEditText.requestFocus();
                mEditText.setSelection(mEditText.getText().length());
                mIMM.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
                isFirst = false;
            }
        });
    }
}

再说下尝试的过程

1. 直接设置 setSelection()

因为之前设置了 android:focusabelInTouchMode="true",所以直接设置是没有效果的,第一次点击EditText区域,会自动弹出软键盘,并且光标位置是手指点击的位置

2. 自定义 EditText,重写 onSelectionChanged(int selStart, int selEnd)方法

这个方法感知光标位置的变化,编写如下代码,可控制光标始终在结尾处:

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);
            if (selStart == selEnd) { // 不考虑多个文字被选中
                setSelection(getText().length());
            }
    }

这个方法的执行时机在自定义EditText对象初始化之前,并且在没点击之前,或者点击时会多次执行该方法,不好控制是否是第一次点击。因此也没有尝试成功

总结

不知道有没有更好的解决方案?期待你的回答。


2018-05-28 补充

实际项目总可能会遇到一个页面中有多个EditText,那么 isFirstTouch 就可能被多个EditText共用,如果有这个问题存在的话,一种解决方案是自定义EditText:

public class MyEditText extends EditText {
    private boolean isFirstTouch = true;
    // 构造方法中调用 init() 方法
    private void init() {
        post( () -> {
            setFocusable(false);
            if(isFirst) {
                setFocusableInTouchMode(true);
                requestFocus();
                setSelection(mEditText.getText().length());
                inputMethodManger.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
                isFirst = false;
            }
        });
    }
}

EditText有个setSelection方法,应该可以满足你的需求

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题