เลย์เอาต์โฟลว์ใน Compose

FlowRow และ FlowColumn เป็น Composable ที่คล้ายกับ Row และ Column แต่แตกต่างกันตรงที่รายการจะไหลไปที่บรรทัดถัดไปเมื่อคอนเทนเนอร์ไม่มีพื้นที่ ซึ่งจะสร้าง หลายแถวหรือหลายคอลัมน์ นอกจากนี้ คุณยังควบคุมจำนวนรายการในบรรทัดได้ด้วย การตั้งค่า maxItemsInEachRow หรือ maxItemsInEachColumn คุณมักจะใช้ FlowRow และ FlowColumn เพื่อสร้างเลย์เอาต์ที่ตอบสนองได้ โดยเนื้อหาจะไม่ถูกตัดออกหากรายการมีขนาดใหญ่เกินไปสำหรับมิติข้อมูลหนึ่ง และการใช้ maxItemsInEach* ร่วมกับ Modifier.weight(weight) จะช่วยสร้างเลย์เอาต์ที่เติม/ขยายความกว้างของแถวหรือคอลัมน์ได้เมื่อจำเป็น

ตัวอย่างทั่วไปคือสำหรับชิปหรือ UI การกรอง

ชิป 5 ชิ้นใน FlowRow ซึ่งแสดงการล้นไปยังบรรทัดถัดไปเมื่อไม่มี
พื้นที่ว่างอีก
รูปที่ 1 ตัวอย่างของ FlowRow

การใช้งานพื้นฐาน

หากต้องการใช้ FlowRow หรือ FlowColumn ให้สร้าง Composable เหล่านี้และวางรายการ ไว้ภายในซึ่งควรเป็นไปตามโฟลว์มาตรฐาน

@Composable
private fun FlowRowSimpleUsageExample() {
    FlowRow(modifier = Modifier.padding(8.dp)) {
        ChipItem("Price: High to Low")
        ChipItem("Avg rating: 4+")
        ChipItem("Free breakfast")
        ChipItem("Free cancellation")
        ChipItem("£50 pn")
    }
}

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

ฟีเจอร์ของเลย์เอาต์โฟลว์

เลย์เอาต์โฟลว์มีฟีเจอร์และพร็อพเพอร์ตี้ต่อไปนี้ที่คุณใช้เพื่อ สร้างเลย์เอาต์ต่างๆ ในแอปได้

การจัดเรียงแกนหลัก: การจัดเรียงแนวนอนหรือแนวตั้ง

แกนหลักคือแกนที่จัดวางรายการ (เช่น ใน FlowRow รายการจะจัดเรียงในแนวนอน) พารามิเตอร์ horizontalArrangement ใน FlowRow จะควบคุมวิธีกระจายพื้นที่ว่างระหว่างรายการต่างๆ

ตารางต่อไปนี้แสดงตัวอย่างการตั้งค่า horizontalArrangement ในรายการ สำหรับ FlowRow

ตั้งค่าการจัดเรียงแนวนอนในวันที่ FlowRow

ผลลัพธ์

Arrangement.Start (Default)

รายการที่จัดเรียงตามเวลาเริ่มต้น

Arrangement.SpaceBetween

การจัดเรียงรายการโดยมีช่องว่างคั่น

Arrangement.Center

จัดวางไอเทมไว้ตรงกลาง

Arrangement.End

รายการที่จัดเรียงไว้ที่ท้าย

Arrangement.SpaceAround

วางสิ่งของโดยเว้นที่ว่างรอบๆ

Arrangement.spacedBy(8.dp)

รายการที่เว้นระยะห่างตาม dp ที่กำหนด

สำหรับ FlowColumn จะมีตัวเลือกที่คล้ายกันใน verticalArrangement โดยมีค่าเริ่มต้นเป็น Arrangement.Top

การจัดเรียงแกนไขว้

แกนไขว้คือแกนที่อยู่ในทิศทางตรงกันข้ามกับแกนหลัก เช่น ใน FlowRow นี่คือแกนแนวตั้ง หากต้องการเปลี่ยนวิธีจัดเรียงเนื้อหาโดยรวม ภายในคอนเทนเนอร์ในแกนไขว้ ให้ใช้ verticalArrangement สำหรับ FlowRow และ horizontalArrangement สำหรับ FlowColumn

สำหรับ FlowRow ตารางต่อไปนี้แสดงตัวอย่างการตั้งค่า verticalArrangement ที่แตกต่างกันในสินค้า

ตั้งค่าการจัดเรียงแนวตั้งใน FlowRow

ผลลัพธ์

Arrangement.Top (Default)

การจัดเรียงด้านบนของคอนเทนเนอร์

Arrangement.Bottom

การจัดวางด้านล่างของคอนเทนเนอร์

Arrangement.Center

การจัดเรียงคอนเทนเนอร์ตรงกลาง

สำหรับ FlowColumn จะมีตัวเลือกที่คล้ายกันพร้อม horizontalArrangement การจัดเรียงแกนไขว้เริ่มต้นคือ Arrangement.Start

การจัดแนวรายการแต่ละรายการ

คุณอาจต้องการจัดตำแหน่งแต่ละรายการภายในแถวด้วยการจัดแนวที่แตกต่างกัน ซึ่งแตกต่างจาก verticalArrangement และ horizontalArrangement เนื่องจากจะจัดแนวรายการภายในบรรทัดปัจจุบัน คุณสามารถ ใช้ฟีเจอร์นี้กับ Modifier.align() ได้

ตัวอย่างเช่น เมื่อรายการใน FlowRow มีความสูงแตกต่างกัน แถวจะมีความสูงเท่ากับรายการที่สูงที่สุดและใช้ Modifier.align(alignmentOption) กับรายการต่างๆ ดังนี้

ตั้งค่าการจัดแนวตั้งเป็น FlowRow

ผลลัพธ์

Alignment.Top (Default)

จัดแนวรายการชิดด้านบน

Alignment.Bottom

จัดแนวรายการชิดด้านล่าง

Alignment.CenterVertically

จัดรายการให้อยู่ตรงกลาง

สำหรับ FlowColumn ก็มีตัวเลือกที่คล้ายกัน การจัดแนวเริ่มต้นคือ Alignment.Start

จำนวนรายการสูงสุดในแถวหรือคอลัมน์

พารามิเตอร์ maxItemsInEachRow หรือ maxItemsInEachColumn จะกำหนดจำนวนสูงสุด ของรายการในแกนหลักที่อนุญาตในบรรทัดเดียวก่อนที่จะขึ้นบรรทัดใหม่ ค่าเริ่มต้นคือ Int.MAX_INT ซึ่งจะอนุญาตให้มีรายการมากที่สุดเท่าที่จะเป็นไปได้ ตราบใดที่ ขนาดของรายการนั้นๆ อนุญาตให้ใส่ในบรรทัดได้

เช่น การตั้งค่า maxItemsInEachRow จะบังคับให้เลย์เอาต์เริ่มต้นมีเพียง 3 รายการเท่านั้น

ไม่ได้ตั้งค่าสูงสุด

maxItemsInEachRow = 3

ไม่มีการตั้งค่าสูงสุดในแถวโฟลว์ จำนวนรายการสูงสุดที่ตั้งค่าในแถวโฟลว์

น้ำหนักสินค้า

Weight จะขยายรายการตามปัจจัยและพื้นที่ว่างในบรรทัดที่วางรายการนั้น สิ่งสำคัญคือ FlowRow และ Row มีความแตกต่างกันในเรื่องการใช้น้ำหนักเพื่อคำนวณความกว้างของรายการ สำหรับ Rows น้ำหนัก จะอิงตามสินค้าทั้งหมดใน Row เมื่อใช้ FlowRow น้ำหนักจะอิงตาม รายการในบรรทัดที่มีรายการอยู่ ไม่ใช่รายการทั้งหมดในคอนเทนเนอร์ FlowRow

ตัวอย่างเช่น หากคุณมีไอเทม 4 รายการที่อยู่บนบรรทัดเดียวกัน โดยแต่ละรายการมีน้ำหนัก 1f, 2f, 1f และ 3f ที่แตกต่างกัน น้ำหนักรวมคือ 7f ระบบจะหารพื้นที่ที่เหลือ ในแถวหรือคอลัมน์ด้วย 7f จากนั้น ระบบจะคำนวณความกว้างของแต่ละรายการโดยใช้ weight * (remainingSpace / totalWeight)

คุณสามารถใช้รายการ Modifier.weight และรายการสูงสุดร่วมกับ FlowRow หรือ FlowColumn เพื่อสร้างเลย์เอาต์แบบตารางได้ แนวทางนี้มีประโยชน์ในการสร้างเลย์เอาต์ที่ตอบสนองซึ่งปรับให้เข้ากับขนาดของอุปกรณ์

ตัวอย่างสิ่งที่คุณทำได้โดยใช้การถ่วงน้ำหนักมีดังนี้ ตัวอย่างหนึ่งคือตารางกริดที่รายการมีขนาดเท่ากัน ดังที่แสดงด้านล่าง

กริดที่สร้างด้วยแถวโฟลว์
รูปที่ 2 การใช้ FlowRow เพื่อสร้างตารางกริด

หากต้องการสร้างตารางที่มีขนาดรายการเท่ากัน ให้ทำดังนี้

val rows = 3
val columns = 3
FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = rows
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .weight(1f)
        .clip(RoundedCornerShape(8.dp))
        .background(MaterialColors.Blue200)
    repeat(rows * columns) {
        Spacer(modifier = itemModifier)
    }
}

สิ่งสำคัญคือ หากคุณเพิ่มรายการอื่นและทำซ้ำ 10 ครั้งแทนที่จะเป็น 9 ครั้ง รายการสุดท้ายจะใช้ทั้งคอลัมน์สุดท้าย เนื่องจากน้ำหนักรวมของทั้งแถว คือ 1f

รายการสุดท้ายขนาดเต็มในตารางกริด
รูปที่ 3 การใช้ FlowRow เพื่อสร้างตารางโดยให้รายการสุดท้ายใช้ความกว้างเต็ม

คุณสามารถรวมน้ำหนักกับ Modifiers อื่นๆ เช่น Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) หรือ Modifier.fillMaxWidth(fraction) ม็อดเหล่านี้ทั้งหมดจะทำงานร่วมกันเพื่อ อนุญาตให้ปรับขนาดรายการภายใน FlowRow (หรือ FlowColumn) ได้

นอกจากนี้ คุณยังสร้างตารางกริดสลับที่มีขนาดรายการต่างๆ ได้ด้วย โดยให้ 2 รายการใช้ความกว้างครึ่งหนึ่งของแต่ละรายการ และ 1 รายการใช้ความกว้างเต็มของคอลัมน์ถัดไป

ตารางกริดสลับที่มีแถวแบบโฟลว์
รูปที่ 4 FlowRow ที่มีขนาดแถวสลับกัน

คุณทำได้โดยใช้โค้ดต่อไปนี้

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 2
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .clip(RoundedCornerShape(8.dp))
        .background(Color.Blue)
    repeat(6) { item ->
        // if the item is the third item, don't use weight modifier, but rather fillMaxWidth
        if ((item + 1) % 3 == 0) {
            Spacer(modifier = itemModifier.fillMaxWidth())
        } else {
            Spacer(modifier = itemModifier.weight(0.5f))
        }
    }
}

การปรับขนาดเศษส่วน

การใช้ Modifier.fillMaxWidth(fraction) จะช่วยให้คุณระบุขนาดของ คอนเทนเนอร์ที่สินค้าควรใช้ได้ ซึ่งแตกต่างจากวิธีที่ Modifier.fillMaxWidth(fraction) ทำงานเมื่อใช้กับ Row หรือ Column โดยที่รายการ Row/Column จะใช้ความกว้างที่เหลือเป็นเปอร์เซ็นต์แทนที่จะใช้ความกว้างของคอนเทนเนอร์ทั้งหมด

ตัวอย่างเช่น โค้ดต่อไปนี้จะให้ผลลัพธ์ที่แตกต่างกันเมื่อใช้ FlowRow vs Row

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 3
) {
    val itemModifier = Modifier
        .clip(RoundedCornerShape(8.dp))
    Box(
        modifier = itemModifier
            .height(200.dp)
            .width(60.dp)
            .background(Color.Red)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .fillMaxWidth(0.7f)
            .background(Color.Blue)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .weight(1f)
            .background(Color.Magenta)
    )
}

FlowRow: รายการตรงกลางมีเศษส่วน 0.7 ของความกว้างของคอนเทนเนอร์ทั้งหมด

ความกว้างเศษส่วนที่มีแถวโฟลว์

Row: รายการตรงกลางใช้ความกว้าง 0.7 เปอร์เซ็นต์ของความกว้างที่เหลือ Row

ความกว้างเศษส่วนที่มีแถว

fillMaxColumnWidth() และ fillMaxRowHeight()

การใช้ Modifier.fillMaxColumnWidth() หรือ Modifier.fillMaxRowHeight() กับรายการภายใน FlowColumn หรือ FlowRow จะช่วยให้มั่นใจได้ว่ารายการในคอลัมน์หรือแถวเดียวกันจะมีความกว้างหรือความสูงเท่ากับ รายการที่ใหญ่ที่สุดในคอลัมน์/แถวนั้น

ตัวอย่างเช่น ตัวอย่างนี้ใช้ FlowColumn เพื่อแสดงรายการของหวานใน Android คุณจะเห็นความแตกต่างของความกว้างของแต่ละรายการเมื่อใช้ Modifier.fillMaxColumnWidth() กับรายการเทียบกับเมื่อไม่ได้ใช้ และรายการจะตัดคำ

FlowColumn(
    Modifier
        .padding(20.dp)
        .fillMaxHeight()
        .fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp),
    maxItemsInEachColumn = 5,
) {
    repeat(listDesserts.size) {
        Box(
            Modifier
                .fillMaxColumnWidth()
                .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp))
                .padding(8.dp)
        ) {

            Text(
                text = listDesserts[it],
                fontSize = 18.sp,
                modifier = Modifier.padding(3.dp)
            )
        }
    }
}

Modifier.fillMaxColumnWidth() ใช้กับแต่ละรายการ

fillMaxColumnWidth

ไม่ได้ตั้งค่าการเปลี่ยนแปลงความกว้าง (รายการที่ตัดข้อความ)

ไม่ได้ตั้งค่าความกว้างคอลัมน์สูงสุดแบบไม่จำกัด