web analytics

Flutter : การทำให้แอปรองรับ Layout ในทุกขนาดหน้าจอ

cover

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

 

เริ่มต้น

ปกติเวลาเราทำแอป ก็ต้องทำหน้าจอให้รองรับสำหรับอุปกรณ์ที่มีจอขนาดใหญ่ด้วย เช่นแท็บเลต ซึ่ง UI/UX มันก็จะแตกต่างจากในหน้าจอมือถือ เช่นมีเมนูด้านซ้าย รายละเอียดด้านขวา ส่วนในมือถือก็กดแล้วไปหน้าใหม่ เราจะมาลองทำกัน

b1

 

New Flutter  Project ก่อน โดยผมจะทำแอปแสดงเมนูชื่อสัตว์

screenshot_1549509147

สร้างหน้า Animal List

ก่อนอื่นทำหน้าสำหรับ list ก่อน โดยใช้ ListView

 

ได้หน้าจอ list แล้ว

2

 

สร้างหน้า Animal Detail

สร้างหน้าใหม่ ชื่อ AnimalDetailPage
ออกแบบหน้าจอง่ายๆ แค่เอาค่าชื่อสัตว์จากหน้า Animal list มาแสดง

3

 

เปลี่ยนหน้าไปยัง Animal Detail

ที่ AnimalListPage เพิ่ม GestureDetector onTap ให้ route ไปที่ AnimalDetailPage

 

ตอนนี้จะสามารถเปลี่ยนหน้า ไป AnimalPageDetail ได้ พร้อมกับเอาค่ามาแสดง

a1

 

ลองรันใน tablet

a2

 

สร้างหน้าจอสำหรับแท็บเลต

ต่อมา เราต้องแยก layout เป็น 2 ส่วน ส่วนนึงสำหรับมือถือ อีกส่วนสำหรับแท็บเลต
โดยการแยกว่าเป้นหน้าจอแท็บเลต สามารถใช้ความกว้างขอจอแยกได้ คือ หน้าจอต้องกว้างมากกว่า 600

 

ถ้าเป็น แท็บเลตก็แสดงผลหน้าจอสำหรับแท็บเลต โดยจะแบ่ง
พื้นที่เป็นด้านซ้าย 1 ส่วน ด้านขวา 3 ส่วน วิธีแบ่งก็ใช้ Widget ที่ชื่อว่า Flexible

 

ลองรัน จะพบว่า AnimalPageDetail มี AppBar ซ้อนอยู่ ดังนั้นเราต้องไปแยก layout ที่ AnimalDetailPage ด้วย

4

 

ปรับแต่ง AnimalListPage

ก่อนอื่นมาปรับเมนู Animal list ให้ dynamic มากขึ้น
สร้าง class Animal

 

ประกาศตัวแปร list เก็บค่าว่ามี Animal อะไรบ้าง และ currentAnimalSelected เก็บค่าว่าตอนนี้เมนูไหนที่ถูกเลือกอยู่

 

ที่ initState กำหนดค่าเริ่มต้นให้กับ listAnimal

 

และที่ AnimalListPage ก็เปลี่ยน ListView มาใช้ ListView.builder แทน ทำให้ dynamic มากขึ้น

 

จากนั้นตอนกดที่เมนู จะแยกเป็น 2 กรณีคือ ถ้าเป็น phone จะเปลี่ยนหน้าโดยใช้ Navigator แต่ถ้าเป็น tablet แค่ กำหนด currentAnimalSelected ใหม่ แล้ว setState()

 

ที่หน้า AnimalDetilPage ก็แยกหน้าจอเป็น phone กับ tablet
และปรับให้ตัวหนังสือใน tablet ใหญ่กว่านิดหน่อย

 

ลองรัน ก็จะได้หน้าจอสำหรับ tablet แล้ว

5a

 

แท็บเลตแนวตั้งก็ยังแสดงผลในโหมดแท็บเลตอยู่ หาก width > 600

6

 

ลองรันในมือถือ ไม่ได้แสดงผลในโหมดแท็บเลต เพราะ width < 600

7 8

 

แต่หากเราทำหน้าจอเป็นแนวนอน ก็จะแสดงในโหมดแท็บเลต เพราะ width > 600
กรณีนี้ก็อยู่ที่เราว่าต้องการแบบนี้หรือไม่ ถ้าไม่ก็ต้องไปปรับเงื่อนไข เช่นใช้ smallWidth แทน

9

 

สรุปผล

a3

 

LayoutBuilder

จริงๆแล้ว Flutter มี Widget มาจัดการเรื่องนี้ ชื่อว่า LayoutBuilder โดยเราต้องกำหนดค่าผ่าน builder
สิ่งที่เราต้องทำคือ เอา constraints มาเช็คเงื่อนไขนั่นเอง ซึ่งผลลัพธ์ก็เหมือนเราใช้ MediaQuery

 

สรุป

การทำหน้าจอให้รองรับสำหรับแท็บเลตนั่นง่ายมาก แค่แยก layout ออกมาอีกอันและเช็คเงื่อนไขจากความกว้างของจอ กรณีเป็น มือถือตอนกดที่เมนูก็ให้เรียก Navigator เพื่อไปหน้าใหม่ แต่ถ้าเป็นแท็บเล็ตก็ช้วิธีการแสดง Widget อีกตัวแล้วก็ setState และสุดท้ายเราสามารถใช้ LayoutBuilder Widget แทนการเรียก MediaQuery ตรงๆได้ แล้วนำค่า constraint มาเช็คเงื่อนไข

 

โค้ดอยู่ที่ Github Gist

https://gist.github.com/benznest/8960e2db2b96b3e34486c25eaa8ee32d