متریال دیزاین-کار با TextInputLayout
در این دوره از آموزش متریال دیزاین (material design) به مبحث برچسب های شناور (floating labels) میپردازیم. این قابلیت همانند یک اشاره (hint) روی EditText ها وجود دارد و هنگام لمس و کلیک بر روی آن با حالتی متحرک (animating) به بالای EditText رفته و دید بسیار جالبی به برنامه میدهد. استفاده از این عنصر در برنامه میتواند طراحی ما را به سمت اصولی (material) شدن سوق دهد و طرحی جذاب و کاربر پسند را به برنامهی خود اضافه کنیم. میخواهیم با استفاده از عنصر TextInputLayout این ویژگی را به برنامه ی خود اضافه کنیم.
این لایه میتواند در هر جایی از برنامه روی EditText قرار گیرد.(به عنوان لایه ی پدر) ولی به طور معمول برای زمانی استفاده میشود که میخواهیم فرمی را بسازیم (برای مثال فرم login) و نیاز به بررسی صحت ورودی ها داریم (form validation).
این لایه از کتابخانهی design است و برای استفاده باید در قدم اول این کتابخانه را وارد برنامه کنیم.
برای این کار باید کد زیر را داخل فایل build.gradle در قسمت dependencies وارد کرده و پروژه را همگام سازی کنیم(sync)
1 |
'com.android.support:design:23.0.1' |
به این صورت
1 2 3 4 5 |
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:design:23.0.1' } |
بعد از وارد کردن کتابخانه باید مقادیر string هایی که میخواهیم در برنامه استفاده کنیم را در فایل strings.xml در مسیر res ⇒ values قرار دهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<resources> <string name="app_name">Floating EditText</string> <string name="hint_name">Full Name</string> <string name="hint_email">Email</string> <string name="hint_password">Password</string> <string name="btn_sign_up">Sign Up</string> <string name="err_msg_name">Enter your full name</string> <string name="err_msg_email">Enter valid email address</string> <string name="err_msg_password">Enter the password</string> </resources> |
حالا نوبت وارد کردن کد زیر داخل برنامه است. این کد را میتوانیم در هر جای برنامه که خواستیم استفاده کنیم.
1 2 3 4 5 6 7 8 9 10 11 |
<android.support.design.widget.TextInputLayout android:id="@+id/input_layout_password" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_email" /> </android.support.design.widget.TextInputLayout> |
برای نمونه ما فرم زیر را طراحی میکنیم تا کاربرد این لایه برایمان ملموس تر شود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="match_parent" android:layout_marginTop="?attr/actionBarSize" android:orientation="vertical" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="60dp"> <android.support.design.widget.TextInputLayout android:id="@+id/input_layout_name" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_name" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:id="@+id/input_layout_email" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_email" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:hint="@string/hint_email" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:id="@+id/input_layout_password" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="@string/hint_password" /> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/btn_signup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/btn_sign_up" android:background="@color/colorPrimary" android:layout_marginTop="40dp" android:textColor="@android:color/white"/> </LinearLayout> </LinearLayout> |
حال میخواهیم در قسمت جاوا بررسی صحت فرم (form validation) را تکمیل کنیم.
کد زیر را در فایل java.* (برای مثال ActivityMain.java) خود وارد میکنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
package ir.zerotohero.ahmad.floatingedittext; import android.support.design.widget.TextInputLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private EditText inputName, inputEmail, inputPassword; private TextInputLayout inputLayoutName, inputLayoutEmail, inputLayoutPassword; private Button btnSignUp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); inputLayoutName = (TextInputLayout) findViewById(R.id.input_layout_name); inputLayoutEmail = (TextInputLayout) findViewById(R.id.input_layout_email); inputLayoutPassword = (TextInputLayout) findViewById(R.id.input_layout_password); inputName = (EditText) findViewById(R.id.input_name); inputEmail = (EditText) findViewById(R.id.input_email); inputPassword = (EditText) findViewById(R.id.input_password); btnSignUp = (Button) findViewById(R.id.btn_signup); inputName.addTextChangedListener(new MyTextWatcher(inputName)); inputEmail.addTextChangedListener(new MyTextWatcher(inputEmail)); inputPassword.addTextChangedListener(new MyTextWatcher(inputPassword)); btnSignUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { submitForm(); } }); } /** * Validating form */ private void submitForm() { if (!validateName()) { return; } if (!validateEmail()) { return; } if (!validatePassword()) { return; } Toast.makeText(getApplicationContext(), "Thank You!", Toast.LENGTH_SHORT).show(); } private boolean validateName() { if (inputName.getText().toString().trim().isEmpty()) { inputLayoutName.setError(getString(R.string.err_msg_name)); requestFocus(inputName); return false; } else { inputLayoutName.setErrorEnabled(false); } return true; } private boolean validateEmail() { String email = inputEmail.getText().toString().trim(); if (email.isEmpty() || !isValidEmail(email)) { inputLayoutEmail.setError(getString(R.string.err_msg_email)); requestFocus(inputEmail); return false; } else { inputLayoutEmail.setErrorEnabled(false); } return true; } private boolean validatePassword() { if (inputPassword.getText().toString().trim().isEmpty()) { inputLayoutPassword.setError(getString(R.string.err_msg_password)); requestFocus(inputPassword); return false; } else { inputLayoutPassword.setErrorEnabled(false); } return true; } private static boolean isValidEmail(String email) { return !TextUtils.isEmpty(email) && android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches(); } private void requestFocus(View view) { if (view.requestFocus()) { getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); } } private class MyTextWatcher implements TextWatcher { private View view; private MyTextWatcher(View view) { this.view = view; } public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } public void afterTextChanged(Editable editable) { switch (view.getId()) { case R.id.input_name: validateName(); break; case R.id.input_email: validateEmail(); break; case R.id.input_password: validatePassword(); break; } } } } |
در کد بالا ما متد هایی برای بررسی صحت ورودی های کاربر از قبیل نام و ایمیل و رمز عبور نوشته ایم. این متد ها را به TextWatcher متصل کردیم که هنگام تایپ ورودی بررسی های انجام شود(داخل متد afterTextChanged) و وضعیت ورودی ها به صورت لحظه ای مورد بررسی قرار گیرد. همچنین داخل دکمه ی sign up نیز صحت ورودی ها را بررسی کردیم. در صورتی که هر کدام از فیلد ها، ورودی صحیحی نداشته باشند با متد ()setError میتوانیم یک خطا را به کاربر نمایش دهیم. متنی را که میخواهیم نمایش دهیم به ورودی متد setError(getString(R.string.err_msg_name)) پاس میدهیم. با متد setErrorEnabled(false) نیز میتوانیم بعد از درست شدن ورودی آن متن خطا را از بین ببریم.
امیدوارم از این آموزش لذت برده باشید و در برنامه های آیندهی خود از این روش استفاده کنید.
لطفا سوالات خود را در قسمت نظرات بیان کنید.
برای دیگر آموزش های اندروید و طراحی اصولی (material design) با ZeroToHero همراه باشید.
موفق باشید.