編輯:關於Android編程
最近公司的產品在陸續做升級,上級領導給的任務是優化代碼結構以及項目架構,力爭把項目寫的精巧簡練,於是我們滿工程找冗余...
我們都知道每一個項目基本上都是有登陸頁的,在登陸頁中肯定是少不了輸入框了,當我們在輸入框中輸入數據後如果輸入的內容不正確或者是錯誤的或者是想重新輸入,如果嗯鍵盤上的刪除鍵就得一個一個的去刪除,這時候我們或許就想要是能有一個標記當點擊了這個標記能把我們剛剛輸入的內容清空就好了。這樣可以極大的提升用戶體驗,就拿QQ的登陸來說吧,效果如下:

當點擊密碼框右側的小×圖標時輸入的內容就都清空了,真的很方便,我之前在項目中也自定義過這種效果的輸入框並且在項目中一直使用它,在此期間並沒有發現什麼Bug,之前的自定義結構如下:

實現方式是使用一個RelativeLayout,它包含了三個控件,兩邊是ImageView控件,中間是EditText控件,當點擊右側清除按鈕後就可以清除輸入框的內容了,但是最近在做產品優化的時候感覺之前寫的這個自定義控件在代碼量上來說有點浪費,明明Android的EditText有drawableLeft和drawableRight屬性,為什麼不去直接使用呢?於是用筆在草稿紙上畫了畫,花點時間又重新寫了一個具有同樣效果的輸入框,並且在代碼量上來說簡化了不少。
好了,還是老規矩,先來看看項目結構吧:

工程中ClearEditText就是我又從新定義的帶清除功能的輸入框,主要是繼承了EditText為了利用它的drawableLeft和drawableRight屬性,那麼趕緊看看它的實現吧
public class ClearEditText extends EditText implements TextWatcher,
OnFocusChangeListener {
/**
* 左右兩側圖片資源
*/
private Drawable left, right;
/**
* 是否獲取焦點,默認沒有焦點
*/
private boolean hasFocus = false;
/**
* 手指抬起時的X坐標
*/
private int xUp = 0;
public ClearEditText(Context context) {
this(context, null);
}
public ClearEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
}
public ClearEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWedgits();
}
/**
* 初始化各組件
* @param attrs
* 屬性集
*/
private void initWedgits() {
try {
// 獲取drawableLeft圖片,如果在布局文件中沒有定義drawableLeft屬性,則此值為空
left = getCompoundDrawables()[0];
// 獲取drawableRight圖片,如果在布局文件中沒有定義drawableRight屬性,則此值為空
right = getCompoundDrawables()[2];
initDatas();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化數據
*/
private void initDatas() {
try {
// 第一次顯示,隱藏刪除圖標
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
addListeners();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 添加事件監聽
*/
private void addListeners() {
try {
setOnFocusChangeListener(this);
addTextChangedListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int after) {
if (hasFocus) {
if (TextUtils.isEmpty(s)) {
// 如果為空,則不顯示刪除圖標
setCompoundDrawablesWithIntrinsicBounds(left, null, null, null);
} else {
// 如果非空,則要顯示刪除圖標
if (null == right) {
right = getCompoundDrawables()[2];
}
setCompoundDrawablesWithIntrinsicBounds(left, null, right, null);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
try {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 獲取點擊時手指抬起的X坐標
xUp = (int) event.getX();
// 當點擊的坐標到當前輸入框右側的距離小於等於getCompoundPaddingRight()的距離時,則認為是點擊了刪除圖標
// getCompoundPaddingRight()的說明:Returns the right padding of the view, plus space for the right Drawable if any.
if ((getWidth() - xUp) <= getCompoundPaddingRight()) {
if (!TextUtils.isEmpty(getText().toString())) {
setText("");
}
}
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return super.onTouchEvent(event);
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
try {
this.hasFocus = hasFocus;
} catch (Exception e) {
e.printStackTrace();
}
}
}
解釋一下ClearEditText的執行順序,它首先繼承了EditText也就是說具有了EditText的所有功能,然後又實現了TextWatcher和OnFocusChangeListener接口,其中接口OnFocusChangeListener是用來監聽當前輸入框是否獲取到焦點的,我們把當前輸入框獲取到的焦點的狀態值賦給hasFocus成員變量,如果獲取到了焦點則hasFocus的值為true,當在輸入框中輸入內容的時候會觸發TextWatcher監聽器,就會順序執行beforeTextChanged,onTextChanged和afterTextChanged方法,而我們僅僅需要在onTextChanged方法中對輸入框的值進行判斷就行了,如果輸入框框的值非空就顯示清空按鈕小圖標否則不顯示,設置圖標隱藏和顯示的方法就是直接調用setCompoundDrawablesWithIntrinsicBounds方法就行了,這個方法的具體使用就不詳解了,大體就是說按照我們給定的圖片尺寸把圖片畫到輸入框的四個方向上,如果傳入值為null就表示不繪制。
接下來就是對清空小圖標進行監聽了,我首先想到的是如果清空小圖標是顯示的,就給他設置事件監聽比如onClickListener或者是onTouchListener,但是遺憾的是找了API並沒有發現EditText提供對drawLeft或者是drawRight的事件監聽,又來又打算自定義一個監聽器但仔細想想又把代碼復雜化了,其實EditText是間接繼承View的而View中有個onTouchEvent方法,我們可以重寫onTouchEvent方法並在它裡邊根據我們手指摁下或者是抬起的坐標進行判斷,如果點擊的位置到當前控件右側的距離小於等於當前控件右側小圖標的寬度加上paddingRight的值,則我們可以直接認為是點擊了清除小圖標,就可以對當前控件進行清空操作了,幸好EditText給我們提供了一個我現在認為是非常實在的方法:getCompoundPaddingRight(),文檔的解釋就是:Returns the right padding of the view, plus space for the right Drawable if any.它的值就是清空小圖標的寬度加上paddingRight的值,呵呵,有了它就好辦多了,(*^__^*) 嘻嘻……
好了,接下來我們來看看在布局文件中怎麼使用它吧(其實很簡單,就是和EditText的使用方法一樣的,(*^__^*) 嘻嘻……)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="@string/hello"
android:gravity="center"
android:textSize="20sp"
android:textColor="#000000" />
<com.llew.e.clear.view.wedgit.ClearEditText
android:id="@+id/clearEditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:paddingRight="8dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:hint="請輸入QQ號碼"
android:background="@drawable/pay_widget_input"
android:drawableLeft="@drawable/super_qq"
android:drawableRight="@drawable/clear_normal_list" />
</LinearLayout>
就是寫完整我們自定義的包名就行了,屬性用的全是父類中的,再次感謝Java給我們提供的繼承特性,呵呵,
在運行之前還是貼出來MainActivity代碼吧,其實真的很簡單:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
簡單吧?創建工程的時候自動生成的,壓根不用進行任何操作,呵呵
好了,我們運行一下,看看效果圖吧O(∩_∩)O~
輸入前:

輸入後:

點擊清除圖標後:

呵呵,這種效果和之前自定義的一樣,並且在代碼量上來說卻是比之前的減少了不少,高興一下
好了,今天的自定義ClearEditText就講到這裡,感謝收看。
源碼下載:Android UI實現帶清除功能的輸入框
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
Android基礎學習—下載並在Eclipse中關聯Android源碼
1.下載源碼 這部分網上有大量的資料,我就不重新寫了,這是我參考的文章:《Windows平台下Android源碼的下載》 一般來說,跟著上面文章的講解操作
Android高手進階——Adapter深入理解與優化
Android高手進階——Adapter深入理解與優化 一般是針對包含多個元素的View,如ListView,GridView,ExpandableList
Android通過自定義View實現隨機驗證碼
很多的Android入門程序猿來說對於Android自定義View,可能都是比較恐懼的,但是這又是高手進階的必經之路,所有准備在自定義View上面花一些功夫,多寫一些文章
OkHttp學習(3)--))同步、異步之上傳文件至服務器(重寫RequestBody方法,實現上傳進度接口回調)
此篇博客,我們通過2種方式來了解下okhttp的文件上傳至服務器ps一下,還有一種就是添加params參數,生成post提交時的分塊request(這裡就不列出實例效果了