本文為菜鳥窩作者劉婷的連載?!鄙坛琼椖繉崙?zhàn)”系列來聊聊仿”京東淘寶的購物商城”如何實現(xiàn)。
類似于淘寶、京東等購物商城平臺需要用戶模塊一樣,商城項目也需要注冊登錄等與用戶相關(guān)的模塊,而在實現(xiàn)登錄模塊的時候,界面的效果都差不多,無非是輸入用戶信息,手機號、密碼等,然后進行登錄操作,下面是商城項目的登錄界面效果。

上圖是菜鳥商城項目中登錄效果頁面,其中的輸入文本框帶有清除的功能,而帶清楚功能的 EditText 因為它給用戶的便利性以及用戶體驗的良好而在很多的項目實際中都有應(yīng)用,本文的重點也就是要實現(xiàn)自定義的帶清除功能的 EditText。
實現(xiàn)自定義帶清除功能的 EditText
按照上文中的效果圖來一步步實現(xiàn)自定義帶清除功能的 EditText。
1. 新建自定義控件
新建 class 文件,命名為 ClearEditText,讓它繼承于最新一代的 AppCompatEditText,同時文本框會根據(jù)輸入的內(nèi)容來變化后面的刪除內(nèi)容的圖標(biāo)的顯示或者是隱藏,自然要對 EditText 的一些事件進行實現(xiàn)。
public class ClearEditText extends AppCompatEditText implements View.OnTouchListener, View.OnFocusChangeListener, TextWatcher {
public ClearEditText(final Context context) {
super(context);
}
public ClearEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public ClearEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//具體實現(xiàn)
}
新建好了自定義的控件,然后開始為其實現(xiàn)功能。
2. 初始化刪除按鈕
刪除按鈕的樣式可以自己定義,使用什么樣的圖標(biāo)自己隨意了,這都不重要的,重要的是要按照自己的想法初始化好刪除按鈕的樣式以及隱藏顯示的狀態(tài)。
final Drawable drawable = ContextCompat.getDrawable(context, R.mipmap.icon_delete);
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable); //Wrap the drawable so that it can be tinted pre Lollipop
DrawableCompat.setTint(wrappedDrawable, getCurrentHintTextColor());
mClearTextIcon = wrappedDrawable;
mClearTextIcon.setBounds(0, 0, mClearTextIcon.getIntrinsicHeight(), mClearTextIcon.getIntrinsicHeight());
setClearIconVisible(false);
其中的 setClearIconVisible(final boolean visible) 方法是用來控制刪除按鈕的顯示和隱藏,初始狀態(tài)下,刪除按鈕是不顯示的,所以設(shè)置為了 false。
private void setClearIconVisible(final boolean visible) {
mClearTextIcon.setVisible(visible, false);
final Drawable[] compoundDrawables = getCompoundDrawables();
setCompoundDrawables(
compoundDrawables[0],
compoundDrawables[1],
visible ? mClearTextIcon : null,
compoundDrawables[3]);
}
根據(jù)傳入的 boolean 類型的參數(shù)來控制刪除圖標(biāo)的顯示和隱藏。
3. 焦點變化的處理
EditText 控件輸入文本之前需要先獲取到焦點,獲取到焦點之后,就可以輸入文本,而當(dāng)輸入的文本長度大于0時,也就是有文本輸入時,刪除按鈕就要處于顯示的狀態(tài),否則就是要隱藏起來。
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
if (mOnFocusChangeListener != null) {
mOnFocusChangeListener.onFocusChange(v, hasFocus);
}
}
獲取焦點是第一步,下面還要對文本的變化監(jiān)聽進行實現(xiàn)。
4. 實現(xiàn)文本改變監(jiān)聽事件
輸入框內(nèi)文本改變時,刪除按鈕的狀態(tài)也要隨之變化。
@Override
public final void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
if (isFocused()) {
setClearIconVisible(text.length() > 0);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
要先判斷下是否獲取到了焦點,獲取到焦點后,然后再處理刪除按鈕的狀態(tài)變化。
5. 實現(xiàn)清除功能
刪除按鈕和 EditText 是一體的,這里需要通過實現(xiàn)觸摸事件的監(jiān)聽來實現(xiàn)刪除按鈕的清除功能。
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
final int x = (int) motionEvent.getX();
if (mClearTextIcon.isVisible() && x > getWidth() - getPaddingRight() - mClearTextIcon.getIntrinsicWidth()) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
setError(null);
setText("");
}
return true;
}
return mOnTouchListener != null && mOnTouchListener.onTouch(view, motionEvent);
}
當(dāng)刪除按鈕處于顯示狀態(tài),并且手勢觸摸的位置是刪除按鈕的位置,并且手勢抬起時,設(shè)置 EditText 的內(nèi)容為空,也就是清除了輸入框中的文本內(nèi)容。
登錄界面使用 ClearEditText
ClearEditText 也就是上文中自定義的帶清除功能的 EditText,現(xiàn)在要把它實際運用到登錄界面中,使用方法很簡單,只要把 ClearEditText添加到登錄界面布局文件中就可以了。
<com.liuting.cniao_shop.widget.ClearEditText
android:id="@+id/login_edt_pwd"
style="@style/editText_base"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@mipmap/icon_lock"
android:drawablePadding="20dp"
android:hint="@string/please_input_password"
android:inputType="textPassword" />
這里是使用 ClearEditText 來顯示上文圖中的密碼輸入框,左側(cè)是密碼圖標(biāo),提示為“請輸入密碼”,而輸入的文本樣式是“textPassword”,也就是密碼格式,同樣的道理,也可以實現(xiàn)手機號輸入框,這里就不多寫了。
最終效果圖
登錄界面很簡單了,使用上面的 ClearEditText 展示手機號和密碼輸入框,加上一個登錄按鈕 Button 以及“注冊”和“忘記密碼”的 TextView 文本,這么簡單的布局設(shè)計不用多展示了,這里把登錄界面完善,然后在 Activity/Fragment 進行加載,運行代碼獲取效果圖。

自定義的帶清除功能的 EditText 就這樣實現(xiàn)了,具體的樣式可以按照自己的想法進行調(diào)整。