Reputation: 45
I have two composable functions "ImageAndDescription"and "PageButtonsAndIndicator" implemented in a third composable file named "FullPage". I am using HorizontalPager in the "ImageAndDescription" composable but the problem is that even though I am setting a weight modifier for both composables in the "FullPage" file, the horizontal pager shows a level difference between each page, which leads to a very bad appearance
GIF https://jumpshare.com/s/pc4AyckmCxbqxFs7hC5Z
ImageAndDescription File
package com.example.al_jazeeranews.presentation.guide.composables
import android.content.res.Configuration
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.al_jazeeranews.presentation.guide.page.Page
import com.example.al_jazeeranews.presentation.guide.page.pages
import com.example.al_jazeeranews.presentation.utils.PaddingConstants.MEDIUM_PADDING
import com.example.al_jazeeranews.presentation.utils.PaddingConstants.NORMAL_PADDING
import com.example.al_jazeeranews.ui.theme.AlJazeeraNewsTheme
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ImageAndDescription(
modifier: Modifier = Modifier, pages: List<Page>,
pagerState: PagerState = rememberPagerState { pages.size }
) {
Column(
modifier
.fillMaxSize()
) {
HorizontalPager(state = pagerState) { pageNumber ->
PageItem(pages[pageNumber])
}
}
}
@Preview(backgroundColor = 0xFF1C1C1C, showBackground = true, uiMode = UI_MODE_NIGHT_YES)
@Preview(backgroundColor = 0xFFE7F4FD, uiMode = UI_MODE_NIGHT_NO, showBackground = true)
@Composable
fun PageItem(page: Page = pages[2]) {
AlJazeeraNewsTheme {
Column(
Modifier
.fillMaxWidth()
) {
Image(
modifier = Modifier
.fillMaxHeight(0.6f)
.fillMaxWidth(),
painter = painterResource(page.imageRes),
contentDescription = page.title,
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.height(NORMAL_PADDING))
Text(
text = page.title,
style = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onPrimary),
modifier = Modifier.padding(horizontal = MEDIUM_PADDING)
)
Spacer(modifier = Modifier.height(NORMAL_PADDING))
Text(
text = page.description,
style = MaterialTheme.typography.bodySmall.copy(color = MaterialTheme.colorScheme.onPrimary),
modifier = Modifier.padding(horizontal = MEDIUM_PADDING)
)
}
}
}
PageButtonsAndIndicator
package com.example.al_jazeeranews.presentation.guide.composables
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.al_jazeeranews.presentation.utils.PaddingConstants
import com.example.al_jazeeranews.ui.theme.AlJazeeraNewsTheme
import com.example.al_jazeeranews.ui.theme.SelectedBlue
import com.example.al_jazeeranews.ui.theme.UnselectedGrey
import com.example.al_jazeeranews.ui.theme.White
@Preview(showBackground = true)
@Composable
fun PageButtonsAndIndicator(
modifier: Modifier,
buttonsString: List<String> = listOf("Back", "Next"),
numberOfPages: Int = 3,
currentPage: Int = 1,
onBackClick: () -> Unit = {},
onNextClick: () -> Unit = {}
) {
AlJazeeraNewsTheme {
Row(
modifier
.fillMaxSize()
.padding(PaddingConstants.MEDIUM_PADDING)
.padding(bottom = PaddingConstants.NORMAL_PADDING),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
repeat(numberOfPages) { index ->
Box(
Modifier
.size(8.dp)
.clip(CircleShape)
.background(
color = if (index == currentPage) SelectedBlue
else UnselectedGrey
)
)
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
if (currentPage != 0) {
TextButton(onClick = onBackClick ) {
Text(
text = buttonsString[0],
style = MaterialTheme.typography.bodySmall.copy(
color = UnselectedGrey, fontWeight = FontWeight.SemiBold
)
)
}
}
Button(
onClick = onNextClick,
shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors(
contentColor = White,
containerColor = SelectedBlue
)
) {
Text(text = buttonsString[1], style = MaterialTheme.typography.bodySmall)
}
}
}
}
}
FullPage File
package com.example.al_jazeeranews.presentation.guide.composables
import android.annotation.SuppressLint
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.al_jazeeranews.presentation.guide.page.pages
import kotlinx.coroutines.launch
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalFoundationApi::class)
@Preview
@Composable
fun FullPage(modifier: Modifier = Modifier) {
Column(
Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.background)
) {
val pagerState = rememberPagerState { pages.size }
Column(Modifier.weight(0.8f)) {
ImageAndDescription(
pages = pages,
pagerState = pagerState,
modifier = Modifier.weight(8f)
)
}
val buttonsString by derivedStateOf {
when {
pagerState.currentPage == 0 -> listOf("", "Next")
pagerState.currentPage < pages.size - 1 -> listOf("Back", "Next")
pagerState.currentPage == pages.size - 1 -> listOf("Back", "Get Started")
else -> listOf("", "")
}
}
val coroutineScope = rememberCoroutineScope()
Column(Modifier.weight(0.2f)) {
PageButtonsAndIndicator(
Modifier,
buttonsString,
pages.size,
pagerState.currentPage,
{
coroutineScope.launch {
pagerState.animateScrollToPage(pagerState.currentPage - 1)
}
},
{
coroutineScope.launch {
if (pagerState.currentPage != pages.size - 1)
pagerState.animateScrollToPage(pagerState.currentPage + 1)
}
}
)
}
}
}
Upvotes: 1
Views: 71
Reputation: 45
I actually discovered the problem, it was in the PageItem in the Image and Description file
fun PageItem(page: Page = pages[2]) {
AlJazeeraNewsTheme {
Column(
Modifier
.fillMaxWidth()
.fillMaxHeight() //I should've added that to fill the maximum
//specified size
)
Upvotes: 0