commonMain.com.arkivanov.decompose.extensions.compose.pages.ChildPages.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of extensions-compose Show documentation
Show all versions of extensions-compose Show documentation
Kotlin Multiplatform lifecycle-aware business logic components
The newest version!
package com.arkivanov.decompose.extensions.compose.pages
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerScope
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.VerticalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.Child
import com.arkivanov.decompose.Ref
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.keyHashString
import com.arkivanov.decompose.router.pages.ChildPages
import com.arkivanov.decompose.value.Value
/**
* Displays a list of pages represented by [ChildPages].
*/
@Composable
fun ChildPages(
pages: Value>,
onPageSelected: (index: Int) -> Unit,
modifier: Modifier = Modifier,
scrollAnimation: PagesScrollAnimation = PagesScrollAnimation.Disabled,
pager: Pager = defaultHorizontalPager(),
key: (Child) -> Any = Child<*, *>::keyHashString,
pageContent: @Composable PagerScope.(index: Int, page: T) -> Unit,
) {
val state by pages.subscribeAsState()
ChildPages(
pages = state,
onPageSelected = onPageSelected,
modifier = modifier,
scrollAnimation = scrollAnimation,
pager = pager,
key = key,
pageContent = pageContent,
)
}
/**
* Displays a list of pages represented by [ChildPages].
*/
@Composable
fun ChildPages(
pages: ChildPages,
onPageSelected: (index: Int) -> Unit,
modifier: Modifier = Modifier,
scrollAnimation: PagesScrollAnimation = PagesScrollAnimation.Disabled,
pager: Pager = defaultHorizontalPager(),
key: (Child) -> Any = Child<*, *>::keyHashString,
pageContent: @Composable PagerScope.(index: Int, page: T) -> Unit,
) {
val selectedIndex = pages.selectedIndex
val state = rememberPagerState(
initialPage = selectedIndex,
pageCount = { pages.items.size },
)
LaunchedEffect(selectedIndex) {
if (state.currentPage != selectedIndex) {
when (scrollAnimation) {
is PagesScrollAnimation.Disabled -> state.scrollToPage(selectedIndex)
is PagesScrollAnimation.Default -> state.animateScrollToPage(page = selectedIndex)
is PagesScrollAnimation.Custom -> state.animateScrollToPage(page = selectedIndex, animationSpec = scrollAnimation.spec)
}
}
}
DisposableEffect(state.currentPage, state.targetPage) {
if (state.currentPage == state.targetPage) {
onPageSelected(state.currentPage)
}
onDispose {}
}
pager(
modifier,
state,
{ key(pages.items[it]) },
) { pageIndex ->
val item = pages.items[pageIndex]
val pageRef = remember(item.key) { Ref(item.instance) }
if (item.instance != null) {
pageRef.value = item.instance
}
val page = pageRef.value
if (page != null) {
pageContent(pageIndex, page)
}
}
}
fun defaultHorizontalPager(): Pager =
{ modifier, state, key, pageContent ->
HorizontalPager(
modifier = modifier,
state = state,
key = key,
pageContent = pageContent,
)
}
fun defaultVerticalPager(): Pager =
{ modifier, state, key, pageContent ->
VerticalPager(
modifier = modifier,
state = state,
key = key,
pageContent = pageContent,
)
}
internal typealias Pager =
@Composable (
Modifier,
PagerState,
key: (index: Int) -> Any,
pageContent: @Composable PagerScope.(index: Int) -> Unit,
) -> Unit
© 2015 - 2024 Weber Informatics LLC | Privacy Policy