iT邦幫忙

2022 iThome 鐵人賽

DAY 16
2

前言


昨天講解了 Grid Layout 的基本用法,今天來講最後一個參數 content 的 LazyGridScope 是什麼。

Scope


Layout 佈局分為 Column 、Row 、Grid,這類排列的 Composable 最後一行的參數content 可以擺入要呈現的 composable。可以觀察到預設值都是 content: xxxScope.() -> Unit 的形式,不像其他 Compose 是content: () -> Unit

Scope 的名稱會對應 Composable 的名,例如 Column 的 Scope 就是ColumnScope ,LazyColumn 是LazyListScope ,而 LazyVerticalGrid 就是 LazyGridScope

在 Column 、Row 、Grid 前面加上 Lazy,效果就是以前的 RecyclerView 。Lazy 系列的 Scope 的特點在於,不能直接在 content ={ } 中使用 composable 而是要在DSL 定義的方法內部使用,像是 item()items() 等。

關鍵術語:DSL 是 domain-specific language 的縮寫,翻譯成特定領域的語言,也就是block範圍內能使用定義好的function、參數等等。

這裡先舉例 LazyColumn 的DSL function

@Preview(showBackground = true)
@Composable
fun LazyColumnDSL() {

    val intList: List<Int> = listOf(1, 2, 3)

    LazyColumn {
        // 新增1列
        item {
            Text(text = "First item")
        }

        // 新增5列
        items(5) { index ->
            Text(text = "items 5: item =$index")
        }

        // 傳入 list 或 array
        items(intList) { int ->
            Text(text = "items list : item = $int")
        }

        // 傳入 list 或 array 並帶有 index 值
        itemsIndexed(intList) { index, int ->
            Text(text = "items index list : index= $index: item = $int")
        }
    }
}

https://ithelp.ithome.com.tw/upload/images/20220922/20136048T8W3Rg8USf.png

Grid Layout 的 scope 和 column 一樣也可以用 itemitems(i)items(List)items(Array)itemsIndexed(*List*)itemsIndexed(*Array*)

item 想橫跨多欄時


Grid Layout 可以很好的計算每一行有多少 items ,但有時候想另外插一行行跨多個欄位的 item 要怎麼做呢?

LazyGridScopeitem() 參數 span 可以做到跨行效果。

fun item(
    key: Any? = null,
    span: (LazyGridItemSpanScope.() -> GridItemSpan)? = null,
    contentType: Any? = null,
    content: @Composable LazyGridItemScope.() -> Unit
)

span = {} 中使用 GridItemSpan(int) 可以單獨計算出該item要行跨多少欄位。

  • int : 1代表佔用1欄位,數字大於最大欄數效果等同最大欄數 maxLineSpan
  • this.maxLineSpan : 最大欄數
  • this.maxCurrentLineSpan : 剩餘最大欄數
GridItemSpan(3) GridItemSpan(this.maxLineSpan) GridItemSpan(this.maxCurrentLineSpan)
https://ithelp.ithome.com.tw/upload/images/20220922/20136048BZxDzvmMl7.png https://ithelp.ithome.com.tw/upload/images/20220922/20136048F2bVItoK97.png https://ithelp.ithome.com.tw/upload/images/20220922/20136048UyOuqJEzaK.png
@Preview
@Composable
fun GridLayout() {

    val list = (1..9).map { it.toString() }

    LazyVerticalGrid(
        //...
        content = {
						//單一個item
						item() {
                Card(
                   //...
                ) {
	                    //...
                }
            }

						// span item
            item(span = { GridItemSpan(this.maxLineSpan) }) {
                Card(
                    modifier = Modifier
                        .padding(4.dp)
                        .fillMaxWidth()
                ) {
                    Text(
                        text = "Span",
                        fontWeight = FontWeight.Bold,
                        fontSize = 30.sp,
                        textAlign = TextAlign.Center,
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
						// list items
            items(list.size) { index ->
							//...
            }
        }
    )
}

總結


今天介紹了 content 如何使用 Scope,以及專有名詞DSL。
在 grid layout 橫跨多欄可以運用 Span 參數。

參考


Grid中文資源
LazyGrid官方介紹

今日運動
休息


上一篇
Day 15 Lazy Grid Layout
下一篇
Day 17 實作 Grid Layout 和 Card
系列文
今年一定減成功!Jetpack Compose 做出重訓紀錄APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
John Lu
iT邦新手 4 級 ‧ 2022-09-22 23:06:27

實用~實用!

我要留言

立即登入留言