เลย์เอาต์โฟลว์ใน 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

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

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

น้ำหนักจะขยายรายการตามปัจจัยและพื้นที่ว่างในบรรทัดที่วางรายการนั้น สิ่งสำคัญคือ 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

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

ไม่ได้ตั้งค่าความกว้างคอลัมน์สูงสุดแบบไม่แสดงโฆษณา