如圖所示,要實現這一的需求,通常人的佈局方式就是左邊一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); } }