30 August 2016

ทำ Password Visibility Toggle แบบง่ายๆได้ด้วย Material Design Support Library

Updated on


        ในทุกวันนี้นักพัฒนาแอนดรอยด์หลายๆคนก็คงต้องขอบคุณเจ้า Material Design Support Library ที่เข้ามาช่วยให้ชีวิตง่ายขึ้นมากๆ ซึ่ง Library ตัวนี้ทำให้นักพัฒนาสามารถสร้างแอปฯให้มีหน้าตาเป็นแบบ Material Design ได้ไม่ยาก เพราะเจ้า Library ตัวนี้เตรียมพร้อมไว้ให้เกือบทั้งหมดแล้ว

        และล่าสุดเจ้า Library ตัวนี้ก็เพิ่มปุ่ม Password Visibility Toggle มาให้ด้วย ซึ่งจะช่วยให้นักพัฒนาสามารถทำ Edit Text สำหรับกรอก Password ให้มีปุ่มแสดง/ซ่อนรหัสผ่านที่พิมพ์ลงในช่องนั้นได้แล้ว โดยแทบจะไม่ต้องทำอะไรเลยล่ะ! แถมเป็นไปตาม Principle ที่ทาง Material Design แนะนำไว้ด้วย


        สำหรับผู้ที่หลงเข้ามาอ่านคนใดยังไม่เคยใช้ Library ตัวนี้มาก่อน ให้เพิ่ม Dependency ของ Material Design เข้าไปใน build.gradle ดังนี้

dependencies {
    ...
    implementation 'com.google.android.material:material:1.0.0'
}

        ซึ่งโดยปกติแล้วเวลาเรียกใช้งานจะต้องใช้ TextInputEditText แทน EditText และต้องครอบด้วย TextInputLayout แบบนี้

<android.support.design.widget.TextInputLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <android.support.design.widget.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Password"
        android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>

        ถ้ากำหนด inputType ให้เป็น textPassword ใน Library เวอร์ชันใหม่นี้ก็จะใส่ปุ่ม Password Visibility Toggle ให้เป็น Default ทันที


        และถ้าไม่อยากให้แสดงปุ่มดังกล่าวก็ต้องเพิ่ม Attribute ที่ชื่อว่า passwordToggleEnabled เข้าไปใน TextInputLayout แทน แล้วกำหนดให้เป็น False

app:passwordToggleEnabled="false"

        เวลาใช้งานก็จะเป็นแบบนี้

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ... >

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleEnabled="false">

        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Password"
            android:inputType="textPassword" />
    </android.support.design.widget.TextInputLayout>
</FrameLayout>

        แต่จากภาพ Default ที่ตัว Library เตรียมไว้ให้ เจ้าของบล็อกรู้สึกว่ามันสังเกตยากไปหน่อยนะ...


        ซึ่งไม่ต้องห่วง เพราะว่าตัว Library ก็ได้คิดเผื่อไว้แล้ว จึงมาพร้อมกับ Attribute ตัวอื่นๆที่ใช้ในการ Custom เจ้าปุ่มดังกล่าวได้

app:passwordToggleDrawable="<drawable>"
app:passwordToggleTint="<color>"

         จึงทำให้ผู้ที่หลงเข้ามาอ่านสามารถกำหนดภาพด้วย Drawable Resource ได้เลยจ้า แต่แนะนำว่าให้ทำเป็น Selector นะ เพราะเวลาแสดงรหัสผ่านเงื่อนไขของ Selector ณ ตอนนั้นคือ

android:state_checked="true"

        ดังนั้นเจ้าของบล็อกก็จะต้องเตรียมภาพอย่างน้อยสองภาพ สำหรับปุ่มดังกล่าว แล้วสร้าง Selector ขึ้นมาดังนี้

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

        และเวลาเรียกใช้งานก็จะเป็นแบบนี้

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    ... >

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:passwordToggleDrawable="@drawable/selector_button_password_visibility"
        app:passwordToggleTint="@color/colorAccent"
        app:passwordToggleEnabled="true">

        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Password"
            android:inputType="textPassword" />
    </android.support.design.widget.TextInputLayout>
</FrameLayout>

        จะเห็นว่าเจ้าของบล็อกมีการกำหนด Tint Color ด้วย ซึ่งค่อนข้างสะดวกดี เพราะว่าภาพที่เจ้าของบล็อกมีอยู่นั้นเป็นสีขาว แต่อยากให้แสดงเป็นสี @color/colorAccent (อันนี้กำหนดไว้ใน colors.xml) ก็สามารถกำหนดจากใน Attribute ที่ชื่อว่า passwordToggleEnabled ได้ทันที

        และเมื่อดูผลลัพธ์ก็จะได้ออกมาเป็นแบบนี้


        แต่ภาพที่ใช้ในนี้ก็เหมือนๆกับภาพของพวก Checkbox หรือ Toggle  Button ตรงที่มันไม่สามารถกำหนดขนาดโดยตรงได้ ดังนั้นผู้ที่หลงเข้ามาอ่านจะต้องเตรียมภาพที่มีขนาดเหมาะสมมาใส่ (ซึ่งเจ้าของบล็อกไม่ชอบซักเท่าไรกับการฝากความหวังไว้กับหน่วย px)


        ขนาดของปุ่ม Password Visibility Toggle นั้นมีขนาด 24x24 dp ซึ่งนั่นก็หมายความว่าที่ mdpi จะต้องใช้ภาพขนาด 24x24 px และขนาดต่างๆก็คำนวณตาม Scale Factor ของ Denstity แต่ละตัวได้เลย

        เพียงเท่านี้ก็ไม่ต้องมานั่งเขียนโค้ดให้มันซ่อน/แสดงรหัสผ่านเองแล้ววววววว

แหล่งข้อมูลอ้างอิง

        • TextInputLayout @ Android Developer
        • Support Library Revision History @ Android Developer