Thursday, April 1, 2021

jetpack compose - LazyColumn smooth scrolling

MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.*

class MainActivity : AppCompatActivity() {
    @ExperimentalAnimationApi
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MainContent()
        }
    }


    @ExperimentalAnimationApi
    @Composable
    fun MainContent(){
        val list = (1..100).map { it.toString() }
        val listState = rememberLazyListState()
        val coroutineScope = rememberCoroutineScope()

        Box(
            modifier = Modifier.fillMaxSize()
        ) {
            LazyColumn(
                state = listState,
                modifier = Modifier
                    .background(Color(0xFFFFFFFF))
                    .wrapContentHeight()
                    .fillMaxWidth(),
                contentPadding = PaddingValues(12.dp),
                verticalArrangement = Arrangement.spacedBy(8.dp)
            ) {
                items(list){ txt ->
                    Card(
                        backgroundColor = Color(0xFFFE4164),
                        modifier = Modifier
                            .fillMaxWidth(),
                        elevation = 8.dp,
                        shape = RoundedCornerShape(16.dp)
                    ) {
                        Text(
                            text = txt,
                            fontWeight = FontWeight.Bold,
                            fontSize = 40.sp,
                            fontFamily = FontFamily.Cursive,
                            color = Color(0xFFFFFFFF),
                            textAlign = TextAlign.Center,
                            modifier = Modifier.padding(16.dp)
                        )
                    }
                }
            }

            val isFabVisible  = remember {
                derivedStateOf {
                    listState.firstVisibleItemIndex > 0
                }
            }

            Box(
                Modifier.align(Alignment.BottomEnd)
            ) {
                AnimatedVisibility(visible = isFabVisible.value) {
                    FloatingActionButton(
                        onClick = {
                            coroutineScope.launch {
                                listState.animateScrollToItem(0)
                            }
                        },
                        shape = RoundedCornerShape(50),
                        backgroundColor = Color(0xFF43302E),
                        modifier = Modifier.padding(16.dp),
                    ) {
                        Icon(
                            Icons.Filled.ArrowUpward,
                            "",
                            tint = Color.White
                        )
                    }
                }
            }
        }
    }


    @Preview
    @Composable
    fun ComposablePreview(){
        //MainContent()
    }
}