EditText,又稱輸入窗格、輸入框、輸入視窗等等等
哎呦隨便怎麼叫啦,阿不就長那樣(╯=▃=)╯︵┻━┻
也因此就是因為常見,所以花招也特別多
像這樣
還有這樣
等等等等...一大堆
好,然後這些都還是只有Icon在旁邊的
還有這種
真是令人崩潰QQ
尤其每次被設計師出題的時候,我真的很想講
然後...然後
我就做到了(笑)←唉..人生在世不就是為了那點錢😒😒😒
這大概是我對EditText的感想XD
講了這麼多,我每次都實在佩服使用者出的難題
果然人多必有白癡狀元
那麼今天的重點很簡單,就是要來講述那些年我做過的Edittext...的一部分( ´_ゝ`)
畢竟太多了...我不太可能一篇寫完XDD
上功能吧
以及Github
https://github.com/thumbb13555/EditTextWithFunction
首先來聊聊今天的結構
如圖:
Java檔案內會看到有三個類別,分別是
MainActivity
ClearEditText
PasswordEditText
Main當然不用說,而另外兩個其實就分別代表是旁邊帶有叉叉的輸入框及帶有按鈕的輸入框
而我所有的圖片檔案都是XML檔案類型,所以建議可以先建立同名檔案,然後下面我都會給你XML檔案的程式內容
回到正題,ClearEditText及PasswordEditText也可以先建立著,等等再補入內容
了解後,開始(・ω・)b
這編要給你需要的圖片及動畫
先載入動畫好了!
再加入動畫前,需要建立一個anim的資料夾
很簡單
res資料夾上右鍵->New->Directory->輸入anim->完成
來載入檔案吧!
動畫:
<?xml version="1.0" encoding="utf-8"?> <cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="7" />
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromXDelta="0" android:interpolator="@anim/cycle_7" android:toXDelta="10" />
這兩個檔案是相輔相成的,所以一個都不能少喔!( ゚Д゚)b
圖片:
ic_baseline_account_circle_24.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/> </vector>
ic_baseline_remove_red_eye_24.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/> </vector>
<vector android:height="24dp" android:tint="#595959" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#FF000000" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/>
<vector android:height="24dp" android:tint="#FF0000" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/> </vector>
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="25dp"/> <stroke android:width="2dp" android:color="@android:color/holo_blue_dark" /> <solid android:color="@android:color/transparent"/> <padding android:left="20dp" android:right="20dp" /> <size android:height="50dp" android:width="100dp" /> </shape>
基本上就是這些了
大部分的圖片都是抓Android Studio內原生的
雖然提供的不特別多,但是我還蠻常用的XD
那麼在這邊先PO一下MainActivity.java跟activity_main.xml的全部,方便後續的理解
public class MainActivity extends AppCompatActivity { Boolean isOpen = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /**設置旁邊有X的EditText*/ ClearEditText(); /**設置旁邊有眼睛圖樣的EditText*/ passwordIsHideEditText(); /**設置錯誤提示之EditText*/ setErrorEditText(); } private void ClearEditText() { ClearEditText edCancelEdit = findViewById(R.id.editText_CancelEditText); /**設置點擊後右方Icon要做的事*/ edCancelEdit.onItemClick(new ClearEditText.OnEditTextRightButtonFunction() { @Override public void onItemClick(ClearEditText clearEditText) { clearEditText.setText(""); } }); } private void passwordIsHideEditText() { PasswordEditText edPasswordSwitchEdit = findViewById(R.id.editText_PasswordDisplay); /**想在程式中設定ICON*/ edPasswordSwitchEdit.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_baseline_account_circle_24, 0, R.drawable.ic_baseline_remove_red_eye_24, 0); /**設置點擊後右方Icon要做的事*/ edPasswordSwitchEdit.onItemClick(new PasswordEditText.PasswordEditTextChange() { @Override public void onItemClick(PasswordEditText passwordEditText) { if (isOpen) { isOpen = false; /**設置為輸入顯示狀態*/ passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); } else { isOpen = true; /**設置為輸入隱藏狀態*/ passwordEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } } }); } private void setErrorEditText() { EditText edError = findViewById(R.id.editText_Error); /**設置按鈕觸發*/ findViewById(R.id.button_TriggerError).setOnClickListener(v -> { /**設置使背景色變為紅色*/ edError.getBackground().setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP); /**設置動畫使EditText晃動*/ Animation animation = AnimationUtils.loadAnimation(this, R.anim.shake); edError.startAnimation(animation); /**設置錯誤觸發時會出現的Icon*/ Drawable drawable = getResources().getDrawable(R.drawable.ic_info_black_24dp); drawable.setBounds(0, 0, 70, 70); /**設置Error時出現的錯誤訊息提示與ICON*/ edError.setError("莫須有", drawable); /**清除此EditText的焦點*/ edError.clearFocus(); }); /**設置取得焦點後要做的事情*/ edError.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { edError.getBackground() .setColorFilter( getResources().getColor(R.color.colorAccent) , PorterDuff.Mode.SRC_ATOP); } else { edError.getBackground() .setColorFilter( Color.BLACK , PorterDuff.Mode.SRC_ATOP); } } }); }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.33" /> <com.jetec.edittextwithfunction.ClearEditText android:id="@+id/editText_CancelEditText" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="24dp" android:layout_marginEnd="24dp" android:background="@drawable/round_edittext_bg" android:drawableLeft="@drawable/ic_baseline_account_circle_24" android:drawablePadding="5dp" android:ems="10" android:hint="隨意輸入吧" app:layout_constraintBottom_toTopOf="@+id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintGuide_percent="0.66" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:text="旁邊有叉叉符號的Edittext" android:textColor="@android:color/background_dark" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:text='旁邊有"顯示密碼"的Edittext' android:textColor="@android:color/background_dark" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline" /> <com.jetec.edittextwithfunction.PasswordEditText android:id="@+id/editText_PasswordDisplay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="24dp" android:layout_marginEnd="24dp" android:background="@drawable/round_edittext_bg" android:drawableLeft="@drawable/ic_baseline_account_circle_24" android:drawablePadding="5dp" android:ems="10" android:hint="隨意輸入吧" android:inputType="textPassword" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline" app:layout_constraintVertical_bias="0.513" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:text="輸入錯誤時會有提示的Edittext" android:textColor="@android:color/background_dark" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" /> <EditText android:id="@+id/editText_Error" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="隨便輸入吧" android:inputType="textPersonName" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" /> <Button android:id="@+id/button_TriggerError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="觸發錯誤" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editText_Error" /> </androidx.constraintlayout.widget.ConstraintLayout>
搞定完圖片後,先來寫帶有顯示/隱藏按鈕的EditText吧
雖然按照順序...感覺應該是帶叉叉的EditText先,那為何事先第二個?
是因為難度啦(;・∀・)
今天的內容其實就是繼承原生的EditText套件後再去複寫他部分的方法而已
考量到有些人對於EditText能使用的方法並不是太熟悉齁
所以先講簡單的,ㄏ
我直接先上PasswordEditText.java的全部
public class PasswordEditText extends AppCompatEditText { public PasswordEditTextChange onEditTextRightButtonFunction; /**若xml有使用Icon,則優先使用之*/ private Drawable rightIcon = getCompoundDrawables()[2]; public PasswordEditText(Context context) { super(context); init(); } public PasswordEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /**將點擊事件傳至外部*/ public void onItemClick(PasswordEditTextChange onEditTextRightButtonFunction) { this.onEditTextRightButtonFunction = onEditTextRightButtonFunction; } private void init() { /**設置Icon圖片,沒有的話則補圖*/ if (rightIcon == null) { rightIcon = getResources().getDrawable(R.drawable.ic_cancel_black_24dp); } /**設置Icon有效範圍*/ rightIcon.setBounds(0, 0, rightIcon.getIntrinsicWidth(), rightIcon.getIntrinsicHeight()); } @Override public boolean onTouchEvent(MotionEvent event) { /**此處重點是設置EditText內點擊有效之範圍*/ if (event.getAction() == MotionEvent.ACTION_UP) { /**有效範圍起算點*/ int start = getWidth() - getTotalPaddingRight() + getPaddingRight() - 100; /**有效範圍終點*/ int end = getWidth(); /**如果使用者有點擊在有效範圍內,則Do something*/ Boolean available = (event.getX() > start) && (event.getX() < end); if (available) { onEditTextRightButtonFunction.onItemClick(this); } } return super.onTouchEvent(event); } /**設置Interface,將類別內的元件使用權限傳至Activity*/ interface PasswordEditTextChange { void onItemClick(PasswordEditText passwordEditText); } }
首先,粉紅底的Public一定要加
首先,粉紅底的Public一定要加
首先,粉紅底的Public一定要加
非常重要!不然之後XML介面會找不到應該要找的東西喔(・ωー)~☆
此處重點有二,一個是init的內容,另一個是複寫onTouchEvent()的內容
init的內容就如同註解寫的,主要是撰寫關於圖片的顯示
另一個onTouchEvent()主要是撰寫點到icon範圍時要做的事情
onTouchEvent()本身就是一個複寫於使用者點擊螢幕所造成的反饋
而只要使碰觸有效範圍被碰觸到,則行使使用者所撰寫之行為
而我在最後寫的InterFace中將此元件的控制權交出去給Activity,使他能夠在外部被控制
再來來到activity_main.xml
<com.jetec.edittextwithfunction.PasswordEditText android:id="@+id/editText_PasswordDisplay" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="24dp" android:layout_marginEnd="24dp" android:background="@drawable/round_edittext_bg" android:drawableLeft="@drawable/ic_baseline_account_circle_24" android:drawablePadding="5dp" android:ems="10" android:hint="隨意輸入吧" android:inputType="textPassword" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline" app:layout_constraintVertical_bias="0.513" />
就可以像這個樣子使用元件囉!
最後,來到MainActivity.java的onCreate內加入以下程式
private void passwordIsHideEditText() { PasswordEditText edPasswordSwitchEdit = findViewById(R.id.editText_PasswordDisplay); /**想在程式中設定ICON*/ edPasswordSwitchEdit.setCompoundDrawablesWithIntrinsicBounds( R.drawable.ic_baseline_account_circle_24, 0, R.drawable.ic_baseline_remove_red_eye_24, 0); /**設置點擊後右方Icon要做的事*/ edPasswordSwitchEdit.onItemClick(new PasswordEditText.PasswordEditTextChange() { @Override public void onItemClick(PasswordEditText passwordEditText) { if (isOpen) { isOpen = false; /**設置為輸入顯示狀態*/ passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); } else { isOpen = true; /**設置為輸入隱藏狀態*/ passwordEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } } }); }
就能夠執行了
再來是打叉叉的部分
這個部分對應的類別是ClearEditText.java
先PO全部
public class ClearEditText extends AppCompatEditText implements TextWatcher, View.OnFocusChangeListener { public OnEditTextRightButtonFunction onEditTextRightButtonFunction; private Drawable rightIcon = getCompoundDrawables()[2]; public ClearEditText(Context context) { super(context); init(); } public ClearEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public void onItemClick(OnEditTextRightButtonFunction onEditTextRightButtonFunction) { this.onEditTextRightButtonFunction = onEditTextRightButtonFunction; } private void init() { if (rightIcon == null) { rightIcon = getResources().getDrawable(R.drawable.ic_cancel_black_24dp); } rightIcon.setBounds(0, 0, rightIcon.getIntrinsicWidth(), rightIcon.getIntrinsicHeight()); /**初始不顯示ICON*/ setDrawVisible(false); /**設置取得焦點事件*/ setOnFocusChangeListener(this); /**設置監測輸入事件*/ addTextChangedListener(this); } /**設置ICON顯示與消失*/ private void setDrawVisible(Boolean visible) { Drawable right = null; if (visible) right = rightIcon; setCompoundDrawables( getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3] ); } /**如果使用者有輸入的話則顯示ICON*/ @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (hasFocus()) setDrawVisible(s.length() != 0); } /**如果使用者有輸入且取得焦點,則顯示;否則不顯示*/ @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus && getText().length() != 0) setDrawVisible(true); else setDrawVisible(false); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { int start = getWidth() - getTotalPaddingRight() + getPaddingRight() - 100; int end = getWidth(); Boolean available = (event.getX() > start) && (event.getX() < end); if (available) { onEditTextRightButtonFunction.onItemClick(this); } } return super.onTouchEvent(event); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } interface OnEditTextRightButtonFunction{ void onItemClick(ClearEditText clearEditText); } }
這邊繼承了TextWatcher跟View.OnFocusChangeListener這兩個方法
其中的TextWatcher在這篇我有聊過,可以參考
->碼農日常-『Android studio』EditText即時監控輸入與限制輸入(TextWatcher)
而OnFocusChangeListener則是可以偵測該EditText是否有被點擊到
剩下的就如同註解了
一樣,public要記得寫喔:D
再來一樣的套路
寫介面
<com.jetec.edittextwithfunction.ClearEditText android:id="@+id/editText_CancelEditText" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="24dp" android:layout_marginEnd="24dp" android:background="@drawable/round_edittext_bg" android:drawableLeft="@drawable/ic_baseline_account_circle_24" android:drawablePadding="5dp" android:ems="10" android:hint="隨意輸入吧" app:layout_constraintBottom_toTopOf="@+id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" />
以及程式
private void ClearEditText() { ClearEditText edCancelEdit = findViewById(R.id.editText_CancelEditText); /**設置點擊後右方Icon要做的事*/ edCancelEdit.onItemClick(new ClearEditText.OnEditTextRightButtonFunction() { @Override public void onItemClick(ClearEditText clearEditText) { clearEditText.setText(""); } }); }
不知道怎麼寫的,就回去翻一翻吧:)
錯誤提示會像這樣
這部分是原生EditText就有的功能,感覺親近很多了嗎XDDDD
這邊是他的XML設定
<EditText android:id="@+id/editText_Error" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="隨便輸入吧" android:inputType="textPersonName" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" />
以及程式內容
private void setErrorEditText() { EditText edError = findViewById(R.id.editText_Error); /**設置按鈕觸發*/ findViewById(R.id.button_TriggerError).setOnClickListener(v -> { /**設置使背景色變為紅色*/ edError.getBackground().setColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP); /**設置動畫使EditText晃動*/ Animation animation = AnimationUtils.loadAnimation(this, R.anim.shake); edError.startAnimation(animation); /**設置錯誤觸發時會出現的Icon*/ Drawable drawable = getResources().getDrawable(R.drawable.ic_info_black_24dp); drawable.setBounds(0, 0, 70, 70); /**設置Error時出現的錯誤訊息提示與ICON*/ edError.setError("莫須有", drawable); /**清除此EditText的焦點*/ edError.clearFocus(); }); /**設置取得焦點後要做的事情*/ edError.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { edError.getBackground() .setColorFilter( getResources().getColor(R.color.colorAccent) , PorterDuff.Mode.SRC_ATOP); } else { edError.getBackground() .setColorFilter( Color.BLACK , PorterDuff.Mode.SRC_ATOP); } } }); }
別看我寫得一派輕鬆,背後真的也花了不少時間找資料( ゜ρ゜)ノ
有些部分我是寫在註解裡頭,沒有拿出來說
不過像是元件震動效果,以及部分畫面細節
就留給各位調整囉:D
此外像是這行
edError.getBackground() .setColorFilter( Color.BLACK , PorterDuff.Mode.SRC_ATOP);
是可以動態調整EditText背景色的
把原本的圖片及這個混用的話,可以做出意想不到的效果喔!
那今天文章到這,有問題歡迎發Mail~