Android : ปรับแต่งปุ่มให้เฟี้ยวด้วย Selector และ Shape

สวัสดีครับบทความนี้ผมจะวกกลับมาเรื่องพื้นฐานของปุ่มครับ โดยจะปรับแต่งลักษณะของปุ่มให้มีลูกเล่นสวยงาม และพูดถึงการใช้งานพื้นฐานของ Resource โดยจะเน้นไปที่ Style (ก็คือ style.xml ของเรานั้นเองครับ) ซึ้งคิดว่าเป็นส่วนที่หลายๆคนไม่ชอบใช้ เอาหละเราจะสร้างตัวอย่างง่ายๆในการปรับแต่งปุ่ม โดยจะแบ่งโครงสร้างของตัวอย่างเป็น 3 ส่วน (3 ไฟล์) ดังนี้

 

โครงสร้างของตัวอย่าง

1.) activity_main.xml

ส่วนนี้รายละเอียดไม่มากครับ แค่ทำการเพิ่ม Button ลงบน Layout ** เป็น Button เปล่าๆเลยครับไม่มีการใส่ขนาดหรือสีอะไรทั้งนั้น

2.) style.xml

ตรงนี้คือรายละเอียดของปุ่มครับไม่ว่าจะเป็น ขนาด, สี, ขอบ และอื่นๆ จะมากำหนดตรงนี้ครับ

3.) button_blue.xml

สุดท้ายจะเป็นการกดหนดให้ปุ่มมีการไฮไลท์ปุ่มหรือการเปลี่ยนสีปุ่ม เมื่อมีการกด

Screenshot from 2014-11-14 08:46:07

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>  

 

ผลการรันตัวอย่าง

Screenshot from 2014-11-14 17:28:57

Fig 2. รูปผลลัพธ์การรันแอพพลิเคชั่น (จะเห็นว่าภาพด้านขวา ปุ่มจะสว่างกว่าเล็กน้อย)

 

About octoboy


Android Developer, Study Master degree of Computer Engineering at Prince of Songkla university.