我想创建一个带有图表的视图,可以左右滚动(从右开始).我已经使用LazyRow完成了这项工作,并将verseLayout设置为真.

val scrollState = rememberLazyListState(0)

LazyRow(
    reverseLayout = true,
    state = scrollState
) {
    items(charts) {data ->
        ChartBar()
    }
}

我的图表是可交换的,并且显示正确.

我的问题是,我需要在保持水平填充的同时,始终在屏幕宽度上显示7个条.我不确定该如何计算.

第二个问题是,在滑动后,检测到新的条形图何时比以前的条形图更高,然后触发操作.我也不知道该怎么做.

Do I need to use Layout() and Measurables for this? enter image description here

推荐答案

您可以使用以下命令设置项目宽度

val padding = 12.dp
val itemCount = 7
val screenWidthDp = LocalConfiguration.current.screenWidthDp
val itemWidth = (screenWidthDp - (itemCount + 1) * padding.value) / itemCount

或者,您可以用BoxWithConstraints来包装LazyRow,并获得MaxWidh参数,而不是LocalConfiguration.current.screenWidthDp,然后以相同的方式apply.

要获得最高的项目,您需要提供有关ChartBar如何构造的更多信息.如果它们是不同高度的物品,你可以这样做.

@Preview
@Composable
private fun ChartTest() {

    val charts = remember {
        List(50) {
            Random.nextInt(40, 500)
        }
    }

    val padding = 12.dp
    val itemCount = 7
    val scrollState = rememberLazyListState(0)

    scrollState.layoutInfo.visibleItemsInfo

    var tallestItem by remember {
        mutableStateOf(0)
    }

    var currentMaxHeight by remember {
        mutableStateOf(0)
    }

    val context = LocalContext.current

    LaunchedEffect(tallestItem) {
        if (tallestItem > currentMaxHeight) {
            currentMaxHeight = tallestItem
            Toast.makeText(context, "Tallest item $tallestItem", Toast.LENGTH_SHORT).show()
        }
    }

    val screenWidthDp = LocalConfiguration.current.screenWidthDp
    val itemWidth = (screenWidthDp - (itemCount + 1) * padding.value) / itemCount
    LazyRow(
        contentPadding = PaddingValues(horizontal = padding),
        modifier = Modifier.fillMaxWidth()
            .border(2.dp, Color.Red)
            .onPlaced {
                val newHeight = it.size.height
                if (newHeight > tallestItem) {
                    tallestItem = newHeight
                }

                if (currentMaxHeight == 0) {
                    currentMaxHeight = newHeight
                }
            },
        reverseLayout = true,
        horizontalArrangement = Arrangement.spacedBy(padding),
        state = scrollState
    ) {

        itemsIndexed(charts) { index, data ->
            ChartBar(
                modifier = Modifier.width(itemWidth.dp).height(charts[index].dp)
            )
        }
    }
}

@Composable
private fun ChartBar(
    modifier: Modifier
) {
    Box(modifier.background(Color.Green, RoundedCornerShape(16.dp)))
}

如果它们包含有多高的数据,您可以使用 scrollState.layoutInfo.visibleItemsInfo

这可以通过以下方式完成

enter image description here

@Preview
@Composable
private fun ChartTest2() {

    BoxWithConstraints(
        modifier = Modifier.height(400.dp)
    ) {

        val context = LocalContext.current
        val density = LocalDensity.current

        val charts = remember {
            List(50) {
                Random.nextInt(40, 400)
            }
        }

        val padding = 24.dp
        val itemCount = 7
        val itemWidth = (maxWidth.value - (itemCount + 1) * padding.value) / itemCount

        val scrollState = rememberLazyListState(0)

        var currentMaxHeight by remember {
            mutableStateOf(0)
        }

        val tallestItem by remember {
            derivedStateOf {
                val visibleItemsInfo = scrollState.layoutInfo.visibleItemsInfo
                var maxHeight = 0
                if (visibleItemsInfo.isNotEmpty()) {
                    visibleItemsInfo.forEach {
                        val index = it.index
                        maxHeight = charts[index].coerceAtLeast(maxHeight)
                    }
                }

                if (currentMaxHeight == 0) {
                    currentMaxHeight = (maxHeight * density.density).toInt()
                }
                (maxHeight * density.density).toInt()
            }
        }

        LaunchedEffect(tallestItem) {
            if (tallestItem > currentMaxHeight) {
                currentMaxHeight = tallestItem
                Toast.makeText(context, "Tallest item $tallestItem", Toast.LENGTH_SHORT).show()
            }
        }

        LazyRow(
            contentPadding = PaddingValues(horizontal = padding),
            modifier = Modifier.fillMaxSize()
                .border(2.dp, Color.Red),
            reverseLayout = true,
            horizontalArrangement = Arrangement.spacedBy(padding),
            state = scrollState
        ) {

            itemsIndexed(charts) { index, data ->
                ChartBar(
                    modifier = Modifier.width(itemWidth.dp).fillMaxHeight(),
                    barHeight = charts[index].dp
                )
            }
        }

    }

}

@Composable
private fun ChartBar(
    modifier: Modifier,
    barHeight: Dp
) {
    Column(modifier) {
        Spacer(modifier = Modifier.weight(1f))
        Box(
            Modifier.fillMaxWidth().height(barHeight)
                .background(Color.Green, RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp))
        )
    }
}

Android相关问答推荐

无法安装后重新编译android代码'

约束布局:垂直链中的视图应将内容包裹到空间的1/3

无法在Android Gradle中同步Chaquopy版本

Android事件:APP_SCOUT_HANG警告SQLite

如何在Android Jetpack Compose中找到我的手机屏幕一行有多少个单词

Android Compose Pages 3-一次加载所有页面,无需在LazyColumn中滚动,无需网络调用和内部滚动

从片段导航回来

Android 中 recyclerview 的自定义分隔线 colored颜色 不起作用

从包含的(复合)模块导入 Kotlin 类时,Android 应用程序模块的 build.gradle.kts 未解决的引用错误

如何使用react native下载android中/data/data/[应用程序包名称文件夹]/files中的文件

面向Jetpack Compose的可组合放置问题

Android - 如何使 TextInputEditText 的高度恰好为 2 行?

如何绘制内边框?

如何在 Jetpack Compose 中向图像视图添加对角色带?

从活动共享视图模型以使用 hilt 组合函数

导航组件中预期的函数调用map(...)

如何在 Android 应用中录制短视频?

如何在 Android 上移动 EditText 上的图标?

Jetpack Compose:mutableStateOf 不随流量更新

在 Android 10 (API 29) 中隐藏状态栏并在应用程序中使用其空间