解決EditText的gravity設定為right時,在android 7.0之上游標變細
阿新 • • 發佈:2019-02-04
問題闡述:
根據需求,需要設定EditText從後往前輸入,游標預設在輸入文字的末尾,如圖所示:
暴力思路:
這種經常的做法是使用一個TextView覆蓋在EditText來偽裝EditText的提示文字。實際操作時卻發現在android6.0及以下沒有問題,在更高版本中,卻出現游標定位在末尾的時候特別細的情況,顯然是不合格的。網上搜索解決辦法不多,沒辦法,只有自己來了。由於專案中這種輸入形式較多,索性做成自定義組合控制元件統一處理,解決思路:游標顯示異常只出現在高版本,並且是游標在末尾的時候才出現,由於是顯示問題,大可使用障眼法解決,何不讓EditText末尾追加一個空格,另外讓使用者使用時游標定位不到末尾。
解決之道:
佈局很簡單,裡面使用了專案中的樣式,見諒,如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll" style="@style/LLWithPaddingStyle"> <TextView android:id="@+id/tv_title" style="@style/TvLeftWapStyle" /> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.hc360.koiambuyer.widget.SelectionEditText android:id="@+id/et_input" style="@style/TvRightStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="0dp" android:background="@null" android:maxLines="4" android:textCursorDrawable="@drawable/shape_et_cursor" android:gravity="right|center_vertical" android:textColor="@color/tvNormalColor" /> <TextView android:id="@+id/tv_et_hint" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="9dp" android:gravity="right|center_vertical" android:text="@string/personal_data_name_hint" android:textColor="@color/HintColor" /> </FrameLayout> </LinearLayout>
定義一些距離自定義屬性
<declare-styleable name="EditInput"> <attr name="ei_paddingBottom" format="dimension"/> <attr name="ei_paddingTop" format="dimension"/> <attr name="ei_paddingLeft" format="dimension"/> <attr name="ei_paddingRight" format="dimension"/> </declare-styleable>
自定義組合控制元件,註釋已經很明白了,也很簡單,就不多說了
public class EditInput extends LinearLayout { private static final float PADDING_DEFAULT = 20; private static final float PADDING_DEFAULT_LEFT = 15; private static final float ANDROID_SDK_NUM= 24; @BindView(R.id.tv_title) TextView mTvTitle; @BindView(R.id.et_input) SelectionEditText mEtInput; @BindView(R.id.tv_et_hint) TextView mTvEtHint; @BindView(R.id.ll) LinearLayout mLl; public EditInput(Context context) { this(context, null); } public EditInput(Context context, AttributeSet attrs) { this(context, attrs, 0); } public EditInput(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); View.inflate(context, R.layout.layout_et, this); ButterKnife.bind(this); try { //獲取自定義屬性 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView); int paddingBottom = a.getDimensionPixelSize(R.styleable.EditInput_ei_paddingBottom, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, PADDING_DEFAULT, getResources().getDisplayMetrics())); int paddingLeft = a.getDimensionPixelSize(R.styleable.EditInput_ei_paddingLeft, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, PADDING_DEFAULT_LEFT, getResources().getDisplayMetrics())); int paddingRight = a.getDimensionPixelSize(R.styleable.EditInput_ei_paddingRight, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, PADDING_DEFAULT_LEFT, getResources().getDisplayMetrics())); int paddingTop = a.getDimensionPixelSize(R.styleable.EditInput_ei_paddingTop, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, PADDING_DEFAULT, getResources().getDisplayMetrics())); mLl.setPadding(paddingLeft,0,0,0); mEtInput.setPadding(0,paddingTop,paddingRight,paddingBottom); mTvEtHint.setPadding(0,paddingTop,10,paddingBottom); }catch (Exception e){} //當EditText獲取焦點的時候,覆蓋的TextView就消失 mEtInput.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus){ mTvEtHint.setVisibility(GONE); }else { if (!TextUtils.isEmpty(mEtInput.getText().toString().trim())){ mTvEtHint.setVisibility(GONE); }else { mTvEtHint.setVisibility(VISIBLE); } } } }); //android7.0之上執行這段程式碼 if (Build.VERSION.SDK_INT >= ANDROID_SDK_NUM) { //初始是EditText追加空格,游標定位到空格的前面 mEtInput.setText(" "); mEtInput.setSelection(0); //EditText的游標變化監聽,當游標位置到末尾時,強制將游標改為空格的前面 mEtInput.setOnSelectionChange(new SelectionEditText.OnSelectionChange() { @Override public void onSelectionChange(int selStart, int selEnd) { String etText = mEtInput.getText().toString(); if (etText.endsWith(" ")){ if (selStart == mEtInput.getText().toString().length()){ mEtInput.setSelection(mEtInput.getText().toString().length()-1); } } } }); //確保EditText輸入文字在空格的前面,游標在空格的前面 mEtInput.addTextChangedListener(new CustomTextWatcher() { @Override public void afterTextChanged(Editable s) { if (!mEtInput.getText().toString().endsWith(" ")){ mEtInput.setText(s+" "); } if (mEtInput.getSelectionStart() == s.length()){ mEtInput.setSelection(s.length()-1); } } }); } } /** * 初始化標題跟EditText的提示文字 * @param title * @param contentHint */ public void initText(String title,String contentHint){ mTvTitle.setText(title); mTvEtHint.setText(contentHint); } /** * 設定EditText的輸入內容 * @param text */ public void setEtText(String text){ //高版本末尾追加空格,設定游標在空格前 if (!TextUtils.isEmpty(text)){ if (Build.VERSION.SDK_INT >= ANDROID_SDK_NUM) { text = text+" "; mEtInput.setText(text); mEtInput.setSelection(text.length()-1); }else { mEtInput.setText(text); mEtInput.setSelection(text.length()); } mTvEtHint.setVisibility(GONE); }else { if (Build.VERSION.SDK_INT >= ANDROID_SDK_NUM) { mEtInput.setText(" "); mEtInput.setSelection(0); } } } /** * 獲取輸入的文字,記得要trim一下,因為EditText可能設定只能輸入數字型別等等 * @return */ public String getEtText(){ return mEtInput.getText().toString().trim(); } /** * 設定最大輸入文字數 * @param max */ public void setEtMaxNum(int max){ mEtInput.addTextChangedListener(new MaxNumTextWatcher(max, mEtInput)); } /** * 設定輸入格式 * @param type */ public void setEtInputType(int type){ mEtInput.setInputType(type); } }
裡面使用的SelectionEditText其實就是一個EditText,只不過是暴漏了游標變化的監聽
public class SelectionEditText extends EditText {
OnSelectionChange mOnSelectionChange;
public SelectionEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
// TODO Auto-generated method stub
super.onSelectionChanged(selStart, selEnd);
if (mOnSelectionChange !=null){
mOnSelectionChange.onSelectionChange(selStart,selEnd);
}
}
public void setOnSelectionChange(OnSelectionChange onSelectionChange){
mOnSelectionChange = onSelectionChange;
}
public interface OnSelectionChange{
void onSelectionChange(int selStart, int selEnd);
}
}
本文很簡單,只是我在網上沒有搜到相應的解決辦法,想到了這個粗暴的方法,如果大家有更好的方法,不吝賜教