วันนี้ขอเบรกด้วยเรื่องพื้นฐานจำเป็นสำหรับการพัฒนาแอพแอนดรอยด์เสียหน่อย เพราะเจ้าของบล็อกเจอผู้ที่หลงเข้ามาอ่านที่ใช้งาน Class และ Listener เป็นแต่กลับสร้างเองไม่ค่อยเป็นกันเยอะพอสมควร ก็เลยทำบทความง่ายๆยกตัวอย่างการสร้าง Class และ Listener เอาไว้ใช้งานกันเองดีกว่า

บทความทั้งหมดในซีรีย์เดียวกัน

มาเริ่มกันเถอะ


Class และ Listener นั้นคืออะไรในบทความนี้ไม่มีอธิบายนะครับ โปรด Google หาด้วยตัวเอง เนื่องจากเป็นพื้นฐานอย่างหนึ่งที่หาศึกษาได้ทั่วๆไป

และตัวอย่างในบทความนี้จะอิงสถานการณ์จากการใช้งานบนแอนดรอยด์ซะหน่อย จะได้เห็นภาพกันง่ายขึ้น โดยจะเอาไอเดียมาจากตัวอย่างในบทความเรื่อง การสร้าง Custom Dialog

เพิ่มเติม — เนื้อหาในบทความนี้จะพิเศษหน่อย เพราะอยากจะให้ออกมาในลักษณะของ Android Code & Design Style คือนอกจากจะมีเรื่อง Class กับ Listener ที่เป็นพื้นฐานแล้ว ยังมีลักษณะการใช้งานที่อิงบนแอนดรอยด์จริงๆ และการออกแบบเพื่อใช้งานบนแอนดรอยด์จริงๆ จะได้เป็น Guideline สำหรับนำไปประยุกต์ต่อเองได้

สมมติว่าเจ้าของบล็อกเกิดอยากได้ Dialog แบบนี้

เอาไว้ทำเป็น Alert Dialog ของตัวเอง เวลาอยากจะให้แสดง Alert Dialog ก็จะให้แสดง Dialog แบบนี้แทน ดังนั้นลองสร้าง Custom Dialog แบบที่ต้องการก่อน

หมายเหตุ — เนื่องจากเป็นบทความพื้นฐานแต่เกี่ยวข้องกับโค๊ดแอนดรอยด์ ดังนั้นเจ้าของบล็อกขอ Follow ตามรูปแบบของแอนดรอยด์ที่ควรเขียนนะครับ อาจจะยาวไปหน่อย

ก่อนอื่นเตรียมสีที่ต้องใช้ก่อน โดยสร้าง Value XML ขึ้นมาสำหรับเก็บค่าสี โดยกำหนดชื่อว่า colors.xml (ไม่บังคับชื่อ แต่ชื่อนี้จะทำให้จำได้ง่าย)

โดยสีที่ใช้จะมีแค่สีส้มกับสีขาว

<?xml version="1.0" encoding="utf-8"?> <resources> <color name="orange">#f1592a</color> <color name="white">#ffffff</color> </resources>


และเนื่องจากพื้นหลังของ Dialog และปุ่ม OK เจ้าของบล็อกจะใช้เป็น Shape Drawable โดยจะมีการกำหนด Radius ของมุมทั้งสองอัน

ซึ่งตรงนี้เจ้าของบล็อกสามารถกำหนดค่าลงไปตรงๆเลยก็ได้ แต่เพื่อความเหมาะสมขอเก็บไว้ใน dimens.xml แทนดีกว่า

เมื่อพร้อมแล้ว ต่อไปก็สร้าง Shape Drawable ให้กับพื้นหลังของ Dialog เป็นอย่างแรกสุด

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="https://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="@color/orange" /> <corners android:radius="@dimen/dialog_bg_radius" /> </shape>


ตามด้วย Shape Drawable ของปุ่ม OK

shape_dialog_button_bg.xml

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="https://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="@color/white" /> <corners android:radius="@dimen/dialog_button_radius" /> </shape>

เมื่อ Shape Drawable พร้อมแล้ว ก็สร้าง Layout สำหรับ Dialog ขึ้นมาซะ โดยเจ้าของบล็อกขอตั้งชื่อไฟล์ว่า layout_dialog

ส่วนโค๊ดข้างในก็จะออกแบบตามที่สมมติไว้ในตอนแรกเลย สิ่งที่ต้องดูต่อคือ “ขนาดของตัวอักษร”
โดยเจ้าของบล็อกกำหนดขนาดเป็น 18sp

ดังนั้นให้กลับไปที่ dimens.xml ซะ แล้วกำหนด Value สำหรับขนาดตัวอักษรเพิ่มเข้าไป

<resources> <dimen name="dialog_bg_radius">20dp</dimen> <dimen name="dialog_button_radius">100dp</dimen> <dimen name="dialog_text_size">18sp</dimen> </resources>


ต่อมาคือ “ข้อความที่แสดง” ให้เปิด strings.xml ขึ้นมาเพื่อเก็บข้อความที่ต้องการใช้แสดง (เนื่องจากเป็นข้อความตายตัว จึงขอเก็บไว้ในนี้เลย) โดยกำหนดชื่อไว้ว่า do_not_press กับ ok

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CustomDialogClass</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="do_not_press">Hey!\nDon\'t press this button</string> <string name="ok">OK</string> </resources>


จากนั้นก็จัด Layout ใน layout_dialog.xml ซะ โดยให้ TextView มี ID เป็น tv_message ส่วน Button มี ID เป็น button_ok

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_dialog_bg" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center" android:text="@string/do_not_press" android:textSize="@dimen/dialog_text_size" android:textColor="@color/white"/> <Button android:id="@+id/button_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/shape_dialog_button_bg" android:text="@string/ok" android:textSize="@dimen/dialog_text_size" android:textColor="@color/orange"/> </LinearLayout>

เอ….รู้สึกเหมือนจะหายใจไม่ออกแฮะ ใส่ Padding กับ Margin เข้าไปซักหน่อยดีกว่า…

ดังนั้นกลับไปที่ dimens.xml แล้วเพิ่มค่าสำหรับ Padding ซะ

<resources> <dimen name="dialog_bg_radius">20dp</dimen> <dimen name="dialog_button_radius">100dp</dimen> <dimen name="dialog_padding">20dp</dimen> <dimen name="dialog_button_padding_vertical">20dp</dimen> <dimen name="dialog_button_padding_horizontal">40dp</dimen> <dimen name="dialog_text_size">18sp</dimen> </resources>


แล้วเพิ่ม Padding กับ Margin เข้าไป

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_dialog_bg" android:gravity="center" android:orientation="vertical" android:padding="@dimen/dialog_padding"> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/dialog_padding" android:gravity="center" android:text="@string/do_not_press" android:textColor="@color/white" android:textSize="@dimen/dialog_text_size" /> <Button android:id="@+id/button_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/shape_dialog_button_bg" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/dialog_text_size" /> </LinearLayout>


โดยที่ Padding ของ Button ให้เพิ่มเข้าไปที่ shape_dialog_bg.xml เพราะว่าเวลาเรียกใช้ shape ดังกล่าวจะได้ไม่ต้องมานั่งกำหนด Padding ทุกๆครั้ง

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/white" /> <corners android:radius="@dimen/dialog_button_radius" /> <padding android:left="@dimen/dialog_button_padding_horizontal" android:right="@dimen/dialog_button_padding_horizontal" android:top="@dimen/dialog_button_padding_vertical" android:bottom="@dimen/dialog_button_padding_vertical" /> </shape>


เพียงเท่านี้ก็จะได้ออกมาคล้ายๆกับที่ร่างแบบไว้ในตอนแรกแล้ว

เมื่อ Dialog พร้อมแล้ว สิ่งที่ขาดไม่ได้อีกอย่างคือ Layout หลักของแอพนั่นเอง ซึ่งเจ้าของบล็อกรู้สึขี้เกียจแล้ว ดังนั้นขอเอา Resource ที่ใช้ใน Dialog นี่แหละมา Reuse แทน จะได้ประหยัด Resource (แถ)

โดยเอา Button วางไว้ตรงกลางหน้าจอเนี่ยแหละ แล้วกำหนดให้มีชื่อ ID ว่า button_alert

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/orange" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/button_alert" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_dialog_button_bg" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/dialog_text_size" /> </LinearLayout>


และถ้าสังเกตดีๆจะเห็นว่าชื่อ Resource เริ่มไม่เหมาะสมแล้ว เช่น dialog_text_size ที่เจ้าของบล็อกเอามาใช้ใน activity_main.xml ด้วยซะงั้น ดังนั้นเพื่อความเหมาะสม “ควรเปลี่ยนเป็นชื่อที่เข้าใจง่ายกว่านี้”

ดังนั้นเจ้าของบล็อกจึงเปลี่ยนชื่อ Resource จาก

* shape_dialog_button_bg.xml >> shape_button_bg.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="dialog_button_radius">100dp</dimen> <dimen name="dialog_bg_radius">20dp</dimen> <dimen name="dialog_padding">20dp</dimen> <dimen name="dialog_button_padding_vertical">20dp</dimen> <dimen name="dialog_button_padding_horizontal">40dp</dimen> <dimen name="text_size">18sp</dimen> </resources>


กลับไปแก้ไฟล์ที่เรียกใช้ Resource ทั้งสองตัวนี้ให้เรียบร้อยด้วยนะ เพราะเปลี่ยนชื่อแล้ว โดยจะมี layout_dialog.xml กับ activity_main.xml ที่ต้องแก้ไข

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_dialog_bg" android:gravity="center" android:orientation="vertical" android:padding="@dimen/dialog_padding"> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/dialog_padding" android:gravity="center" android:text="@string/do_not_press" android:textColor="@color/white" android:textSize="@dimen/text_size" /> <Button android:id="@+id/button_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/shape_button_bg" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/text_size" /> </LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/orange" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/button_alert" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_button_bg" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/text_size" /> </LinearLayout>


เอ…รู้สึกว่าเจ้าของบล็อกลืมทำ Selector ให้กับปุ่มแฮะ ดังนั้นเวลากดที่ปุ่ม ปุ่มก็จะไม่มีการ Interactive ให้เห็น เพราะฉะนั้นขอใส่ Selector ให้ปุ่มหน่อยดีกว่า

เริ่มจากเปิดไฟล์ colors.xml ขึ้นมา แล้วเพิ่มสีเทานิดๆ

<?xml version="1.0" encoding="utf-8"?> <resources> <color name="orange">#f1592a</color> <color name="white">#ffffff</color> <color name="gray">#999999</color> </resources>


เปลี่ยนชื่อ shape_button_bg.xml เป็น shape_button_bg_normal.xml

จากนั้นก็สร้าง Shape Drawable ขึ้นมาใหม่อีกตัวชื่อว่า shape_button_bg_pressed.xml โดยที่โค๊ดข้างในเหมือนกับ shape_button_bg_normal.xml แต่ว่าใช้เป็นสีเทาแทน (Copy มาแล้วแก้โค๊ดข้างในก็ได้)

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/gray" /> <corners android:radius="@dimen/dialog_button_radius" /> <padding android:left="@dimen/dialog_button_padding_horizontal" android:right="@dimen/dialog_button_padding_horizontal" android:top="@dimen/dialog_button_padding_vertical" android:bottom="@dimen/dialog_button_padding_vertical" /> </shape>


จากนั้นสร้าง Selector ขึ้นมา โดยเจ้าของบล็อกจะกำหนดให้ชื่อว่า selector_button.xml

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


จากนั้นก็เอา Selector ไปกำหนดที่ Button แทน Shape Drawable ซะ

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/orange" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/button_alert" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/selector_button" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/text_size" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shape_dialog_bg" android:gravity="center" android:orientation="vertical" android:padding="@dimen/dialog_padding"> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="@dimen/dialog_padding" android:gravity="center" android:text="@string/do_not_press" android:textColor="@color/white" android:textSize="@dimen/text_size" /> <Button android:id="@+id/button_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/selector_button" android:text="@string/ok" android:textColor="@color/orange" android:textSize="@dimen/text_size" /> </LinearLayout>


เท่านี้ Button ก็จะดูมีชีวิตชีวาขึ้นมาหน่อยแล้ว เวลาที่ไม่ได้กดปุ่มจะเป็นสีขาว และเมื่อกดปุ่มก็จะเป็นสีเทา

เอาล่ะ!! Layout พร้อมแล้ว มาต่อกันที่โค๊ดเลยนะ

อ๊ะๆ อย่ารีบๆ เพราะรู้สึกบทความเริ่มจะยาวแล้ว ดังนั้นขอแยกออกไปเป็นสามตอนนะจ๊ะ