Home > front end >  Preparing a button to be reused multiple times in different screens
Preparing a button to be reused multiple times in different screens

Time:11-22

I have a reusable layout containing a LazyColumn and a button to scroll to the top of the LazyColumn. What is the most efficient way to declare my button (and make sure the click event works) so that I don't have to decalre it every time I create a new screen?

@Composable
fun MyReusableScaffold(scaffoldTitle: String, scaffoldContent: @Composable () -> Unit) {
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()

    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            LargeTopAppBar(
                title = { Text(text = scaffoldTitle) },
                scrollBehavior = scrollBehavior
            )
        },
        content = { contentPadding ->
            scaffoldContent(contentPadding = contentPadding)
        }
    )
}

@Composable
fun MyScreen(navController: NavController) {
    MyReusableScaffold(
        scaffoldTitle = "Hello Android",
        scaffoldContent = {
            MyScreenContent(contentPadding = it)
        }
    )
}

@Composable
fun MyScreenContent(modifier: Modifier = Modifier,
    contentPadding: PaddingValues = PaddingValues()) {
LazyColumn(
state = listState,
contentPadding = contentPadding,
    ) {
        items(22) {
            ListItem(it)
        }
    }

val showButton by remember {
    derivedStateOf {
        listState.firstVisibleItemIndex > 0
    }
}

AnimatedVisibility(
    visible = showButton,
    enter = fadeIn(),
    exit = fadeOut(),
    modifier = Modifier.align(BottomCenter)
) {
    ScrollToTopButton(onClick = {
        coroutineScope.launch {
            listState.animateScrollToItem(index = 0)
        }
    })
}
}

@Composable
fun ScrollToTopButton(onClick: () -> Unit) {
    Box(
        Modifier
            .fillMaxSize()
    ) {
        Button(
            onClick = { onClick() }
        ) {
            Text(text = stringResource(id = R.string.top))
        }
    }
}

CodePudding user response:

You can move all the logic inside the ScrollToTopButton.

Something like:

@Composable
fun ScrollToTopButton(
    modifier : Modifier = Modifier,
    listState : LazyListState) {

    val coroutineScope = rememberCoroutineScope()

    val showButton by remember {
        derivedStateOf {
            listState.firstVisibleItemIndex > 0
        }
    }

    AnimatedVisibility(
        visible = showButton,
        enter = fadeIn(),
        exit = fadeOut(),
    ) {

        Box(
            modifier
        ) {
            Button(
                onClick = {
                    coroutineScope.launch {
                        listState.animateScrollToItem(index = 0)
                    }
                }

            ) {
                Text(text = "Top")
            }
        }
    }
}

and then use in all screens with:

val listState = rememberLazyListState()

LazyColumn(
    state = listState,
    contentPadding = contentPadding,
) {
    items(100) {
        androidx.compose.material.Text(""   it)
    }
}

ScrollToTopButton(
    listState = listState
)
  • Related