用于撰写的寻呼机指示器

2024-01-13

我正在使用伴奏者的寻呼指示器。 它工作正常,但不可定制。 我想设置屏幕上应显示的确切数量的点,并且这些点的大小应在卷轴上进行配置。 有另一个问题 https://stackoverflow.com/questions/71998748/how-to-create-dot-indicator-with-color-and-size-transiton-in-jetpack-compose与此线程类似,但所有者已经接受了 AndroidView 方法,我希望它是可组合的方式。


我制作了一个看起来相似的示例,缩放逻辑是原始的,但看起来很相似。需要转换自

@OptIn(ExperimentalPagerApi::class)
@Composable
fun PagerIndicator(
    modifier: Modifier = Modifier,
    pagerState: PagerState,
    indicatorCount: Int = 5,
    indicatorSize: Dp = 16.dp,
    indicatorShape: Shape = CircleShape,
    space: Dp = 8.dp,
    activeColor: Color = Color(0xffEC407A),
    inActiveColor: Color = Color.LightGray,
    onClick: ((Int) -> Unit)? = null
) {

    val listState = rememberLazyListState()

    val totalWidth: Dp = indicatorSize * indicatorCount + space * (indicatorCount - 1)
    val widthInPx = LocalDensity.current.run { indicatorSize.toPx() }

    val currentItem by remember {
        derivedStateOf {
            pagerState.currentPage
        }
    }

    val itemCount = pagerState.pageCount

    LaunchedEffect(key1 = currentItem) {
        val viewportSize = listState.layoutInfo.viewportSize
        listState.animateScrollToItem(
            currentItem,
            (widthInPx / 2 - viewportSize.width / 2).toInt()
        )
    }


    LazyRow(
        modifier = modifier.width(totalWidth),
        state = listState,
        contentPadding = PaddingValues(vertical = space),
        horizontalArrangement = Arrangement.spacedBy(space),
        userScrollEnabled = false
    ) {

        items(itemCount) { index ->

            val isSelected = (index == currentItem)

            // Index of item in center when odd number of indicators are set
            // for 5 indicators this is 2nd indicator place
            val centerItemIndex = indicatorCount / 2

            val right1 =
                (currentItem < centerItemIndex &&
                        index >= indicatorCount - 1)

            val right2 =
                (currentItem >= centerItemIndex &&
                        index >= currentItem + centerItemIndex &&
                        index <= itemCount - centerItemIndex + 1)
            val isRightEdgeItem = right1 || right2

            // Check if this item's distance to center item is smaller than half size of
            // the indicator count when current indicator at the center or
            // when we reach the end of list. End of the list only one item is on edge
            // with 10 items and 7 indicators
            // 7-3= 4th item can be the first valid left edge item and
            val isLeftEdgeItem =
                index <= currentItem - centerItemIndex &&
                        currentItem > centerItemIndex &&
                        index < itemCount - indicatorCount + 1

            Box(
                modifier = Modifier
                    .graphicsLayer {
                        val scale = if (isSelected) {
                            1f
                        } else if (isLeftEdgeItem || isRightEdgeItem) {
                            .5f
                        } else {
                            .8f
                        }
                        scaleX = scale
                        scaleY = scale

                    }

                    .clip(indicatorShape)
                    .size(indicatorSize)
                    .background(
                        if (isSelected) activeColor else inActiveColor,
                        indicatorShape
                    )
                    .then(
                        if (onClick != null) {
                            Modifier
                                .clickable {
                                    onClick.invoke(index)
                                }
                        } else Modifier
                    )
            )
        }
    }
}

Usage

Column(
    modifier = Modifier.fillMaxSize(),
    horizontalAlignment = Alignment.CenterHorizontally
) {

    Spacer(Modifier.height(40.dp))
    val pagerState1 = rememberPagerState(initialPage = 0)
    val coroutineScope = rememberCoroutineScope()

    PagerIndicator(pagerState = pagerState1) {
        coroutineScope.launch {
            pagerState1.scrollToPage(it)
        }
    }

    HorizontalPager(
        count = 10,
        state = pagerState1,
    ) {
        Box(
            modifier = Modifier
                .padding(10.dp)
                .shadow(1.dp, RoundedCornerShape(8.dp))
                .background(Color.White)
                .fillMaxWidth()
                .height(200.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(
                "Text $it",
                fontSize = 40.sp,
                color = Color.Gray
            )
        }
    }

    val pagerState2 = rememberPagerState(initialPage = 0)

    PagerIndicator(
        pagerState = pagerState2,
        indicatorSize = 20.dp,
        indicatorCount = 7,
        activeColor = Color(0xff2196F3),
        inActiveColor = Color(0xffBBDEFB),
        indicatorShape = CutCornerShape(10.dp)
    )
    HorizontalPager(
        count = 10,
        state = pagerState2,
    ) {
        Box(
            modifier = Modifier
                .padding(10.dp)
                .shadow(1.dp, RoundedCornerShape(8.dp))
                .background(Color.White)
                .fillMaxWidth()
                .height(200.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(
                "Text $it",
                fontSize = 40.sp,
                color = Color.Gray
            )
        }
    }
}

需要转换自

listState.animateScrollToItem()

to

listState.animateScrollBy()

用于平滑指示器变化并随着寻呼机的偏移变化而移动。

并进行一些更有条理的比例、颜色和偏移计算

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于撰写的寻呼机指示器 的相关文章

随机推荐