3

I've been trying to align a button in Column from the bottom to the center for a while, but I couldn't succeed.

hear is my code:

NutritionHabitsScreen

@Composable
fun NutritionHabitsRoute(
    navHostController: NavHostController,
    sharedViewModel: SharedViewModel,
    viewModel: NutritionHabitsViewModel = hiltViewModel()
) {

    val state by viewModel.state.collectAsState()

    NutritionHabit(
        navHostController = navHostController,
        sharedViewModel = sharedViewModel,
        state = state,
        buttonEnabled = viewModel::buttonEnabled
    )
}

@Composable
fun NutritionHabit(
    navHostController: NavHostController,
    sharedViewModel: SharedViewModel,
    state: NutritionHabitsScreenState,
    buttonEnabled: (MutableList<Int>, MutableList<Int>) -> Unit
) {


    val firstChoicesItems = sharedViewModel.registerItems?.choices?.get(0)?.items
    val secondChoicesItems = sharedViewModel.registerItems?.choices?.get(1)?.items

    var firstSelectedIndexes = remember { mutableListOf<Int>() }
    var secondSelectedIndexes = remember { mutableListOf<Int>() }

    Scaffold(
        topBar = { BackPopUp(navController = navHostController, route = null) },
        backgroundColor = Color.Transparent
    ) {

        Column(
            modifier = Modifier
                .fillMaxSize()
                .verticalScroll(rememberScrollState())
        ) {

            CustomText(
                padding = 15.dp,
                text = sharedViewModel.registerItems!!.choices[0].title ?: "",
                textStyle = MaterialTheme.typography.h3
            )

            firstChoicesItems?.let {
                it.forEachIndexed { index, element ->
                    CustomButton(
                        selectedIndexes = firstSelectedIndexes,
                        index = index,
                        borderDp = 2.dp,
                        textPadding = 15.dp,
                        topPadding = 5.dp,
                        bottomPadding = 5.dp,
                        startPadding = 15.dp,
                        endPadding = 15.dp,
                        text = firstChoicesItems[index].key ?: "",
                        selectedBorderColor = DefaultDYTColor,
                        unselectedBorderColor = MaterialTheme.colors.grayColor,
                        onSelected = { list ->
                            firstSelectedIndexes = list
                            buttonEnabled(firstSelectedIndexes, secondSelectedIndexes)
                        }
                    )
                }
            }
            
            CustomText(
                padding = 15.dp,
                text = sharedViewModel.registerItems!!.choices[1].title ?: "",
                textStyle = MaterialTheme.typography.h3
            )

            secondChoicesItems?.let {
                it.forEachIndexed { index, items ->
                    CustomButton(
                        selectedIndexes = secondSelectedIndexes,
                        index = index,
                        borderDp = 2.dp,
                        textPadding = 15.dp,
                        topPadding = 5.dp,
                        bottomPadding = 5.dp,
                        startPadding = 15.dp,
                        endPadding = 15.dp,
                        text = secondChoicesItems[index].key ?: "",
                        selectedBorderColor = DefaultDYTColor,
                        unselectedBorderColor = MaterialTheme.colors.grayColor,
                        onSelected = { list ->
                            secondSelectedIndexes = list
                            buttonEnabled(firstSelectedIndexes, secondSelectedIndexes)
                        }
                    )
                }
            }

            DYTLoginAndContinueButton(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp),
                text = stringResource(id = R.string.devam),
                navController = navHostController,
                route = null,
                enabled = state.buttonEnabled
            ) {}
        }
    }
}

My Custom button

@Composable
fun DYTLoginAndContinueButton(
    modifier:Modifier,
    text: String,
    navController: NavController?,
    route: String?,
    enabled: Boolean,
    onClick: () -> Unit
) {

    Button(
        onClick = {
            onClick()
            if(navController != null && route !=null)
                navController.navigate(route)
        },
        modifier = modifier,
        enabled = enabled,
        elevation = ButtonDefaults.elevation(0.dp, 0.dp),
        colors = ButtonDefaults.buttonColors(backgroundColor = DefaultDYTColor),
        shape = RoundedCornerShape(25.dp)
    ) {
        Text(
            modifier = Modifier.padding(8.dp),
            text = text,
            textAlign = TextAlign.Center,
            style = MaterialTheme.typography.button,
            color = Color.White
        )
    }
}

As you can see, there are multiple components in the column and there is a custom button I created at the bottom DYTLoginAndContinueButton, I want to align it to the bottom center of the screen. I tried some things and it happened when I succeeded, but for some reason the button was not visible on small screens, I couldn't understand why. This is the latest version of my code. At the moment, it does not appear aligned in the center at the bottom of the screen on large screens, and on small screens, it seems to be localized to the very end because the screen is already small. I want it to appear properly in the center at the bottom of the screen on both small screens and large screens. Anyone have a suggestion?

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
NewPartizal
  • 604
  • 4
  • 18

2 Answers2

3

You have to use something different. You can't put the Button in the Column with a verticalScroll. Move the Button outside the Column and just apply a weight modifier to the same Column.

Something like:

    Column(
        Modifier.fillMaxHeight(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {

        Column(
            modifier = Modifier
                .verticalScroll(rememberScrollState())
                .weight(1f, false)
        ) {
            //...
        }

        Button(
            onClick = {},
            modifier = Modifier
                .padding(vertical = 2.dp)
                .fillMaxWidth()
        ) {
            Text("Button")
        }
    }

}

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • 1
    okey thanks it works @Gabriele Moriotti. I did not examine very carefully your answer. I am sorry my previous comment. it was my mistake , I deleted. I will accept your answer. – NewPartizal Apr 28 '23 at 10:45
1

Adding

 Spacer(modifier = Modifier.weight(1f))

in the column above the DYTLoginAndContinueButton will make the button go to the bottom of the screen on large screen. The issue with it not being visible on the smaller screens is probably that the firstChoicesItem and secondChoicesItem fill most of the screen and to see the button you have to scroll down. If you want it aligned at the bottom without scrolling, you could do something like.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NutritionHabit(
) {

    Scaffold(
        topBar = { },
    ) { it->
        Box(modifier=Modifier.fillMaxSize()){
            Column(
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .padding(it)
                    .fillMaxSize()
                    .verticalScroll(rememberScrollState())
            ) { 
                // column content goes here
                
            }
            
            DYTLoginAndContinueButton(
                modifier = Modifier
                    .align(Alignment.BottomCenter)
                    .fillMaxWidth()
                    .padding(16.dp),
                text ="Button",
                route = null,
                enabled = true, navController = null) {}
        }


    }
} 
  • thanks for answer it works but there is a problem when I try in small emulator. For example On the small screens, the texts of the button and the column overlap and the texts are not visible. – NewPartizal Apr 27 '23 at 15:15
  • by the way where should I put the Spacer that you declare above – NewPartizal Apr 27 '23 at 15:35
  • Spacer(modifier = Modifier.weight(1f)) should be inside the column above the DYTLoginAndContinueButton composable as it fills all the empty space above it and places the DYTLoginAndContinueButton on the bottom, however if the lists are to long there may be some issues with that. – Adam Pałkowski Apr 27 '23 at 15:45