ของเล่นใหม่สำหรับนักพัฒนาสาย Android ที่มาพร้อมกับ Material Design เวอร์ชัน 23+ นั้นก็คงจะหนีไม่พ้น SnackBar ที่เป็นลูกเล่นแทน Toast ได้อย่างดี
ศึกษาบทเรียนก่อนหน้านี้: บทเรียนการพัฒนาแอพพลิเคชันบน Android
สำหรับ SnackBar นั้นเป็นลูกเล่นใหม่ของระบบปฏิบัติการ Android ที่มาพร้อมกับ Material Design เพื่อมาเป็นจุดนำเสนอข้อความแจ้งเตือนรูปแบบสถานะ ทดแทน Widget เก่าอย่าง Toast ออกไป หากสังเกตดูแล้วการทำงานของ SnackBar และ Toast นั้นแทบจะใกล้เคียงกันแต่ก็มีข้อแตกต่างปรากฏอยู่ตามนี้ครับ
ข้อดีของ SnackBar คือ ผู้ใช้งานสามารถกำหนดให้โชว์ตลอดเวลา หรือไม่ต้องตลอดเวลาก็ได้ หากต้องการโชว์ตลอดเวลาก็สามารถปิดมันได้ด้วยการ Swipe ปาดไปทางขวา หรือแตะเพื่อดูมันได้ครับ ต่างกับ Toast ที่ทำไรไม่ได้ อีกทั้งต้องรอมัน Fade Out หายไปซึ่งก็ต้องใช้เวลาประมาณนึง
การแสดงผลของ SnackBar นั้นก็จะไม่รบกวนผู้ใช้งานครับ หากมีหลายรายการมันจะทยอยแสดงผลทีละ บรรทัดเป็นแอนิเมชันทีละตัวทีละตัวไป ต่างกับ Toast ที่มาทีเดียวครึ่งหน้าจอก็เลยปรากฏขึ้น (ตอนเทสแอพฯ) เอาเป็นว่าเรามาดูวิธีทำกันดีกว่ายากแค่ไหน
เปิด Android Studio ขึ้นมาครับสร้าง Blank Activity ขึ้นมา 1 ตัว
หากเป็นตัว SDK 23.0.1 หรือ 23+ ที่มากับการอัพเด็ต Android Studio และ Android SDK ครั้งใหญ่แล้วก็ไม่ต้องทำไรครับ แต่ถ้ายังเป็นตัวเก่าให้อัพเกรต SDK เป็น 23 แล้วเปิด build.gradle (Module) ขึ้นมาเพิ่มส่วน dependencies เข้าไปครับ
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:design:23.0.1' }
เปิดไฟล์ Layouts/activity_main.xml ขึ้นมาเพิ่ม id ให้กับ CoordinatorLayout ชื่อว่า @+id/coordinatorLayout
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:id="@+id/coordinatorLayout" tools:context=".MainActivity">
ไฟล์ activity_main.xml จะเป็นดังนี้
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:id="@+id/coordinatorLayout" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
ต่อมาเพิ่มปุ่มที่ content_main.xml ครับ 3 ปุ่มโดยเราจะใช้ฟังก์ชันของ SnackBar Widget ที่ประกอบไปด้วย Simple Mode, CallBack เพื่อกดแก้ไขข้อมูล หรือตอบรับ และตัวสุดท้ายคือการ Customized Color ชุดสีของ SnackBar ครับ
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_main" tools:context=".MainActivity"> /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingLeft="20dp" android:paddingRight="20dp" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <Button android:id="@+id/btnSnackBar1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="Simple Snackbar" /> <Button android:id="@+id/btnSnackBar2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="With Action Callback" /> <Button android:id="@+id/btnSnackBar3" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="Custom Color"/> </LinearLayout> </RelativeLayout>
เมื่อจัดการส่วนของ Layout เรียบร้อยแล้วก็มาส่วนของ MainActivity.java ครับ ส่วนของ Import มีดังนี้
import android.os.Bundle; import android.graphics.Color; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; import android.widget.TextView;
สร้างตัวแปร Global Var เข้าไปตามนี้ มี Button 3 ตัวตามฟังก์ชัน
public class MainActivity extends AppCompatActivity { private CoordinatorLayout coordinatorLayout; private Button sb_simple, sb_callback, sb_custom;
สร้างตัวแปรมารับ CoordinatorLayout
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
ทำการ Finalize ส่วนของ Button ทั้งหมด
sb_simple = (Button) findViewById(R.id.btnSnackBar1); sb_callback = (Button) findViewById(R.id.btnSnackBar2); sb_custom = (Button) findViewById(R.id.btnSnackBar3);
ปุ่มแรกคือ Simple SnackBar
sb_simple.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar simple_mode_snackbar = Snackbar.make(coordinatorLayout, "Hello World!", Snackbar.LENGTH_LONG); simple_mode_snackbar.show(); } });
ทดสอบสักหน่อย
เป็นรูปแบบง่ายๆ เรียก String ปรากฏขึ้นมา ถ้าต้องการปิดแจ้งเตือน SnackBar ก็ Swipe หรือปาดนิ้วไปทางขวาของหน้าจอแอพพลิเคชัน
ส่วนของ Call Back
sb_callback.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar callback_mode_snackbar = Snackbar .make(coordinatorLayout, "เช้าฟาดผัดฟัก!", Snackbar.LENGTH_LONG) .setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { Snackbar callback_mode_snackbar_undo = Snackbar.make(coordinatorLayout, "เย็นฟาดฟักผัด!", Snackbar.LENGTH_SHORT); callback_mode_snackbar_undo.show(); } }); callback_mode_snackbar.show(); } });
ทดสอบ
จะเป็นการแสดงข้อความเบื้องต้น พร้อมปุ่มให้กระทำสักอย่างเพื่อเปลี่ยนสถานะของมัน
ปุ่มสุดท้ายเป็นการเปลี่ยนสไตล์ชุดสีการแสดงผลของ SnackBar ครับ
sb_custom.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar custom_mode_snackbar = Snackbar .make(coordinatorLayout, "ยายกินลำใยน้ำลายยายไหลย้อย!", Snackbar.LENGTH_LONG) .setAction("FUCK", new View.OnClickListener() { @Override public void onClick(View view) { } }); //Text Color custom_mode_snackbar.setActionTextColor(Color.RED); //Change Action Color View sbView = custom_mode_snackbar.getView(); TextView txt_message = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); txt_message.setTextColor(Color.GREEN); custom_mode_snackbar.show(); } });
ทดสอบ
ภาพรวมของไฟล์ MainActivity.java คือ
package th.ac.dpu.snackbartutorial; import android.os.Bundle; import android.graphics.Color; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private CoordinatorLayout coordinatorLayout; private Button sb_simple, sb_callback, sb_custom; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); sb_simple = (Button) findViewById(R.id.btnSnackBar1); sb_callback = (Button) findViewById(R.id.btnSnackBar2); sb_custom = (Button) findViewById(R.id.btnSnackBar3); sb_simple.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar simple_mode_snackbar = Snackbar.make(coordinatorLayout, "Hello World!", Snackbar.LENGTH_LONG); simple_mode_snackbar.show(); } }); sb_callback.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar callback_mode_snackbar = Snackbar .make(coordinatorLayout, "เช้าฟาดผัดฟัก!", Snackbar.LENGTH_LONG) .setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { Snackbar callback_mode_snackbar_undo = Snackbar.make(coordinatorLayout, "เย็นฟาดฟักผัด!", Snackbar.LENGTH_SHORT); callback_mode_snackbar_undo.show(); } }); callback_mode_snackbar.show(); } }); sb_custom.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar custom_mode_snackbar = Snackbar .make(coordinatorLayout, "ยายกินลำใยน้ำลายยายไหลย้อย!", Snackbar.LENGTH_LONG) .setAction("FUCK", new View.OnClickListener() { @Override public void onClick(View view) { } }); //Text Color custom_mode_snackbar.setActionTextColor(Color.RED); //Change Action Color View sbView = custom_mode_snackbar.getView(); TextView txt_message = (TextView) sbView.findViewById(android.support.design.R.id.snackbar_text); txt_message.setTextColor(Color.GREEN); custom_mode_snackbar.show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
อีกตัวอย่างที่ไม่ยากเลยใช่ไหมครับ SnackBar ที่มาพร้อม Material Design เอาไปประยุกต์กันดูนะครับ
ศึกษาบทเรียนก่อนหน้านี้: บทเรียนการพัฒนาแอพพลิเคชันบน Android