Google Flutter

Flutter: วิธีแก้ปัญหา UI โดนบัง จาก on-screen keyboard ใน Google Flutter

เรื่องที่เกี่ยวข้อง - Google Flutter, Widget

วันก่อนเห็นพี่เอกโพสเกี่ยวกับวิธีแก้ปัญหา UI โดนบังเพราะ on-screen keyboard สำหรับคนทำแอพ Android แบบ Native (ใน post ใช้ Kotlin) ก็มานั่งคิดว่าเออ แล้ว Google Flutter มันเจอปัญหาแบบเดียวกันไหม

มานั่งดู เฮ้ย มันเจอกรณีแบบเดียวกันจริงๆ ด้วย

เลยนั่งหา solution เพื่อแก้ปัญหานี้ ซึ่งก็จะมีอธิบายกลไกคร่าวๆ และพลได้ทำเป็น flutter package ออกมาให้เอาไปใช้กันได้สบายๆ ครับ

สถานการณ์เป็นใจ

คือเรื่องของการที่ผู้ใช้กดเลือกช่องสำหรับกรอกข้อมูล ที่เราสร้างด้วย widget ชื่อ TextField หรือ TextFormField แล้วมีการ scroll พาตัว Widget ไปวางอยู่ด้านบนของคีย์บอร์ด (เรียกอีกชื่อว่า on-screen keyboard ก็ได้) เป็นเรื่องปกติใช่ไหม

ทว่ามันจะมีบางสถานการณ์ที่ เราไม่อยากให้ส่วนที่อยู่ด้านล่างของ TextField หรือ TextFormField มันถูกซ่อนไปไว้ด้านหลัง keyboard หน่ะสิ

เช่น อาจจะเป็นปุ่มลงทะเบียน, ปุ่ม sign in, sign up หรือ UI ส่วนอื่นๆ ที่ตอนผู้ใช้จะกรอกข้อมูล เราอยากให้มันยังอยู่บนหน้าจอ

ไม่อยากให้มันถูกซ่อนอยู่ด้านหลัง keyboard เงียบๆ

scrollPadding ไม่ดีหรอ?

จริงๆ แล้ว Flutter มีการเตรียมกลไก สำหรับการเว้นระยะห่างระหว่างขอบด้านล่างของ TextField และ TextFormField และตัว keyboard อยู่นะ มันมีชื่อว่า scrollPadding

ซึ่งทำให้เราสามารถกำหนดค่าด้วย EdgeInset แบบทั่วๆ ไปอยู่

TextField(
   scrollPadding: EdgeInsets.all(10)
)

และมันก็ใช้ได้นะ

แต่ว่าการจะกะเกณฑ์ให้มีระยะห่างที่สวยงามเป๊ะๆ กับพื้นที่ของ UI ที่อยู่ถัดไปด้านล่างของส่วนกรอกข้อมูล มันอาจต้องใช้พลังเยอะซักหน่อย

พลเลยทำ Widget set ออกมาเป็น Never Behind Keyboard package ที่ทำให้เราเอาไปใช้ได้ง่ายๆ ครับ

ซึ่งกลไกภายใน Never Behind Keyboard package จะขอเขียนเล่าทางเทคนิคไว้อีกโพสหน้าแล้วกัน ด้านล่างเอาวิธีใช้ก่อน

แนะนำการใช้งาน Never Behind Keyboard

กลไกการทำงานของ Never Behind Keyboard จะประกอบไปด้วย Widget 3 ตัว นั่นคือ

  1. NeverBehindKeyboardArea
  2. NeverBehindFocusSource
  3. NeverBehindBottom

1. กำหนดพื้นที่การ scroll ด้วย NeverBehindKeyboardArea

ปกติถ้าเรามีการวางแบบฟอร์มการกรอกข้อมูล ที่ประกอบไปด้วย TextField หรือ TextFormField แล้ว ถ้ามีขนาดที่ยาวล้นหน้าจอ หรือมองแล้วว่าต้องถูกบังด้วย keyboard แน่ๆ ก็มักจะเอาใส่ไว้ใน ScrollView หรือ ListView widget

จุดนี้แหละที่เราต้องครอบ NeverBehindKeyboardArea ไว้นอกบริเวณที่เป็น ScrollView หรือ ListView widget ครับ

NeverBehindKeyboardArea(
    scrollView: ListView(
        children: [
            
        ],
    ),
),

จากนั้น ด้านในที่แหละที่เราสามารถวาง NeverBehindFocusSource กับ NeverBehindBottom ไว้ด้านในได้

2. กำหนดส่วนตรวจจับการกดเลือกกรอกข้อมูล ด้วย NeverBehindFocusSource

ทีนี้ไม่ว่าด้านในจะซับซ้อนแค่ไหน ตัวที่กระตุ้นกลไกของเราคือ TextField และ TextFormField เวลาถูกกดเลือก

ดังนั้นอยากให้ส่วนที่ทำให้เกิดกลไกการเปิด on-screen keyboard อยู่ภายใน NeverBehindFocusSource widget

และแน่นอนว่า NeverBehindFocusSource widget ต้องอยู่ภายใน NeverBehindKeyboardArea widget นะ

NeverBehindKeyboardArea(
    scrollView: ListView(
        children: [
            // ไม่สำคัญว่าจะซับซ้อนแค่ไหน แค่ใส่ TextField หรือ TextFormField ไว้ด้านใน NeverBehindFocusSource ก็พอ
            NeverBehindFocusSource(
                child: Column(
                    children: [
                        TextField(
                            decoration: InputDecoration(
                                hintText: "หลักสูตรเรียนออนไลน​์ Google Flutter สำหรับผู้เริ่มต้น www.nextflow.in.th",
                            ),
                        ),
                        TextFormField(),
                    ],
                ),
            ),
        ],
    ),
),

เราสามารถใช้ NeverBehindFocusSource กับ TextField หรือ TextFormField ก็ได้ครับ และสามารถใส่ลงไป NeverBehindFocusSource ได้หลายตัวครับ

3. กำหนดขอบด้านล่างพื้นที่ ด้วย NeverBehindBottom

สุดท้ายแล้ว เราต้องกำหนดตำแหน่งอ้างอิงพื้นที่ระหว่าง NeverBehindFocusSource กับขอบด้านบนของ on-screen keyboard ด้วยการใช้ NeverBehindBottom widget

ซึ่งตำแหน่งที่มักวาง NeverBehindBottom widget ก็คือขอบด้านล่างสุดของพื้นที่ที่เราไม่อยากให้ถูกซ่อน หรือถูกบังไว้ด้านหลัง on-screen keyboard นั่นเอง

สำคัญตรงจุดที่มีการใช้ NeverBehindBottom widget คือต้องกำหนด key ด้วย GlobalKey() นะ ส่วนนี้สำคัญในการอ้างอิงตำแหน่งในการ scroll

และให้ชัวร์ว่า NeverBehindBottom widget อยู่ภายใน NeverBehindKeyboardArea widget นะครับ

NeverBehindKeyboardArea(
    scrollView: ListView(
        children: [
            // ไม่สำคัญว่าจะซับซ้อนแค่ไหน แค่ใส่ TextField หรือ TextFormField ไว้ด้านใน NeverBehindFocusSource ก็พอ
            NeverBehindFocusSource(
                child: Column(
                    children: [
                        TextField(
                            decoration: InputDecoration(
                                hintText: "หลักสูตรเรียนออนไลน​์ Google Flutter สำหรับผู้เริ่มต้น www.nextflow.in.th",
                            ),
                        ),
                        TextFormField(),
                    ],
                ),
            ),
            // กำหนดขอบด้านล่างสุดที่จะถูกวางไว้เหนือ on-screen keyboard และอย่าลืมสร้าง GlobalKey ให้มันด้วย
            NeverBehindBottom(key: Globalkey())
        ],
    ),
),

เสร็จแล้วก็ลองใช้งานได้เลย หรือจะโหลดโปรเจคนี้มาลองรันก็ได้นะ หรือพร้อมแล้วก็ไปดูวิธีติดตั้งในของ package ใน pub.dev

ถ้าชอบก็เข้าไปกดให้คะแนนใน pub.dev และกดให้ดาวใน Github เป็นกำลังใจได้นะครับ

เริ่มต้นเรียนรู้สร้างแอพ iOS และ Android ด้วย Google Flutter ไปกับโค้ชพล

เหมาะสำหรับผู้เริ่มต้น

เขียนครั้งเดียว ใช้ได้ทั้งระบบ iOS และ Android ประหยัดเวลา

เรียนได้ทุกเวลา ไม่มีวันหมดอายุ

ได้รู้ตั้งแต่วิธีติดตั้งโปรแกรม จนเอาขึ้นApp Store และ Play Store

ได้ทำแอพของจริง เริ่มต้นจาก 0 ทุกโปรเจค มีระบบถามตอบ กรณีติดปัญหา

 

แหล่งที่มาของข้อมูลที่ใช้ในการสร้าง

เริ่มต้นยุค AI ด้วยคอร์สฟรี และพรีเมี่ยม กับพล

หากชอบสิ่งที่พลเล่า เรื่องที่พลสอน สามารถสนับสนุนพลโดยการเข้าเรียนคอร์สออนไลน์ของพลนะคร้าบ

  • เข้าใจง่าย ใช้ได้จริง ออกแบบการสอนอย่างเข้าใจโดยโค้ชพล
  • มีคอร์สสำหรับคนใช้งานทั่วไป จนถึงเรียนรู้เพื่อใช้งานในสายอาชีพขั้นสูง
  • ทุกคอร์สมีใบประกาศณียบัตรรับรองหลังเรียนจบ

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

Privacy Preferences

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

Allow All
Manage Consent Preferences
  • Always Active

Save