pie
pie

Reputation: 163

Recomposition HorizontalPageIndicator

There is a HorizontalPager and a HorizontalPageIndicator. When swiping, there are 3 recompositions of the HorizontalPageIndicator. Is this normal, or did I write the code incorrectly?

@Composable
fun HouseholdScreen(
    isLoading: Boolean,
    households: List<Household>,
    clickOnDevice: (id: String) -> Unit
) {
    val pagerState = rememberPagerState { households.size }

    val pageIndicatorState = remember {
        derivedStateOf {
            object : PageIndicatorState {
                override val pageCount: Int
                    get() = pagerState.pageCount
                override val pageOffset: Float
                    get() = pagerState.currentPageOffsetFraction
                override val selectedPage: Int
                    get() = pagerState.currentPage

            }
        }
    }

    HorizontalPager(
        state = pagerState,
        key = { households[it].id }
    ) {
        HouseholdScreen(
            isLoading = isLoading,
            household = households[it]
        ) {
            clickOnDevice(it)
        }
    }

    HorizontalPageIndicator(
        pageIndicatorState = pageIndicatorState.value,
        modifier = Modifier.padding(4.dp)
    )
}

Before:

enter image description here

After 1 swipe:

enter image description here

Upvotes: 0

Views: 41

Answers (1)

pie
pie

Reputation: 163

As it turns out, Horologist has an implementation of PageScreenIndicatorState, which serves as a bridge between PagerState and PageIndicatorState. It implements the following method:

public class PageScreenIndicatorState(
    private val state: PagerState,
) : PageIndicatorState {
    override val pageCount: Int
        get() = state.pageCount

    override val pageOffset: Float
        get() = state.currentPageOffsetFraction.takeIf { it.isFinite() } ?: 0f

    override val selectedPage: Int
        get() = state.currentPage
}

Result:

@Composable
fun HouseholdScreen(
    isLoading: Boolean,
    households: List<Household>,
    clickOnDevice: (id: String) -> Unit
) {
    val pagerState = rememberPagerState { households.size }

    PagerScreen(
        state = pagerState,
        key = { households[it].id }
    ) {
        HouseholdScreen(
            isLoading = isLoading,
            household = households[it]
        ) {
            clickOnDevice(it)
        }
    }

    PageScreenIndicatorState(state = pagerState)
}

Upvotes: 0

Related Questions