Android : ปรับแต่งปุ่มให้เฟี้ยวด้วย Selector และ Shape
|สวัสดีครับบทความนี้ผมจะวกกลับมาเรื่องพื้นฐานของปุ่มครับ โดยจะปรับแต่งลักษณะของปุ่มให้มีลูกเล่นสวยงาม และพูดถึงการใช้งานพื้นฐานของ Resource โดยจะเน้นไปที่ Style (ก็คือ style.xml ของเรานั้นเองครับ) ซึ้งคิดว่าเป็นส่วนที่หลายๆคนไม่ชอบใช้ เอาหละเราจะสร้างตัวอย่างง่ายๆในการปรับแต่งปุ่ม โดยจะแบ่งโครงสร้างของตัวอย่างเป็น 3 ส่วน (3 ไฟล์) ดังนี้
โครงสร้างของตัวอย่าง
1.) activity_main.xml
ส่วนนี้รายละเอียดไม่มากครับ แค่ทำการเพิ่ม Button ลงบน Layout ** เป็น Button เปล่าๆเลยครับไม่มีการใส่ขนาดหรือสีอะไรทั้งนั้น
2.) style.xml
ตรงนี้คือรายละเอียดของปุ่มครับไม่ว่าจะเป็น ขนาด, สี, ขอบ และอื่นๆ จะมากำหนดตรงนี้ครับ
3.) button_blue.xml
สุดท้ายจะเป็นการกดหนดให้ปุ่มมีการไฮไลท์ปุ่มหรือการเปลี่ยนสีปุ่ม เมื่อมีการกด
Fig 1. จากภาพอธิบายการทำงานทั้ง 3 ไฟล์เพิ่มเติมจะได้เห็นภาพมากขึ้น
ทำไมต้องใช้ Style ?
มาถึงตรงนี้หลายๆคนอาจมีข้อสงใสในการกำหนดคุณลักษณะของปุ่มว่าทำไมเราไม่กำหนดใน activity_main.xml และต้องมากำหนดใน style.xml ให้ยุ่งยาก ซึ้งผมจะเสนอข้อดีของการใช้ style ผ่านคำถาม 2 ข้อดังนี้ครับ
1.) หากคุณต้องสร้างปุ่มเหมือนๆกันหลายๆครั้ง ไม่ว่าจะใน layout เดียวกันหรือต่าง layout คิดว่าใช้แบบไหนง่ายกว่ากัน (การกำหนดลักษณะของปุ่มใน style ทำให้เราสามารถนำ style ที่เราสร้างขึ้นมาใส่ให้กับทุกปุ่ม)
2.) หากเราต้องแก้ไขทุกปุ่มในภายหลัง คิดว่าแบบไหนแก้ไขได้ไวกว่า (เราสามารถแก้ที่ไฟล์ style อย่างเดียว)
โดยปกติแล้วเราจะกำหนดคุณลักษณะของปุ่มแบบนี้
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"/>
แต่การใช้ style เราจะต้องแยกคุณลักษณะมาเก็บไว้ใน style.xml แบบนี้
<style name="btn_blue" parent="@android:style/Widget.Button">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#FFFFFF</item>
</style>
หลังจากนั้นเราสามารถใส่ style ให้กับปุ่มได้โดยการวางโค้ดข้างล่างเป็น style ของปุ่มใน activity_main.xml
<Button
style="@style/btn_blue"/>
State List หรือ Selector คืออะไร ?
ส่วนนี้ทำหน้าที่ในการกำหนดการเปลี่ยนแปลงกราฟฟิคเมื่อมีการเปลี่ยนสถานะ (selector อยู่ใน bg_btn_blue.xml) เช่น การเปลี่ยนพื้นหลังเมื่อถูกกด โดยมีสถานะของที่เราสามารถกำหนดได้เช่น state_pressed (ถูกกด), state_focused (ถูกโฟกัส), state_selected (ถูกเลือก) และอื่นๆ ในตัวอย่างนี้เราจะใช้แค่ state_pressed เท่านั้นมีรูปแบบดังนี้ครับ
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/hilight" /> <!-- เมื่อกด -->
<item android:drawable="@drawable/normal" /> <!-- ปกติ -->
</selector>
แต่หากจะกำหนดสถานะเพิ่มเติมได้ก็สามารถไปอ่านต่อได้ที่ Resource Types หลังจากนั้นเราจะกำหนด selector ให้กับปุ่มโดยการตั้งเป็นพื้นหลังของใน style.xml ดังนี้ครับ
<item name="android:background">@drawable/bg_btn_blue</item>
การวาดรูปด้วย Shape เพื่อเปลี่ยนสีปุ่ม
ในตัวอย่างนี้เราจะนำ shape มาเป็นพื้นหลังของปุ่ม โดยการกำหนด shape ให้กับปุ่มสามารถกำหนดได้ตามตัวอย่างข้างล่างครับ
<item android:state_pressed="true">
<shape android:shape="rectangle">
<corners android:radius="5dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#01A9DB" android:endColor="#819FF7" />
</shape>
</item>
การใส่ shape ให้กับ selector เราจะทำการกำหนดใน state ต่างๆในตัวอย่างข้างบนเรากำหนดใน state_pressed อีกทั้งการสร้าง shape นั้นเรายังสามารถกำหนดคุณลักษณะต่างให้สวยงาม ด้วยการกำหนด corner (ขอบโค้ง), stroke (ขนาดและสีของขอบ), gradient (พื้นหลังแบบไล่สี) และอื่นๆ (ดูรายละเอียดเพิ่มเติมได้ที่ Drawable Shape หรือภาษาไทยที่ สร้างภาพง่ายๆจาก XML ด้วย Shape [Drawable Resource] ) เอาหละเนื้อหาสำคัญๆ ผมก็อธิบายไปครบแล้วต่อไปคือตัวอย่าโค้ดและผลการรัน และก็ขอจบบทความไว้แต่เพียงเท่านี้ครับ
ตัวอย่างซอสโค้ด
res/layout/activity_main.xml
<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:text="Button"
style="@style/btn_blue"/>
</RelativeLayout>
res/value/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
<style name="btn_blue" parent="@android:style/Widget.Button">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/bg_btn_button</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
<item name="android:padding">2dp</item>
<item name="android:layout_margin">10dp</item>
<item name="android:layout_alignParentTop">true</item>
</style>
</resources>
res/drawable/bg_btn_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<shape android:shape="rectangle">
<corners android:radius="5dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#01A9DB" android:endColor="#819FF7" />
</shape>
</item>
<item android:state_focused="true">
<shape android:shape="rectangle">
<corners android:radius="5dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#01A9DB" android:endColor="#819FF7" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<corners android:radius="5dip" />
<stroke android:width="1dip" android:color="#5e7974" />
<gradient android:angle="-90" android:startColor="#0489B1" android:endColor="#01A9DB" />
</shape>
</item>
</selector>
ผลการรันตัวอย่าง
Fig 2. รูปผลลัพธ์การรันแอพพลิเคชั่น (จะเห็นว่าภาพด้านขวา ปุ่มจะสว่างกว่าเล็กน้อย)