รู้จักกับ Snackbar ของเล่นตัวใหม่จาก Material Design

วันนี้ขอหยิบหนึ่งใน Component ของ Material Design ที่มีชื่อว่า Snackbar มาเล่าสู่กันฟัง

โดย Material Design เป็น UI Design Concept ที่ถูกพัฒนาขึ้นโดย Google เพื่อเป็น Design Guideline ในการพัฒนาซอฟต์แวรบน Platform ต่างๆ ซึ่ง Android ก็เป็นหนึ่งในนั้นเช่นกัน

และสิ่งที่น่าสนใจของ Material Design นั้นก็คือ Library ที่พัฒนาขึ้นมาตาม Concept ของ Material Design เพื่อช่วยให้นักพัฒนาสามารถนำ Component ต่างๆไปใช้งานได้ทันที

Snackbar คืออะไร?

Snackbar เป็น Lightweight Feedback ที่ถูกออกแบบมาเพื่อใช้ในการโต้ตอบกับผู้ใช้ โดยมีจุดประสงค์หลักคือการแจ้งเตือนข้อความบางอย่างให้ผู้ใช้ทราบ ด้วยการแสดงผลที่ด้านล่างของหน้าจอมือถือที่จะรบกวนสายตาผู้ใช้ให้น้อยที่สุด แต่ยังคงมองเห็นเนื้อหาบน Snackbar ได้อยู่

แล้ว Snackbar ต่างจาก Toast ยังไง?

ถ้าเทียบ Snackbar กับ Toast ด้วยรูปแบบ Snackbar ที่ง่ายที่สุดก็จะเห็นว่ามีหน้าตาที่คล้ายกันอยู่ไม่น้อย

แต่ทว่า Snackbar นั้นมีความสามารถอื่นๆที่นักพัฒนาสามารถกำหนดได้ โดยที่ไม่สามารถทำได้ใน Toast มาก่อน

  • Snackbar ที่แสดงอยู่จะถูกซ่อนทันที ถ้ามีการแสดง Snackbar ตัวใหม่กว่า
  • สามารถกำหนดให้แสดงช่วงระยะเวลาหนึ่งหรือจะแสดงถาวรก็ได้
  • สามารถเพิ่ม Action Button เพื่อให้ผู้ใช้สามารถกดเพื่อทำอะไรบางอย่างตามที่นักพัฒนากำหนดไว้ได้ เช่น กดเพื่อปิด Snackbar หรือกดเพื่อ Undo เพื่อยกเลิกการลบอีเมล เป็นต้น

และแน่นอนว่า Snackbar ถูกออกแบบมาแบบ Material Design จึงทำให้การแสดงผลของ Snackbar นั้นเข้ากันได้ดีกับ Component ตัวอื่นๆของ Material Design นั่นเอง

การใช้งาน Snackbar

เพราะ Snackbar เป็น Component ของ Material Design ดังนั้นการเรียกใช้งานก็จะต้องเพิ่ม Library ของ Material Design เข้าไปในโปรเจคก่อน

implementation 'com.google.android.material:material:1.3.0'

สำหรับคำสั่งเพื่อเรียกใช้งาน Snackbar นั้นจะมีให้ใช้งานหลายแบบ

Snackbar.make(view: View, resId: Int, duration: Int)
Snackbar.make(view: View, text: CharSequence?, duration: Int)
Snackbar.make(context: Context, view: View, text: CharSequence, duration: Int)

แต่รูปแบบในการใช้งานก็จะคล้ายๆกับ Toast ตรงที่สร้างมีการใช้ show() ด้วยทุกครั้งเพื่อให้ Snackbar แสดงขึ้นมาบนหน้าจอ

val view: View = /* ... */
val message: String = "Hello from Sleeping For Less"
Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show()

ในการใช้งานรูปแบบที่ง่ายที่สุด Snackbar จะนำ View ที่กำหนดไว้ในคำสั่ง make(...) ไปหา Root View ก่อน แล้วค่อยแสดง Snackbar บน Root View ตัวนั้นอีกที

การแสดงข้อความใน Snackbar

ข้อความใน Snackbar จะแสดงได้สูงสุดแค่ 2 บรรทัดเท่านั้น ถ้าเกิน 2 บรรทัดก็จะถูกตัดคำให้เป็นเครื่องหมายจุด 3 จุดแทน

ทั้งนี้ก็เพราะว่า Snackbar ใช้เพื่อแจ้งเตือนผู้ใช้งานแอปในระยะสั้นๆ ดังนั้นควรเป็นข้อความที่สั้นกระชับเพื่อไม่รบกวนผู้ใช้จนมากเกินไป

ระยะเวลาในการแสดงผลของ Snackbar

นักพัฒนาไม่สามารถกำหนดระยะเวลาในการแสดงผลของ Snackbar ด้วยการระบุหน่วยเป็นวินาทีได้ แต่จะต้องใช้ค่าที่ Snackbar ได้เตรียมไว้ให้แล้ว (คล้ายกับ Toast) โดยมีทั้งหมด 3 แบบด้วยกัน

  • Snackbar.LENGTH_SHORT - 1.5 วินาที
  • Snackbar.LENGTH_LONG - 2.75 วินาที
  • Snackbar.LENGTH_INDEFINITE - ไม่หายไปจนกว่าจะมีคำสั่งยกเลิกหรือมีอันอื่นมาแทนที่ (ควรกำหนด Action ให้กับ Snackbar ด้วย)

กำหนด Action ให้กับ Snackbar

เพื่อให้ผู้ใช้สามารถโต้ตอบอะไรบางอย่างกับการแจ้งเตือนด้วย Snackbar ได้ จึงทำให้นักพัฒนาสามารถกำหนด Action ในลักษณะของ Text Button ที่จะแสดงบน Snackbar ได้ตามใจชอบ

โดยใส่ Action ได้แค่เพียง 1 ตัวเท่านั้น และเมื่อผู้ใช้กดที่ Action ก็จะทำการซ่อน Snackbar ทันที

setAction(resId: Int, listener: (View) -> Unit)
setAction(text: CharSequence?, listener: (View) -> Unit)

ในการกำหนด Action จะต้องสร้าง Snackbar ขึ้นมาด้วยคำสั่ง make(...) ก่อนแล้วค่อยกำหนด Action ที่ต้องการเพิ่มเข้าไป

Snackbar.make(/* ... */)
    .setAction("OK") { /* Do something */ }
    .show()

และถ้าอยากจะเปลี่ยนสีของข้อความใน Action ก็มีคำสั่งให้กำหนดเพิ่มแบบนี้ด้วย

val color: Int = /* ... */
Snackbar.make(/* ... */)
    .setAction(/* ... */)
    .setActionTextColor(color)
    .show()

โดยคำสั่ง setActionTextColor(...) นอกจากจะกำหนดค่าเป็น Color Integer ได้แล้ว ยังกำหนดเป็น ColorStateList ได้อีกด้วย สำหรับการกำหนดสีข้อความแยกตาม State

นอกจากนี้ Snackbar จะตัดคำของข้อความแจ้งเตือนโดยคำนวณจากข้อความของ Action ด้วย ดังนั้นจึงทำให้ในบางครั้งข้อความถูกตัดหายไปเมื่อมีการแสดง Action

เพื่อแก้ปัญหานี้ Snackbar จึงรองรับการแยกบรรทัดระหว่างข้อความแจ้งเตือนกับข้อความของ Action ได้

นักพัฒนาจะต้องใช้คำสั่ง setMaxInlineActionWidth(...) เพื่อกำหนดความกว้างสูงสุดของ Action เพื่อตัดขึ้นบรรทัดใหม่

val color: Int = /* ... */
Snackbar.make(/* ... */)
    .setAction(/* ... */)
    .setMaxInlineActionWidth(80)
    .show()

โดยค่าดังกล่าวจะต้องกำหนดเป็นหน่วย dp

การซ่อน Snackbar ผ่านโค้ด

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

ด้วยเงื่อนไขนี้ นักพัฒนาสามารถเก็บค่าของ Snackbar เพื่อใช้คำสั่ง dismiss() ในภายหลังได้ตามต้องการ

val snackbar = Snackbar.make(/* ... */)
snackbar.show()
/* ... */
snackbar.dismiss()

และถ้าในหน้านั้นมี Snackbar มากกว่า 1 ตัวก็ระวังโดน Snackbar ตัวอื่นแสดงขึ้นมาแทนที่ด้วยล่ะ

แสดง Snackbar อยู่ข้างบน View ที่ต้องการ

โดยปกติแล้ว Snackbar จะแสดงอยู่ข้างล่างสุดของหน้าจออยู่เสมอ แต่ในบางกรณีนักพัฒนาก็ไม่อยากให้ Snackbar ทับ View บางตัว เช่น Floating Action Button หรือ ปุ่มที่อยู่ข้างล่างของหน้าจอ เป็นต้น

ซึ่ง Snackbar นั้นรองรับการกำหนดค่าที่เรียกว่า Anchor View หรือ View ที่ต้องการให้ Snackbar แสดงอยูข้างบนนั่นเอง

โดยกำหนด Anchor View ผ่านคำสั่ง setAnchorView(...) ในตอนที่สร้าง Snackbar ขึ้นมานั่นเอง

val view: View = /* ... */
val button: Button = /* ... */
Snackbar.make(view, "Hello from Sleeping For Less", Snackbar.LENGTH_SHORT)
    .setAnchorView(button)
    .show()

สรุป

Snackbar ถือว่าเป็นหนึ่งใน Component สำคัญจาก Material Design ที่จะช่วยเพิ่มรูปแบบสำหรับการแจ้งเตือนภายในแอปให้กับผู้ใช้ในรูปแบบที่ User Friendly มากขึ้น ซึ่งแน่นอนว่าการใช้งานส่วนใหญ่ของ Snackbar จะเป็นการใช้งานแทนที่ Toast นั่นเอง เพราะถูกออกแบบมาให้รองรับรูปแบบการใช้งานได้หลากหลายกว่า จึงทำให้นักพัฒนาสามารถนำไปใช้งานได้สถานการณ์ต่างๆได้ง่ายนั่นเอง