TextInputLayout trong Android

Xin chào tất cả các bạn, hôm nay chúng ta sẽ cùng nhau tìm hiểu TextInputLayout trong Android. TextInputLayout

1. TextInputLayout là gì?

TextInputLayout là một thành phần của thư viện support design, được thêm vào từ version 22.2.0 và hiện tại là 28.0.0 com.android.support:design:28.0.0. Đây là một lớp kế thừa từ lớp LinearLayout cùng với TextInputLayout chúng ta còn có một lớp khác là TextInputEditText kế thừa từ lớp AppCompatEditText được thiết kế riêng để sử dụng cùng với TextInputLayout như là một thành phần con của lớp này và các bạn cũng nên sử dụng TextInputEditText thay vì EditText. TextInputLayout hỗ trợ chúng ta một số chức năng như hiển thị một label dạng nổi, hiển thị thông báo lỗi hay đếm số ký tự v.v..

2. Cách sử dụng?

<android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/form_username"/>

</android.support.design.widget.TextInputLayout>

Để sử dụng các bạn khai báo thẻ TextInputLayout làm thẻ cha sau đó khai báo thêm TextInputEditText bên trong thẻ này.
Lưu ý: Khi các bạn nhìn vào view thì TextInputLayout là view cha của TextInputEditText và các bạn sẽ dùng getParent() ở view con để lấy TextInputLayout, tuy nhiên việc gọi như vậy không đảm bảo việc view trả về cho các bạn sẽ là TextInputLayout giống như các bạn thấy trong file thiết kế giao diện xml, thay vào đó các bạn nên truy cập vào TextInputLayout bằng cách đặt id cho nó.

3. Các thuộc tính hỗ trợ.

TextInputLayout hỗ trợ một số thứ như gợi ý nổi, đếm ký tự hay hiển thị thông báo lỗi như ở trên đã trình bày, chúng ta hãy cũng tìm hiểu cách sử dụng.

3.1. Nhãn gợi ý nổi.

  • Cái này là mặc định khi các bạn khai báo thì floating hint sẽ mặc định được bật, float ting hint này thực ra là hint của TextInputEditText sẽ tự động nổi lên trên TextInputEditText khi người dùng click để nhập dữ liệu vào TextInputEditText.

    Hint khi người dùng chưa click vào TextInputEditText

    Hint khi người dùng click, hint sẽ tự động nổi lên, các bạn cũng có thể đổi màu hint này bằng cách set thuộc tính app:hintTextColor="@color/black" tại TextInputLayout. Ví dụ mình sẽ đổi màu sang màu đỏ chẳng hạn.

  • Tuy nhiên nếu các bạn thấy việc hiển thị này là không cần thiết, các bạn có thể tắt nó đi bằng cách đặt thuộc tính app:hintEnabled="false" cho TextInputLayout. Khi đó khi bạn click vào TextInputEditText thì giao diện sẽ như thế này.

    Lúc này thì như EditText bình thường các bạn hay dùng, hint sẽ không nổi lên trên nữa, rất đơn giản.

  • Còn một vấn đề nữa là khi hint nổi lên sẽ có animation, nếu bạn không muốn có animation này, bạn có thể tắt nó đi bằng thẻ app:hintAnimationEnabled="false" ở trong TextInputlayout. Lúc này hint sẽ nổi lên với animation đã bị bỏ đi, bạn có thể set như thế này nếu sợ animation kia làm người dùng mất tập trung.

  • Ngoài ra các bạn cũng có thể tạo ra style riêng cho hint của mình thông qua thẻ app:hintTextAppearance="@style/customHintStyle", sau đó định nghĩa customHintStyle ở trong style.xml. Ví dụ như màu sắc, font chữ hay size chữ chẳng hạn.

    <style name="customHintStyle" parent="TextAppearance.Design.Hint">
        <item name="android:textSize">@dimen/sp_32</item>
        <item name="fontFamily">@font/hiraginosans_w6</item>
        <item name="android:gravity">start|center_vertical</item>
    </style>

Và đây là kết quả.

  • Nhắc đến style tiện thể mình giới thiệu luôn ở đây các style cơ bản của TextInputlayout và chúng sẽ khác nhau ra sao. Ở đây chúng ta sẽ có bốn style cơ bản là.
"prefix + TextInputLayout.OutlinedBox"
"prefix + TextInputLayout.OutlinedBox.Dense"
"prefix + TextInputLayout.FilledBox"
"prefix + TextInputLayout.FilledBox.Dense"

Ở đây ta lưu ý đến hai thuộc tính chính đó là OutlinedBox với FilledBox và không có Dense với Dense

  • FilledBox: Đúng với tên gọi, chế độ này ta sẽ có hint và input sẽ nằm trong một không gian nhất định (box) kể cả khi hint nổi lên thì cũng sẽ vẫn nằm bên trong.


  • FilledBox.Dense: Tương tự như style ở trên, tuy nhiên khoảng cách các view sẽ có sự khác biệt đôi chút
</style>
    <style name="Widget.MaterialComponents.TextInputEditText.FilledBox" parent="Base.Widget.MaterialComponents.TextInputEditText">
    <item name="android:paddingTop">28dp</item>
    <item name="android:paddingBottom">12dp</item>
  </style>
<style name="Widget.MaterialComponents.TextInputEditText.FilledBox.Dense">
    <item name="android:paddingTop">24dp</item>
    <item name="android:paddingBottom">8dp</item>
  </style>

-> Các giá trị ở đây sai khác nhau ở việc TextInputEditText sẽ có các giá trị padding là bao nhiêu, với style dense thì các giá trị này nhỏ hơn, hiểu đơn giản là chúng ta sẽ có không gian TextInputEditText lớn hơn so với không có dense

  • OutlineBox: Đúng với tên gọi, chế độ này ta sẽ có hint khi nổi lên sẽ nằm bên ngoài khoảng không gian của thiết kế.


  • OutlineBox. Dense: Ok phần này cũng sẽ tương tự phần trên, sự khác biệt hiểu đơn giản sẽ là các giá trị padding sẽ nhỏ hơn so với không có dense.
<style name="Widget.MaterialComponents.TextInputEditText.OutlinedBox" parent="Base.Widget.MaterialComponents.TextInputEditText"/>
    <style name="Widget.MaterialComponents.TextInputEditText.OutlinedBox.Dense">
    <item name="android:paddingTop">13dp</item>
    <item name="android:paddingBottom">13dp</item> 

3.2. Đếm số ký tự.

Như đã trình bày ở trên chúng ta sẽ được hỗ trợ đếm và hiển thị việc đếm số ký tự. Việc này rất hữu ích khi chúng ta cần giới hạn độ dài nhập vào của một trường nào đó và muốn người dùng có thể dễ dàng quan sát được họ đã nhập vào bao nhiêu trên số ký tự cho phép. Để sử dụng chúng ta đặt hai thẻ là app:counterEnabled = "true"app:counterMaxLength="Your max length" tại TextInputLayout Việc hiển thị sẽ mặc định ở góc phía dưới bên phải của TextinputEditText, bạn có thể thay đổi style của view nhờ thẻ app:counterTextAppearance tuy nhiên vị trí hiển thị sẽ là cố định. Ví dụ.

     <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/text_input_email"
            style="@style/TextInputLayout"
            android:layout_marginTop="@dimen/dp_10"
            android:tag="email_invalid_tag"
            app:counterEnabled="true"
            app:counterTextAppearance="@style/CounterText"
            app:counterMaxLength="@integer/text_input_password_max_length"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_email_title">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/text_input_edit_text_email"
                style="@style/TextInputEditText"
                android:background="@drawable/bg_text_input_layout"
                android:inputType="textEmailAddress"
                android:maxLength="@integer/text_input_email_max_length"
                android:text="@={viewModel.email}" />

        </com.google.android.material.textfield.TextInputLayout>
    <style name="CounterText" parent="TextAppearance.Design.Counter">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/white</item>
    </style>


3.3. Hiển thị lỗi.

Để hiển thị lỗi các bạn chỉ cần gọi phương thước setError() cho TextInputLayout. Như đã trình bày ở trên, chúng ta không thể lấy TextInputLayout bằng cách getParent() vậy nên ta sẽ đặt id cho nó ví dụ như @+id/text_input_email sau đó chỉ cần gọi text_input_email.setError("Your error content here") và cũng tương tự như ở trên các bạn hoàn toàn có thể set style cho thông báo lỗi này bằng thẻ app:errorTextAppearance và định nghĩa một style cho nó trong style.xml

3.4. Ẩn hiện mật khẩu.

Để hiển thị icon ẩn hiện mật khẩu các bạn chỉ cần set thẻ app:passwordToggleEnabled="true" cho TextInputLayout là xong, tuy nhiên nếu bạn có mong muốn thay đổi icon này theo icon mà bạn mong muốn bạn có thể đặt thẻ app:passwordToggleDrawable="@drawable/show_password_selector" và sau đó định nghĩa một drawable show_password_selector là xong.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_show_password" android:state_checked="true" />
    <item android:drawable="@drawable/ic_hide_password" />
</selector>

4. Tổng kết.

Cảm ơn các bạn đã theo dõi bài viết. Các bạn cũng có thể tham khảo nguồn tại trang https://developer.android.com/guide