Constraint Layout - Barrier

Barrier เป็น Constraint Helper ที่สำคัญตัวหนึ่งสำหรับการใช้งาน Constraint Layout เลยก็ว่าได้ เพื่อช่วยให้นักพัฒนาสามารถจัด UI ที่ซับซ้อนได้ง่ายขึ้น

เพราะ View ที่อยู่ใน ConstraintLayout จะมี View ที่มี Dynamic Size ตาม Content เสมอ ทำให้ View บางตัวไม่สามารถอ้างอิงกับ View ได้แค่ตัวใดตัวหนึ่งเท่านั้น แต่ขึ้นอยู่กับขนาดของ View แต่ละตัวด้วย

ยกตัวอย่างเช่น ต้องการสร้าง UI ที่อยู่ต่อท้าย View 2 ตัว โดยมีเงื่อนไขว่าจะต้องอยู่ต่อท้าย (Bottom) กับ View ตัวที่ใกล้ที่สุด โดยไม่ไปทับกับ View อีกตัวนึง

จากภาพข้างบนจะเห็นว่าถ้า View ฝั่งซ้ายมือใกล้กว่า ก็จะอ้างอิงระยะห่างจาก View ตัวนั้น แต่ถ้า View ฝั่งขวาใกล้กว่า ก็จะอิงจาก View ตัวนั้นแทน

แต่ Constraint ไม่สามารถทำแบบนี้ได้ เพราะอ้างอิงกับ View ได้เพียงแค่ตัวเดียวเท่านั้น จึงต้องใช้ความสามารถของ Barrier เข้ามาช่วย แล้วให้ View ที่ต้องการไปอ้างอิงตำแหน่งจาก Barrier แทน

จากตัวอย่างข้างบนจะได้เป็น XML ออกมาแบบนี้

<androidx.constraintlayout.widget.ConstraintLayout ...>

    <TextView
        android:id="@+id/textViewLeft"
        ... />

    <TextView
        android:id="@+id/textViewRight"
        ... />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrierHeading"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="textViewLeft,textViewRight"
        ... />

    <View
        android:id="@+id/viewSeparator"
        app:layout_constraintTop_toBottomOf="@id/barrierHeading"
        ... />

    <!-- ... -->

</androidx.constraintlayout.widget.ConstraintLayout>

จะเห็นว่า Barrier มี Attribute เป็นของตัวเองอยู่ 2 ตัวด้วยกันคือ app:barrierDirection ที่เอาไว้กำหนดว่าจะให้ Barrier อ้างอิงจากด้านไหนของ View และ app:constraint_referenced_ids สำหรับกำหนดว่าจะให้ Barrier อ้างอิง View ตัวไหนบ้าง

กำหนดทิศทางในการอ้างอิงตำแหน่งให้กับ Barrier

ใช้ Attribute ที่ชื่อว่า app:barrierDirection ด้วยค่า top, bottom, start และ end โดยจะมีผลกับ View ทุกตัวที่อ้างอิง ไม่สามารถกำหนดทิศทางแยกกันได้

กำหนด View ที่ต้องการให้ Barrier อ้างอิงตำแหน่ง

ใช้ Attribute ที่ชื่อว่า app:constraint_referenced_ids สามารถกำหนด View กี่ตัวก็ได้โดยกำหนดเป็น View ID ที่ต้องการได้เลย (ไม่ต้องใส่ @+id) ถ้ามีหลายตัวก็ให้คั่นระหว่าง View ID แต่ละตัวด้วยเครื่องหมาย ,

การทำงานอื่น ๆ ของ Barrier ที่ควรรู้

Visibility ของ View ที่อ้างอิงใน Barrier มีผลต่อการทำงานของ Barrier

ในกรณีที่ View นั้น ๆ มีค่าเป็น Gone ก็จะทำให้ Barrier อ้างอิงตำแหน่งจาก View ตัวอื่น ๆ ที่เหลืออยู่ และถ้า View ทุกตัวกลายเป็น Gone ก็จะไปอ้างอิงจาก Parent (ConstraintLayout) แทน

แน่นอนว่าการกำหนด Invisible ให้กับ View ก็จะให้ผลลัพธ์ของ Barrier เหมือนกับ Visible นั่นเอง

การกำหนด Margin ให้กับ Barrier จะแตกต่างจาก View ทั่วไป

การใช้ Attribute อย่าง android:layout_margin จะไม่สามารถใช้กับ Barrier ได้ จะต้องใช้ app:barrierMargin แทน

Barrier มี Visibility เป็น Gone เสมอ

เป็นเรื่องปกติของ Constraint Helper แทบทุกตัว เพราะใช้เพื่ออ้างอิงตำแหน่งของ View ใน ConstraintLayout เท่านั้น

แต่นั่นก็หมายความว่าถ้ามี View ใด ๆ ก็ตามที่มาอ้างอิงตำแหน่งจาก Barrier และมีการกำหนด Attribute อย่าง android:layout_margin คู่กับ app:layout_goneMargin ผลที่ได้ก็คือค่า Margin ของ View ตัวนั้นจะใช้ค่าจาก app:layout_goneMargin เสมอ เพราะว่า Barrier มี Visibility เป็น Gone นั่นเอง

สรุป

Barrier เป็นหนึ่งใน Constraint Helper ที่สำคัญในการใช้งาน ConstraintLayout เพื่อรองรับ Dynamic UI ในรูปแบบต่าง ๆ ได้สะดวกมากขึ้น จึงทำให้การใช้งาน ConstraintLayout จะต้องมีการหยิบ Barrier เข้ามาช่วยอยู่บ่อย ๆ และในขณะเดียวกัน Barrier ก็มีรูปแบบการทำงานของตัวเองอยู่ ทำให้ในบางครั้งกลายเป็นข้อจำกัดในการสร้าง UI บางรูปแบบ อาจจะต้องมีการปรับรูปแบบของ View ต่าง ๆ ใน ConstraintLayout นิดหน่อยเพื่อให้สอดคล้องกับการทำงานของ Barrier