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);
        }
    }
相關文章
相關標籤/搜索