一、起因:

在开发Android TV,有个场景需要使用TvLazyColum 嵌套 TvLazyVerticalGrid。需要判断焦点,然后滑动到指定位置并改变背景图片实现高斯模糊效果。直接嵌套会运行会报 IllegalStateException异常。

异常如下:

java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity
maximum height constraints, which is disallowed. One of the common reasons is nesting layouts 
like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the 
list of items please add a header as a separate item() before the main items() inside the LazyColumn 
scope. There are could be other reasons for this to happen: your ComposeView was added into a 
LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) 
or wrote a custom layout. Please try to remove the source of infinite constraints in 
the hierarchy above the scrolling container.

二、根据异常提示2种修复方式。(都不能解决)

2.1 第一种修复方式:在Modifier.wrapContentSize(unbounded=true)

2.2 第二种修复方式: TvLazyColum添加了(Modifier.verticalScroll()

三、自定义view修复

代码如下 : 

package com.trim.tv.ui.components

import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.animateScrollBy
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.tv.foundation.lazy.grid.TvGridCells
import androidx.tv.foundation.lazy.grid.TvLazyGridScope
import androidx.tv.foundation.lazy.grid.TvLazyGridState
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
import androidx.tv.foundation.lazy.grid.rememberTvLazyGridState
import androidx.tv.foundation.lazy.list.TvLazyColumn
import androidx.tv.foundation.lazy.list.TvLazyListScope
import androidx.tv.foundation.lazy.list.TvLazyListState
import androidx.tv.foundation.lazy.list.rememberTvLazyListState
import kotlinx.coroutines.launch

/**
 * @author 小强
 *
 * @time 2023/11/21  11:57
 *
 * @desc TvLazyColumn 嵌套 TvLazyGrid
 *
 *
 * @param modifier Modifier  调节器
 * @param topState TvLazyListState 顶部视图状态
 * @param bottomState TvLazyGridState 底部视图状态
 * @param fixedCount Int 网格一行展示几个
 * @param contentPadding PaddingValues  网格间距
 * @param horizontalArrangement Arrangement.Horizontal  网格横向item间距
 * @param verticalArrangement Arrangement.Vertical  网格众向item间距
 * @param topContent TvLazyListScope.() -> Unit  顶部视图
 * @param bottomContent TvLazyGridScope.() -> Unit 底部状态
 */

@Composable
fun NestedTvLazyColumnGrid(
    modifier: Modifier = Modifier,
    topState: TvLazyListState = rememberTvLazyListState(),
    bottomState: TvLazyGridState = rememberTvLazyGridState(),
    fixedCount: Int = 6,
    contentPadding: PaddingValues = PaddingValues(0.dp),
    horizontalArrangement: Arrangement.Horizontal = Arrangement.spacedBy(40.dp),
    verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(52.dp),
    topContent: TvLazyListScope.() -> Unit,
    bottomContent: TvLazyGridScope.() -> Unit,
) {
    val scope = rememberCoroutineScope()
    val innerFirstVisibleItemIndex by remember {
        derivedStateOf {
            bottomState.firstVisibleItemIndex
        }
    }


    BoxWithConstraints(
        modifier = modifier.scrollable(
            state = rememberScrollableState {
                scope.launch {
                    val toDown = it <= 0
                    if (toDown) {
                        if (topState.run { firstVisibleItemIndex == layoutInfo.totalItemsCount - 1 }) {
                            bottomState.scrollBy(-it)
                        } else {
                            topState.scrollBy(-it)
                        }
                    } else {
                        if (innerFirstVisibleItemIndex == 0 && bottomState.firstVisibleItemScrollOffset == 0) {
                            topState.scrollBy(-it)
                        } else {
                            bottomState.scrollBy(-it)
                        }
                    }
                }
                it
            },
            Orientation.Vertical,
        )
    ) {
        TvLazyColumn(
            userScrollEnabled = false, state = topState, modifier = Modifier.heightIn(maxHeight)
        ) {

            // 顶部内容
            topContent()

            // 底部内容
            item {
                TvLazyVerticalGrid(
                    columns = TvGridCells.Fixed(fixedCount),
                    state = bottomState,
                    userScrollEnabled = false,
                    modifier = Modifier.height(maxHeight),
                    contentPadding = contentPadding,
                    horizontalArrangement = horizontalArrangement,
                    verticalArrangement = verticalArrangement
                ) {
                    bottomContent()
                }
            }
        }

    }
}

解决后的效果如下:

GitHub 加速计划 / compose / compose
33.27 K
5.15 K
下载
compose - Docker Compose是一个用于定义和运行多容器Docker应用程序的工具,通过Compose文件格式简化应用部署过程。
最近提交(Master分支:2 个月前 )
501b5acd Add `jhrotko` to Core Maintainers. Signed-off-by: Laura Brehm <laurabrehm@hey.com> 9 天前
f51bc4cd Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com> 9 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐