วันนี้ขอเบรกด้วยเรื่องพื้นฐานจำเป็นสำหรับการพัฒนาแอพแอนดรอยด์เสียหน่อย เพราะเจ้าของบล็อกเจอผู้ที่หลงเข้ามาอ่านที่ใช้งาน Class และ Listener เป็นแต่กลับสร้างเองไม่ค่อยเป็นกันเยอะพอสมควร ก็เลยทำบทความง่ายๆยกตัวอย่างการสร้าง Class และ Listener เอาไว้ใช้งานกันเองดีกว่า
บทความทั้งหมดในชุดนี้
• ลองหัดสร้าง Class และ Listener กันเถอะ - ตอนที่ 1• ลองหัดสร้าง Class และ Listener กันเถอะ - ตอนที่ 2
• ลองหัดสร้าง Class และ Listener กันเถอะ - ตอนที่ 3
มาเริ่มกันเถอะ
Class และ Listener นั้นคืออะไรในบทความนี้ไม่มีอธิบายนะครับ โปรด Google หาด้วยตัวเอง เนื่องจากเป็นพื้นฐานอย่างหนึ่งที่หาศึกษาได้ทั่วๆไปและตัวอย่างในบทความนี้จะอิงสถานการณ์จากการใช้งานบนแอนดรอยด์ซะหน่อย จะได้เห็นภาพกันง่ายขึ้น โดยจะเอาไอเดียมาจากตัวอย่างในบทความเรื่อง [Android Code] การสร้าง Custom Dialog
เพิ่มเติม - เนื้อหาในบทความนี้จะพิเศษหน่อย เพราะอยากจะให้ออกมาในลักษณะของ Android Code & Design Style คือนอกจากจะมีเรื่อง Class กับ Listener ที่เป็นพื้นฐานแล้ว ยังมีลักษณะการใช้งานที่อิงบนแอนดรอยด์จริงๆ และการออกแบบเพื่อใช้งานบนแอนดรอยด์จริงๆ จะได้เป็น Guideline สำหรับนำไปประยุกต์ต่อเองได้
สมมติว่าเจ้าของบล็อกเกิดอยากได้ Dialog แบบนี้
เอาไว้ทำเป็น Alert Dialog ของตัวเอง เวลาอยากจะให้แสดง Alert Dialog ก็จะให้แสดง Dialog แบบนี้แทน ดังนั้นลองสร้าง Custom Dialog แบบที่ต้องการก่อน
หมายเหตุ - เนื่องจากเป็นบทความพื้นฐานแต่เกี่ยวข้องกับโค๊ดแอนดรอยด์ ดังนั้นเจ้าของบล็อกขอ Follow ตามรูปแบบของแอนดรอยด์ที่ควรเขียนนะครับ อาจจะยาวไปหน่อย
Android Design Style
ก่อนอื่นเตรียมสีที่ต้องใช้ก่อน โดยสร้าง Value XML ขึ้นมาสำหรับเก็บค่าสี โดยกำหนดชื่อว่า colors.xml (ไม่บังคับชื่อ แต่ชื่อนี้จะทำให้จำได้ง่าย)
โดยสีที่ใช้จะมีแค่สีส้มกับสีขาว
/values/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 แทนดีกว่า
dimens.xml
<resources>
<dimen name="dialog_bg_radius">20dp</dimen>
<dimen name="dialog_button_radius">100dp</dimen>
</resources>
เมื่อพร้อมแล้ว ต่อไปก็สร้าง Shape Drawable ให้กับพื้นหลังของ Dialog เป็นอย่างแรกสุด
shape_dialog_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/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 สำหรับขนาดตัวอักษรเพิ่มเข้าไป
dimens.xml
<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
strings.xml
<?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
layout_dialog.xml
<?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>
ดังนั้นกลับไปที่ dimens.xml แล้วเพิ่มค่าสำหรับ Padding ซะ
dimens.xml
<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 เข้าไป
layout_dialog.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/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 ทุกๆครั้ง
shape_dialog_bg.xml
<?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
activity_main.xml
<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
• dialog_text_size >> text_size
dimens.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 ที่ต้องแก้ไข
layout_dialog.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>
activity_main.xml
<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 ขึ้นมา แล้วเพิ่มสีเทานิดๆ
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
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 ซะ
activity_main.xml
<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>
layout_dialog.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/selector_button"
android:text="@string/ok"
android:textColor="@color/orange"
android:textSize="@dimen/text_size" />
</LinearLayout>
เท่านี้ Button ก็จะดูมีชีวิตชีวาขึ้นมาหน่อยแล้ว เวลาที่ไม่ได้กดปุ่มจะเป็นสีขาว และเมื่อกดปุ่มก็จะเป็นสีเทา
เอาล่ะ!! Layout พร้อมแล้ว มาต่อกันที่โค๊ดเลยนะ
อ๊ะๆ อย่ารีบๆ เพราะรู้สึกบทความเริ่มจะยาวแล้ว ดังนั้นขอแยกออกไปเป็นสามตอนนะจ๊ะ