Android之输入框光标和Hint的位置

如图所示,要实现这一的需求,通常人的布局方式就是左边一button,右边一button,中间一个EditText,为了输入框的响应触摸范围更大每每不会把宽度设置为wrap_content,要么设置成match_parent/fill_parent要么给定个minWidth+wrap_content。android

不管如何布局,gravity或layout_gravity都应是center才能达到需求所示。然而问题来了,若是gravity设置为了center,很不巧的是大部分手机(笔者某为居然会自动纠正光标与hint的相对位置)实际运行效果是光标会位于hint的中间,要知道gravity会影响到光标所在位置,gravity为Left光标就在最左边,graity为right光标就在Hint的最右边,固然gravity为Center光标天然在hint的中间。ide

借图一张(来自万能的StackOverFlow,惋惜万能的SOF也没给出答案)布局

 

遂左思右想各类弥救方法,主要有3个方案两个角度来解决。完美的角度是把光标位置想法设法调正,退而求其次的方法是显示hint(即输入框没有text)的时候隐藏光标。方案触发点有两个,一个是第一次没有任何text但设置了hint此时,入口应为onFocusChange方法;另外一个是动态输入过程当中清除了text,这个入口在onTextChange。字体

我总结出来有三个对策以下。spa

下策:当须要显示hint的时候把hint设置为空字符串,不须要显示hint的时候再把hint还原成须要设置的字符串。这种方法带来的效果就是,界面一打开能看见hint,当你一点击输入框开始输入就没有hint了,虽然此时光标可见,但仍是有瑕疵,而且在onFocusChange方法里面设置hint会形成要点两次才会弹起输入法(具体缘由还没有深究)。code

中策:当须要显示hint的时候隐藏光标,一旦用户开始输入显示光标。这种效果相似第一种,一打开界面能看见hint,但看不到光标,你要开始输入才能看见。这也是有瑕疵的,当用户点了输入框(得到用户焦点)没有光标用户就会很郁闷不知道可不能够输入,缺少光标的引导做用。blog

上策:那上策就是调整位置咯,其实也不是说能调整光标的位置,而是逆向思惟把输入框的位置改变来适用光标所须要摆在的位置。这种方案实现起来有点复杂,改动量大。首先你EditTextd的宽度不能指定,minWidth不能由输入框来设置而要在它的parent容器设置最小宽度,因此它的width最好是wrap_content,而且设置必定的padding来保留必定用户触摸响应区域。而后EditText的Gravity仍是Center,须要调整的就是它的LayoutGravity了,当用户有输入毫无疑问须要居中,当没有输入须要显示Hint时,那就要设置成Left了,而后计算出须要设置marginLeft距离。这个距离就是EditText(父容器的宽度-hint的宽度)/2,固然要获取LayoutWdth须要必定的技巧,获取hint的宽度更须要一点技巧。这样就能让光标位于hint的前面了,曲线救国吧。字符串

干货来了。get

android要获取宽高常常能拿到0这个值,这个通常有经验的都会在onWindowsFocus里去拿到,而后量字符串的像素,就须要你要用你显示hint的画笔去测量字符串,由于须要知道字体属性,好比字体、大小、粗细等。it

直接上代码咯:

@Override
  public void onWindowFocusChanged(boolean hasWindowFocus) {
   super.onWindowFocusChanged(hasWindowFocus);
        if (mSpaceWidth <= 0) mSpaceWidth = getWidth() - left.getWidth() - right.getWidth();
    }

@Override
public void onFocusChange(View v, boolean hasFocus) {
        adjustCursorPosition(etInput.getText());
    }

@Override
public void afterTextChanged(Editable s) {
        adjustCursorPosition(etInput.getText());
    }

private void adjustCursorPosition(CharSequence text){
        if (!TextUtils.isEmpty(etInput.getHint())){
            adjustGravityForCursor(text);//adjustCursorVisible(text);//adjustHintContent(hasFocus(),text);
        }
    }

    private void adjustGravityForCursor(CharSequence text) {
        LayoutParams lp = (LayoutParams) etInput.getLayoutParams();
        if (mSpaceWidth <= 0) mSpaceWidth = lp.width - left.getWidth() - right.getWidth();
        if (!TextUtils.isEmpty(text)) {
            etInput.setGravity(Gravity.CENTER);
            lp.leftMargin = 0;
        } else {
            etInput.setGravity(Gravity.LEFT);
            lp.leftMargin = (mSpaceWidth - measureText(etInput,mHint)) / 2;
        }
        etInput.setLayoutParams(lp);
    }

    public int measureText(TextView textView, String text) {
        TextPaint paint = textView.getPaint();
        return (int) paint.measureText(text);
    }

    private void adjustCursorVisible(CharSequence text){
        etInput.setCursorVisible(!TextUtils.isEmpty(text));
    }

    private void adjustHintContent(boolean hasFocus, CharSequence text){
        if (TextUtils.isEmpty(text)) {
            etInput.setHint(hasFocus ? "" : mHint);
        }
    }
相关文章
相关标签/搜索