متریال دیزاین : بخش دوازدهم : کار با TextInputLayout و Floating Label

خانه » آموزش های پایه » متریال دیزاین : بخش دوازدهم : کار با TextInputLayout و Floating Label
متریال دیزاین : بخش دوازدهم : کار با TextInputLayout و Floating Label معرفی TextInputLayout:
به‌نام خدا. در این مبحث به قابلیتی با عنوان Floating Label می‌پردازیم که بر روی EditText اجرا می‌شود. در گذشته با Hint آشنا شدیم. با استفاده از این ویژگی می‌توانستیم یک توضیح کوتاه به یک EditText اضافه کنیم که با پر شدن فیلد توسط کاربر، Hint نیز مخفی می‌شد. اما برای زیبایی بیشتر فیلدهایی که دارای Hint می‌باشند می‌توانیم قابلیتی پیاده سازی کنیم که با لمس EditText توسط کاربر و وارد کردن مقدار، Hint حذف نشده و با یک حالت انیمیشن به بالای فیلد منتقل شود. برای پیاده سازی این قابلیت به کتابخانه Support Design و تگ TextInputLayout نیاز داریم. ضمنا از این کامپوننت برای نمایش Error ها نیز استفاده می‌شود.
یک پروژه جدید با نام TextInputLayout و یک Empty Activity ایجاد می‌کنم.
در ابتدا لازم است کتابخانه design را به پروژه اضافه کنم:
dependencies { implementation fileTree(dir: '..

خانه » آموزش های پایه » متریال دیزاین : بخش دوازدهم : کار با TextInputLayout و Floating Label

متریال دیزاین : بخش دوازدهم : کار با TextInputLayout و Floating Label

معرفی TextInputLayout:

آموزش ساخت Floating Label متریال در اندروید

به‌نام خدا. در این مبحث به قابلیتی با عنوان Floating Label می‌پردازیم که بر روی EditText اجرا می‌شود. در گذشته با Hint آشنا شدیم. با استفاده از این ویژگی می‌توانستیم یک توضیح کوتاه به یک EditText اضافه کنیم که با پر شدن فیلد توسط کاربر، Hint نیز مخفی می‌شد. اما برای زیبایی بیشتر فیلدهایی که دارای Hint می‌باشند می‌توانیم قابلیتی پیاده سازی کنیم که با لمس EditText توسط کاربر و وارد کردن مقدار، Hint حذف نشده و با یک حالت انیمیشن به بالای فیلد منتقل شود. برای پیاده سازی این قابلیت به کتابخانه Support Design و تگ TextInputLayout نیاز داریم. ضمنا از این کامپوننت برای نمایش Error ها نیز استفاده می‌شود.

یک پروژه جدید با نام TextInputLayout و یک Empty Activity ایجاد می‌کنم.
در ابتدا لازم است کتابخانه design را به پروژه اضافه کنم:

  dependencies {      implementation fileTree(dir: 'libs', include: ['*.jar'])      implementation 'com.android.support:appcompat-v7:27.1.1'      implementation 'com.android.support:design:27.1.1'  }  

قصد دارم دو EditText برای دریافت نام کاربری و رمز عبور کاربر به اکتیویتی اضافه کنم:

activity_main.xml:

  <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical"      tools:context=".MainActivity">        <android.support.design.widget.TextInputLayout          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/user_layout">            <EditText              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:id="@+id/user_edittext"              android:hint="Username"/>        </android.support.design.widget.TextInputLayout>          <android.support.design.widget.TextInputLayout          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_layout">            <EditText              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:id="@+id/pass_edittext"              android:hint="Password"              android:inputType="textPassword"/>        </android.support.design.widget.TextInputLayout>    </LinearLayout>  

هر EditText درون یک تگ TextInputLayout قرار می‌گیرد.
پروژه را اجرا می‌کنم:

آموزش کار با TextInputLayout در اندروید

آموزش کار با TextInputLayout در اندروید

با اجرای پروژه، اولین EditText یعنی Username در حالت Focus قرار می‌گیرد که آماده وارد کردن کاراکتر است. هر آیتمی که در حالت Focus باشد رنگ Hint و خط زیر آن قرمز و مابقی آیتم‌ها خاکستری است.
ممکن است بخواهیم آیتمی غیر از آیتم اول در حالت Focus باشد. یا بهرحال تعیین کنیم یک آیتم خاص به عنوان آیتم Focus شده نمایش داده شود. به کد زیر دقت کنید:

  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/pass_layout">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_edittext"          android:hint="Password"          android:inputType="textPassword"/>      <requestFocus/>    </android.support.design.widget.TextInputLayout>  

من یک تگ requestFocus به TextInputLayout مربوط به آیتم Password اضافه کردم که در اجرای مجدد پروژه هم این فیلد Focus شده:

تگ requestFocus

در حال حاضر همیشه یک EditText باید در حالت Focus باشد. اما بهتر است حالتی را پیاده سازی کنیم که اگر کاربر نقطه ای از صفحه (بجز محل این دو آیتم) را لمس کند، آیتمی که Focus هست از این حالت خارج شده و در نهایت تمامی آیتم ها در حالت عادی نمایش داده شوند.

  <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:tools="http://schemas.android.com/tools"      android:layout_width="match_parent"      android:layout_height="match_parent"      android:orientation="vertical"      tools:context=".MainActivity"      android:focusable="true"      android:focusableInTouchMode="true"      android:id="@+id/main_layout">        <android.support.design.widget.TextInputLayout          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/user_layout">            <EditText              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:id="@+id/user_edittext"              android:hint="Username"/>        </android.support.design.widget.TextInputLayout>          <android.support.design.widget.TextInputLayout          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_layout">            <EditText              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:id="@+id/pass_edittext"              android:hint="Password"              android:inputType="textPassword"/>          <requestFocus/>        </android.support.design.widget.TextInputLayout>    </LinearLayout>  

Layout ریشه اکتیویتی یک LinearLayout است. به این لایه دو خاصیت focusable و focusableInTouchMode با مقدار true و یک id اضافه کردم. سپس در Backend اکتیویتی این لایه را تعریف نموده و برای آن یک متد Listener می‌سازم که ورودی آن null است:

MainActivity.java:

  package ir.android_studio.textinputlayout;    import android.support.v7.app.AppCompatActivity;  import android.os.Bundle;  import android.widget.LinearLayout;    public class MainActivity extends AppCompatActivity {        LinearLayout mLayout;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);            mLayout = findViewById(R.id.main_layout);          mLayout.setOnClickListener(null);        }  }  

مقدار null برای این setOnClickListener باعث می‌شود تا هنگام کلیک (لمس) صفحه که من از نوع LinearLayout ساخته ام، همه EditText ها در حالت غیر Focus قرار گیرند:

خارج شدن EditText ها از حالت فوکوس

ضمنا با اضافه شدن دو خاصیت فوق به لایه اصلی، هیچکدام از آیتم ها در ابتدای اجرای پروژه به صورت پیش فرض Focus نیستند.
قبل از ادامه آموزش، تگ requestFocus را هم غیر فعال (کامنت) می‌کنم زیرا نمی‌خواهم هیچ آیتمی فوکوس باشد.

مدیریت Error ها در TextInputLayout:

مطمئنا همه ما هنگام تکمیل فرم ها به ارورهایی برخورد کرده ایم. این فرم می‌تواند یک فرم ثبت نام در یک وب سایت یا یک اپلیکیشن باشد. به عنوان مثال در فیلد مربوط به کد پستی، اخطار “کد وارد شده باید ده رقم باشد” به کاربر اعلام می‌شود.
تصمیم دارم برای فیلد Username یک error تعریف کنم.

  package ir.android_studio.textinputlayout;    import android.support.design.widget.TextInputLayout;  import android.support.v7.app.AppCompatActivity;  import android.os.Bundle;  import android.view.View;  import android.widget.EditText;  import android.widget.LinearLayout;    public class MainActivity extends AppCompatActivity {        LinearLayout mLayout;      TextInputLayout userLayout, passLayout;      EditText userEdittext, passEdittext;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);            mLayout = findViewById(R.id.main_layout);          mLayout.setOnClickListener(null);            userLayout = findViewById(R.id.user_layout);          passLayout = findViewById(R.id.pass_layout);            userEdittext = findViewById(R.id.user_edittext);          passEdittext = findViewById(R.id.pass_edittext);            userEdittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {              @Override              public void onFocusChange(View view, boolean b) {                    if (userEdittext.getText().toString().isEmpty()) {                      userLayout.setError("Enter Username!");                  } else {                      userLayout.setErrorEnabled(false);                  }                }          });        }    }  

در کد بالا از متد setOnFocusChangeListener استفاده شده:

متد setOnFocusChangeListener

  userEdittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {      @Override      public void onFocusChange(View view, boolean b) {        }  });  

این متد هنگامی اجرا می‌شود که کاربر روی یک EditText ضربه بزند و آن فیلد در حالت فوکوس قرار بگیرد. متد را به اینصورت تکمیل می‌کنم:

  userEdittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {      @Override      public void onFocusChange(View view, boolean b) {            if (userEdittext.getText().toString().isEmpty()) {              userLayout.setError("Enter Username!");          } else {              userLayout.setErrorEnabled(false);          }        }  });  

یک شرط تعیین کردم که اگر EditText خالی بود، توسط متد setError یک ارور را روی userLayout نمایش بدهد و زمانی که این شرط نقض شد (یعنی فیلد خالی نباشد) ارور غیر فعال شود.
پروژه را اجرا می‌کنم:

نمایش ارور در EditText

نمایش ارور توسط TextInputLayout

نمایش Error در EditText

ملاحظه می‌کنید با لمس EditText مربوط به Username بلافاصله اخطار با رنگ قرمز زیر آن نمایش داده می‌شود. در حال حاضر برنامه یک ایراد دارد. با وجود اینکه من کلمه test را تایپ کرده‌ام هنوز اخطار Enter Username حذف نشده و زمانی حذف خواهد شد که کاربر EditText بعدی یا جای دیگری از صفحه را لمس کند تا این آیتم از Focus خارج شود. در صورتی که به محض ورود اولین کاراکتر این ارور باید حذف شود.
با استفاده از متد addTextChangedListener و TextWatcher می‌توانیم تغییرات متن یک EditText را شنود کنیم.

متد addTextChangedListener در اندروید

  userEdittext.addTextChangedListener(new TextWatcher() {      @Override      public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {        }        @Override      public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {        }        @Override      public void afterTextChanged(Editable editable) {        }  });  

TextWatcher سه متد دارد که نقش هرکدام از نامش پیداست. beforeTextChanged قبل از تغییر متن، onTextChanged هنگام تغییر متن و afterTextChanged بعد از تغییر متن صدا زده می‌شوند.
در اینجا من به متد دوم نیاز دارم. همان if ای که قبلا نوشتم را درون این متد تکرار می‌کنم:

  package ir.android_studio.textinputlayout;    import android.support.design.widget.TextInputLayout;  import android.support.v7.app.AppCompatActivity;  import android.os.Bundle;  import android.text.Editable;  import android.text.TextWatcher;  import android.view.View;  import android.widget.EditText;  import android.widget.LinearLayout;    public class MainActivity extends AppCompatActivity {        LinearLayout mLayout;      TextInputLayout userLayout, passLayout;      EditText userEdittext, passEdittext;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);            mLayout = findViewById(R.id.main_layout);          mLayout.setOnClickListener(null);            userLayout = findViewById(R.id.user_layout);          passLayout = findViewById(R.id.pass_layout);            userEdittext = findViewById(R.id.user_edittext);          passEdittext = findViewById(R.id.pass_edittext);            userEdittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {              @Override              public void onFocusChange(View view, boolean b) {                    if (userEdittext.getText().toString().isEmpty()) {                      userLayout.setError("Enter Username!");                  } else {                      userLayout.setErrorEnabled(false);                  }                }          });            userEdittext.addTextChangedListener(new TextWatcher() {              @Override              public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {                }                @Override              public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {                    if (userEdittext.getText().toString().isEmpty()) {                      userLayout.setError("Enter Username!");                  } else {                      userLayout.setErrorEnabled(false);                  }                }                @Override              public void afterTextChanged(Editable editable) {                }          });        }    }  

حالا با وارد کردن اولین کاراکتر، اخطار حذف می‌شود:

متد onTextChanged در اندروید

با استفاده از خاصیت textColorHint می‌توان رنگ Hint یا همان Floating Label را تغییر داد:

  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/user_layout"      android:textColorHint="#36cb1f">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/user_edittext"          android:hint="Username"/>    </android.support.design.widget.TextInputLayout>  

خاصیت textColorHint در اندروید

خاصیت hintTextAppearance هم برای استایل دهی به Hint هنگامی که Focus شده، بکار می‌رود:

  <style name="TextInputStyle" parent="TextAppearance.AppCompat">      <item name="android:textColor">#434ab2</item>      <item name="android:textSize">16dp</item>  </style>  
  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/user_layout"      android:textColorHint="#36cb1f"      app:hintTextAppearance="@style/TextInputStyle">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/user_edittext"          android:hint="Username"/>    </android.support.design.widget.TextInputLayout>  

خاصیت hintTextAppearance در اندروید

بهتر است استایلی که تعریف می‌کنیم از TextAppearance.AppCompat ارث بری کند.
متن Error را هم به همین صورت و توسط خاصیت errorTextAppearance می‌توان استایل دهی کرد:

  <style name="ErrorInputStyle" parent="TextAppearance.AppCompat">      <item name="android:textColor">#731539</item>      <item name="android:textSize">16dp</item>  </style>  
  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/user_layout"      android:textColorHint="#36cb1f"      app:hintTextAppearance="@style/TextInputStyle"      app:errorTextAppearance="@style/ErrorInputStyle">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/user_edittext"          android:hint="Username"/>    </android.support.design.widget.TextInputLayout>  

خاصیت errorTextAppearance در اندروید

در TextInputLayout قابلیت دیگری با نام Counter (شمارنده) تعریف شده. کاربرد شمارنده در مواقعی است که بخواهیم تعداد کاراکترهای مناسب را به کاربر اعلام کنیم:

  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/pass_layout"      app:counterEnabled="true"      app:counterMaxLength="8">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_edittext"          android:hint="Password"          android:inputType="textPassword" />      <!-- <requestFocus/> -->    </android.support.design.widget.TextInputLayout>  

خاصیت counterEnabled برای فعال کردن این ویژگی و counterMaxLength برای تعیین تعداد کاراکتر استفاده شده است:

قابلیت Counter یا شمارنده در TextInputLayout اندروید

با وارد کردن هر کاراکتر درون این EditText یک شماره به عدد سمت چپ اضافه می‌شود.
در صورتی که تعداد کاراکتر ورودی از مقدار MaxLength بیشتر شود، رنگ شمارنده تغییر می‌کند. تعیین رنگ شمارنده در حالت عادی و حالتی که تعداد کاراکترها از مقدار تعیین شده تجاوز کند به ترتیب توسط دو خاصیت counterTextAppearance و counterOverflowTextAppearance صورت می‌پذیرد:

  <style name="CounterStyle" parent="TextAppearance.AppCompat">      <item name="android:textColor">#30c7ae</item>  </style>    <style name="OverflowStyle" parent="TextAppearance.AppCompat">      <item name="android:textColor">#199b85</item>  </style>  
  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/pass_layout"      app:counterEnabled="true"      app:counterMaxLength="8"      app:counterTextAppearance="@style/CounterStyle"      app:counterOverflowTextAppearance="@style/OverflowStyle">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_edittext"          android:hint="Password"          android:inputType="textPassword" />      <!-- <requestFocus/> -->    </android.support.design.widget.TextInputLayout>  

خاصیت counterTextAppearance در اندروید

خاصیت counterOverflowTextAppearance در اندروید

خاصیت passwordToggleEnabled آیکونی به EditText های از نوع password اضافه می‌کند که کاربر با لمس آن، پسوردی که وارد کرده را می‌تواند مشاهده می‌کند:

  <android.support.design.widget.TextInputLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:id="@+id/pass_layout"      app:counterEnabled="true"      app:counterMaxLength="8"      app:counterTextAppearance="@style/CounterStyle"      app:counterOverflowTextAppearance="@style/OverflowStyle"      app:passwordToggleEnabled="true">        <EditText          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:id="@+id/pass_edittext"          android:hint="Password"          android:inputType="textPassword" />      <!-- <requestFocus/> -->    </android.support.design.widget.TextInputLayout>  

خاصیت passwordToggleEnabled در اندروید برای نمایش پسورد

توجه : سورس پروژه درون پوشه Exercises قرار داده شده است

منابع تکمیلی:

https://developer.android.com/reference/android/support/design/widget/TextInputLayout
https://developer.android.com/reference/com/google/android/material/textfield/TextInputLayout
https://developer.android.com/reference/android/text/TextWatcher

دانلود فایل این آموزش با فرمت PDF به همراه سورس پروژه
تعداد صفحات : ۲۱
حجم : ۱/۳ مگابایت
قیمت : رایگان
دانلود رایگان با حجم ۱/۳ مگابایت لینک کمکی برچسب ها : رابط_کاربری, رابط_کاربری_اندروید, متریال_دیزاین آموزش رایگان, آموزش های پایه ۰۱ تیر ۱۳۹۷

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

سوربات پتاسیم استئارات منیزیم بنزوات سدیم منتول وانیل مونوسدیم گلوتامات صمغ عربی استئاریک اسید پودر تالک پرلیت خاک رنگبر روغن آرگان روغن جوجوبا تیو سولفات سدیم کراتین کتراک اسید تانیک پکتین کاراگینان پودر کاکائو

کتراک

صمغ عربی

مونو سدیم گلوتامات

اسید استیک

کربومر

کافور

خاک دیاتومه

کربن فعال

سیلیکون دی اکساید

آویسل

آنتی اکسیدان TBHQ

گلوتن ذرت

لانولین

روغن کندش

کافور

گلوتن

روغن فندوق

لاکتات کلسیم

منیزیم استئارات

روغن آووکادو

روغن درخت چای

روغن براهمی

روغن نارگیل

کتراک

سوربات پتاسیم

روغن بادام

شی باتر

ایزوتیازولین

روغن خراطین

روغن جوجوبا

مالتودکسترین

روغن آرگان

فوماریک اسید

خاک دیاتومه

پروپیونات کلسیم