i have an issue in placing ConstraintLayout as Row's Child (Compose Version : 1.1.1). when set the height of Row to IntrinsicSize.Min, the content of ConstraintLayout gets corrupted, ie it's width gets narrow and all children are placed in that narrow width.
here's the code
Row(modifier = Modifier.height(IntrinsicSize.Min) ) {
ConstraintLayout(modifier = Modifier){
.
.
.
}
}
and here are screenshots
before putting inside Box:
after :
here's ConstraintLayout Content:
Surface(
modifier = modifier,
shape = RoundedCornerShape(roundedCornerSize),
border = BorderStroke(width = 1.dp,
color = Color.Gray),
color = Color.Green,
elevation = elevation) {
ConstraintLayout(modifier = Modifier
.fillMaxWidth()
.background(color = Color.Blue)
.padding(16.dp)) {
val (dragIconRef, imageRef, nameRef, updateTimeRef, priceRef, changeRef) = createRefs()
val endMarginFromImageStart = 8.dp
Icon(modifier = Modifier.constrainAs(dragIconRef) {
end.linkTo(parent.end)
linkTo(top = parent.top, bottom = parent.bottom)
}, painter = painterResource(id = R.drawable.ic_drag_indicator),
contentDescription = null)
Image(
modifier = Modifier
.constrainAs(imageRef) {
end.linkTo(dragIconRef.start, margin = 16.dp)
linkTo(top = parent.top, bottom = parent.bottom)
}
.size(36.dp),
painter = painterResource(id = R.drawable.ic_notify),
contentDescription = null
)
Text(
modifier = Modifier.constrainAs(nameRef) {
top.linkTo(imageRef.top)
end.linkTo(imageRef.start, margin = endMarginFromImageStart)
},
text = itemModel.name,
)
Text(
modifier = Modifier.constrainAs(updateTimeRef) {
bottom.linkTo(imageRef.bottom)
end.linkTo(imageRef.start, margin = endMarginFromImageStart)
},
text = itemModel.updateTime,
)
Text(
modifier = Modifier.constrainAs(priceRef) {
baseline.linkTo(nameRef.baseline)
end.linkTo(changeRef.end)
},
text = itemModel.price,
)
Text(
modifier = Modifier.constrainAs(changeRef) {
baseline.linkTo(updateTimeRef.baseline)
start.linkTo(parent.start)
},
text = itemModel.change.toString(),
)
}
}
Related
I use ModalBottomSheetLayout and I want the back part to darken when opening the lower curtain and it was not clickable. How to do it?
If you set screen Color = Color.Unspecified, the background will not be clickable, but at the same time it will be colorless. It doesn't suit me.
#OptIn(ExperimentalMaterialApi::class)
#Composable
fun ForpostScreen(forpostViewModel: ForpostViewModel = koinViewModel()) {
val scope = rememberCoroutineScope()
val bottomSheetOpen = remember{ mutableStateOf(false) }
val viewState = forpostViewModel.forpostViewState.observeAsState()
val bottomSheetState = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden
)
ModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
Box(modifier = Modifier
.fillMaxWidth()
.height(500.dp)) {
Image(
painter = painterResource(id = R.drawable.botton_sheet_top_line),
contentDescription = "Линия",
modifier = Modifier
.height(20.dp)
.width(70.dp)
.padding(top = 10.dp)
.align(Alignment.TopCenter)
)
Text(
text = stringResource(id = R.string.all_cams_button),
color = colorResource(id = R.color.title_text_color),
fontWeight = FontWeight(600),
fontSize = 25.sp,
modifier = Modifier
.padding(top = 30.dp)
.align(Alignment.TopCenter)
)
}
},
sheetShape = RoundedCornerShape(topStart = 25.dp, topEnd = 25.dp),
sheetElevation = 12.dp,
) {
Surface(color = Color.White) {
Column {
Button(
onClick = {
bottomSheetOpen.value = true
scope.launch {
bottomSheetState.show()
}
},
colors = ButtonDefaults.buttonColors(colorResource(id = R.color.button_color)),
shape = RoundedCornerShape(15.dp),
modifier = Modifier
.padding(top = 20.dp, start = 20.dp)
.height(30.dp)
.width(130.dp),
contentPadding = PaddingValues(bottom = 0.dp),
content = {
Text(
text = stringResource(id = R.string.all_cams_button),
color = Color.White,
fontWeight = FontWeight(400)
)
}
)
Text(
modifier = Modifier.padding(top = 50.dp, start = 20.dp),
text = "Репина, 1 Б",
color = colorResource(id = R.color.title_text_color),
fontWeight = FontWeight(700),
fontSize = 18.sp,
letterSpacing= 1.sp
)
ButtonsLazyColumn(
listItem = listOf("Двор", "Подъезд", "Парковка", "Въезд", "Пост охраны"),
height = 50,
modifierPaddingStart = 20,
modifierPaddingTop = 15,
modifierPaddingEnd = 10,
)
Surface(modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp)
.height(220.dp)
.background(Color.Black)) {
when (viewState.value) {
is ForpostViewState.Loading -> { VideoLoadingView() }
is ForpostViewState.Load -> { PlayerView(forpostViewModel = forpostViewModel) }
else -> {}
}
}
Divider(
modifier = Modifier.padding(top = 100.dp),
color = colorResource(id = R.color.sevstar_gray_light),
thickness = 1.dp
)
ButtonsLazyColumn(
listItem = listOf("1 сек", "1 мин", "5 мин", "10 мин", "30 мин"),
height = 50,
modifierPaddingStart = 20,
modifierPaddingTop = 15,
modifierPaddingEnd = 10
)
Divider(
modifier = Modifier.padding(top = 20.dp),
color = colorResource(id = R.color.sevstar_purple),
thickness = 1.dp
)
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(
color = if (bottomSheetOpen.value) Color.Black.copy(alpha = 0.5f)
else Color.Transparent
))
}
if (bottomSheetState.currentValue != ModalBottomSheetValue.Hidden
&& bottomSheetState.offset.value > 1800) bottomSheetOpen.value = false
LaunchedEffect(key1 = viewState, block = {
forpostViewModel.obtainEvent(event = ForpostEvents.EnterScreen)
})
}
I made the back darkening myself and it works, but in this case the back part becomes clickable.
You can use something like
val bottomSheetState = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
confirmStateChange = {false}
)
and you have to manually close the bottom sheet like,
onClick = { scope.launch { bottomSheetState.hide() } }
I've been trying to build a list with a Card in it formatted like this:
The difficulty here is that the title e.g. "Bread" and ingredient name e.g. "Flour" can be very long and thus I want to have an ellipsis to keep things manageable i.e. "My Long Flour name" will be displayed as "My Long Flou..." or as much space as is allowed.
The picture size and the gram and percent widths are constant .dp values.
Ellipsis worked fine when it was in a Column but with ConstraintLayout it doesn't seem to work and I get this:
here's my code
#Composable
fun BakeItem(
modifier: Modifier = Modifier,
bake: Bake,
cardClicked: () -> Unit,
ingredeints: List<Ingredient>
) {
Card(
modifier = modifier
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp)
.clickable { cardClicked() }
.fillMaxSize()
.wrapContentHeight(),
border = BorderStroke(4.dp, MaterialTheme.colorScheme.secondary),
shape = RoundedCornerShape(14.0.dp),
colors = cardColors(
containerColor = MaterialTheme.colorScheme.background
)
) {
val context = LocalContext.current
val uri = remember(bake.imagePath) { Uri.parse(bake.imagePath) }
// Card Content
ConstraintLayout(
modifier = modifier
.fillMaxSize()
.padding(start = 16.dp, top = 8.dp, end = 8.dp, bottom = 8.dp)
) {
val (titleRef, gramColRef, ingrColRef, percentColRef,
imageRef, dateRef, starsRef) = createRefs()
Text(
modifier = modifier
.padding(4.dp)
.constrainAs(titleRef) {
top.linkTo(parent.top, margin = 8.dp)
// end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
}
.background(Color(0xffeeeeee)),
// textAlign = TextAlign.Left,
text = if (bake.recipeName.isEmpty()) "<Unnamed>" else bake.recipeName,
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary,
softWrap = false,
overflow = TextOverflow.Ellipsis,
)
Column(
horizontalAlignment = Alignment.End,
modifier = modifier
.width(50.dp)
.constrainAs(gramColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(ingrColRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
}
) {
ingredeints.forEachIndexed { _, it ->
Text(
text = it.weightGram,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Column(
modifier = modifier
.constrainAs(ingrColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
start.linkTo(gramColRef.end, margin = 8.dp)
end.linkTo(ingrColRef.start, margin = 8.dp)
},
) {
ingredeints.forEachIndexed { _, it ->
Text(
text = it.name,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Column(
modifier = modifier
.width(50.dp)
.constrainAs(percentColRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(ingrColRef.end, margin = 8.dp)
},
horizontalAlignment = Alignment.End
) {
ingredeints.forEachIndexed { i, it ->
Text(
text = if (i == 0) "" else it.bakingPercent,
style = MaterialTheme.typography.titleSmall,
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
}
Text(
modifier = modifier.padding(
top = 8.dp,
start = 4.dp,
end = 4.dp,
bottom = 4.dp
),
text = bake.notes,
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 3
)
if (bake.imagePath.isNotEmpty()) {
Image(
modifier = modifier
.constrainAs(imageRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
}
.padding(4.dp)
.requiredSize(150.dp)
.clip(RoundedCornerShape(14.dp))
.border(
4.dp,
MaterialTheme.colorScheme.primaryContainer,
RoundedCornerShape(14.dp)
),
painter = rememberAsyncImagePainter(
remember(uri) {
ImageRequest.Builder(context)
.data(uri)
// TODO, think of caching improvements
// .diskCacheKey(uri.toString() + key.value)
// .memoryCacheKey(uri.toString() + key.value)
.diskCachePolicy(CachePolicy.DISABLED)
.memoryCachePolicy(CachePolicy.DISABLED)
.build()
}
),
contentScale = ContentScale.Crop,
contentDescription = "Image of your bake"
)
} else {
Spacer(modifier = modifier
.background(Color.Blue)
.width(150.dp)
.height(10.dp)
.constrainAs(imageRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
})
}
Text(
modifier = modifier
.padding(4.dp)
.constrainAs(dateRef) {
bottom.linkTo(parent.bottom, margin = 8.dp)
top.linkTo(imageRef.bottom, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
},
text = bake.startTime.toString(),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
// textAlign = Layout.Alignment.ALIGN_CENTER
)
createHorizontalChain(
gramColRef, ingrColRef, percentColRef, imageRef,
chainStyle = ChainStyle.SpreadInside
)
createVerticalChain(
imageRef, dateRef,
chainStyle = ChainStyle.SpreadInside
)
createHorizontalChain(
titleRef, imageRef,
chainStyle = ChainStyle.SpreadInside
)
}
}
}
In the title you have to add as constrain width = Dimension.fillToConstraints, end.linkTo(imageRef.start, margin = 8.dp) and maxLines = 1:
Text(
modifier = Modifier
.padding(4.dp)
.constrainAs(titleRef) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
width = Dimension.fillToConstraints
}
.background(Color(0xffeeeeee)),
text = "Recipe Name",
//...
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
For the list instead of using 3 Columns you do can something different.
For the ingredient name add the weight(1f) modifier and the maxLines = 1
Column(
modifier = Modifier
.constrainAs(listRef) {
top.linkTo(titleRef.bottom, margin = 8.dp)
end.linkTo(imageRef.start, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
width = Dimension.fillToConstraints
}
) {
//forEach Row...
Row(Modifier.fillMaxWidth()) {
Text(text = "50g", Modifier.width(xx.dp), textAlign = TextAlign.End)
Text(
text = "Very long text long text",
Modifier
.padding(start=4.dp)
.weight(1f),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(text = "75%", Modifier.width(xx.dp), textAlign = TextAlign.End)
}
}
I want make a UI like this picture.
What I want:
Now my result:
My code:
Row(
verticalAlignment = Alignment.CenterVertically
) {
Image(
imageVector = Icons.Rounded.CheckCircle,
contentDescription = null,
modifier = Modifier
.size(16.dp)
.onGloballyPositioned {
topOffset = it.boundsInRoot().bottomCenter
}
)
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
fontSize = 16.sp,
)
}
Spacer(modifier = Modifier.size(8.dp))
Row(
verticalAlignment = Alignment.CenterVertically
) {
Image(
imageVector = Icons.Rounded.CheckCircle,
contentDescription = null,
modifier = Modifier
.size(16.dp)
.onGloballyPositioned {
bottomOffset = it.boundsInRoot().bottomCenter
}
)
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
fontSize = 16.sp,
)
}
I want draw a vertical line between the CheckCircle icons.
You can have a fixed height and then draw a line behind. You should also have another icon with white arrow.
An example:
#Composable
fun checkComposable() {
// padding between rows
val padding = 50.dp
Row {
Box(Modifier.height(intrinsicSize = IntrinsicSize.Min)) {
Box(modifier = Modifier
.width(4.dp)
.padding(top = padding / 2, bottom = padding / 2)
.fillMaxHeight()
.background(Color.Black)
.align(Alignment.Center))
Column {
Box(Modifier.height(padding)) {
Image(
imageVector = Icons.Rounded.CheckCircle,
contentDescription = null,
modifier = Modifier
.size(16.dp)
.align(Alignment.Center)
)
}
Box(Modifier.height(padding)) {
Image(
imageVector = Icons.Rounded.CheckCircle,
contentDescription = null,
modifier = Modifier
.size(16.dp)
.align(Alignment.Center)
)
}
}
}
Spacer(modifier = Modifier.width(8.dp))
Column{
Box(Modifier.height(padding)) {
Text(
modifier = Modifier.align(Alignment.CenterStart),
text = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
fontSize = 16.sp,
)
}
Box(Modifier.height(padding)) {
Text(
modifier = Modifier.align(Alignment.CenterStart),
text = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
fontSize = 16.sp,
)
}
}
}
}
A workaround, could be this:
Row {
Vector() // Complete Icon, ticks and line
Column {
Text(...)
Text(...)
}
}
I wanna have this layout in Jetpack Compose. How can I place the image at the bottom of the card and have it a bit outside the card borders? Also how to make sure that the content above won't collide with the image, because the content above can be longer. Thanks very much.
A simple way is to use a Box and apply an Offset to the Image
Box() {
val overlayBoxHeight = 40.dp
Card(
modifier = Modifier
.fillMaxWidth()
.height(300.dp)
) {
//...
}
Image(
painterResource(id = R.drawable.xxxx),
contentDescription = "",
modifier = Modifier
.align(BottomCenter)
.offset(x = 0.dp, y = overlayBoxHeight )
)
}
If you want to calculate the offset you can use a Layout composable.
Something like:
Layout( content = {
Card(
elevation = 10.dp,
modifier = Modifier
.layoutId("card")
.fillMaxWidth()
.height(300.dp)
) {
//...
}
Image(
painterResource(id = R.drawable.conero),
contentDescription = "",
modifier = Modifier
.layoutId("image")
)
}){ measurables, incomingConstraints ->
val constraints = incomingConstraints.copy(minWidth = 0, minHeight = 0)
val cardPlaceable =
measurables.find { it.layoutId == "card" }?.measure(constraints)
val imagePlaceable =
measurables.find { it.layoutId == "image" }?.measure(constraints)
//align the icon on the top/end edge
layout(width = widthOrZero(cardPlaceable),
height = heightOrZero(cardPlaceable)+ heightOrZero(imagePlaceable)/2){
cardPlaceable?.placeRelative(0, 0)
imagePlaceable?.placeRelative(widthOrZero(cardPlaceable)/2 - widthOrZero(imagePlaceable)/2,
heightOrZero(cardPlaceable) - heightOrZero(imagePlaceable)/2)
}
}
You can use Card for main view layout.
To have an icon placed like this, you need to place it with Card into a box, apply Alignment.BottomCenter alignment to image and add paddings.
To make image be under your text, I've added Spacer with size calculated on image size.
#Composable
fun TestView() {
CompositionLocalProvider(
LocalContentColor provides Color.White
) {
Column {
LazyRow {
items(10) {
Item()
}
}
Box(Modifier.fillMaxWidth().background(Color.DarkGray)) {
Text("next view")
}
}
}
}
#Composable
fun Item() {
Box(
Modifier
.padding(10.dp)
) {
val imagePainter = painterResource(id = R.drawable.test2)
val imageOffset = 20.dp
Card(
shape = RoundedCornerShape(0.dp),
backgroundColor = Color.DarkGray,
modifier = Modifier
.padding(bottom = imageOffset)
.width(200.dp)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(20.dp)
) {
Text(
"Title",
modifier = Modifier.align(Alignment.Start)
)
Spacer(modifier = Modifier.size(15.dp))
Text("PM2.5")
Text(
"10",
fontSize = 35.sp,
)
Text("m/s")
Spacer(modifier = Modifier.size(15.dp))
Text(
"Very Good",
fontSize = 25.sp,
)
Spacer(
modifier = Modifier
.size(
with(LocalDensity.current) { imagePainter.intrinsicSize.height.toDp() - imageOffset }
)
)
}
}
Image(
painter = imagePainter,
contentDescription = "",
Modifier
.align(Alignment.BottomCenter)
)
}
}
Result:
I am trying to scroll down to the position of a specific UI element on clicking a Text.
The code for my Text is:
Text(
"What is autosaving?",
color = colorResource(id = R.color.text_highlight),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
},
fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier.constrainAs(whatIsAutosaving) {
top.linkTo(glWhatIsAutoSaving)
start.linkTo(parent.start)
end.linkTo(parent.end)
},
)
On clicking this Text my screen should scroll to the beginning position of another Text. The code for this another Text is:
Text(
stringResource(id = R.string.autosave_info),
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
}, fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier.constrainAs(autoSaveInfo) {
top.linkTo(glAutoSaveInfo)
start.linkTo(glLeft)
end.linkTo(glRight)
width = Dimension.fillToConstraints
},
)
How do I achieve this?
EDIT:
The complete code for my screen is:
#Composable
fun Autosave(navController: NavController) {
val query = remember { mutableStateOf("") }
val errorMsg = remember { mutableStateOf(false) }
Box(
modifier = Modifier
.background(color = MaterialTheme.colors.background)
.fillMaxSize()
) {
ConstraintLayout(
modifier = Modifier.verticalScroll(rememberScrollState())
) {
val (logo, illustration, title, triangle, slider, percent, maxLimitTxt,
maxLimitTextField, buttonSave, whatIsAutosaving, autoSaveInfo, progressBar,
detailsRow, iconUp, spacer, error) = createRefs()
val glLogo = createGuidelineFromTop(0.0075f)
val glIllustrationTop = createGuidelineFromTop(0.0235f)
val glIllustrationBottom = createGuidelineFromTop(0.045f)
val glIllustrationLeft = createGuidelineFromStart(0.27f)
val glIllustrationRight = createGuidelineFromEnd(0.27f)
val glTitle = createGuidelineFromTop(0.053f)
val glSlider = createGuidelineFromTop(0.062f)
val glMaxLimitTxt = createGuidelineFromTop(0.086f)
val glMaxLimitTextField = createGuidelineFromTop(0.09f)
val glButtonSaveTop = createGuidelineFromTop(0.11f)
val glButtonSaveBottom = createGuidelineFromTop(0.12f)
val glWhatIsAutoSaving = createGuidelineFromTop(0.125f)
val glAutoSaveInfo = createGuidelineFromTop(0.175f)
val glSpacer = createGuidelineFromTop(0.99f)
val glLeft = createGuidelineFromStart(0.1f)
val glRight = createGuidelineFromEnd(0.1f)
val glRightIcon = createGuidelineFromEnd(0.825f)
val glLeftTextField = createGuidelineFromStart(0.3f)
val glRightTextField = createGuidelineFromEnd(0.3f)
val coroutineScope = rememberCoroutineScope()
val scrollState = rememberScrollState()
var scrollToPosition by remember { mutableStateOf(0F) }
Image(
painter = painterResource(id = R.drawable.effect_app_bg_720),
contentDescription = "effect top",
modifier = Modifier
.fillMaxSize()
.scale(1.325f)
)
Image(
painter = painterResource(id = R.drawable.logo_voodlee),
contentDescription = "logo", modifier = Modifier
.constrainAs(logo) {
top.linkTo(glLogo)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
)
Image(
painter = painterResource(id = R.drawable.img_autosaving),
contentDescription = "autosave image",
modifier = Modifier.constrainAs(illustration) {
top.linkTo(glIllustrationTop)
bottom.linkTo(glIllustrationBottom)
start.linkTo(glIllustrationLeft)
end.linkTo(glIllustrationRight)
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
}
)
Text(
"Set the percentage for autosaving",
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._13ssp).toSp()
}, fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier.constrainAs(title) {
top.linkTo(glTitle)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
)
Image(
painter = painterResource(id = R.drawable.ic_triangle_dn),
modifier = Modifier
.height(39.dp)
.width(29.dp)
.constrainAs(triangle) {
top.linkTo(title.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
},
contentDescription = "triangle down"
)
Column(modifier = Modifier.constrainAs(slider) {
top.linkTo(glSlider)
start.linkTo(parent.start)
end.linkTo(parent.end)
}) {
val context = LocalContext.current
val customView = remember { com.shawnlin.numberpicker.NumberPicker(context) }
// Adds view to Compose
AndroidView({ customView }) { view ->
// View's been inflated - add logic here if necessary
with(view) {
orientation = HORIZONTAL
//dividerDrawable = ResourcesCompat.getDrawable(resources, R.drawable.bg_blue, null)
textColor =
ResourcesCompat.getColor(resources, R.color.slider_num_color, null)
selectedTextColor =
ResourcesCompat.getColor(resources, R.color.slider_num_color, null)
selectedTextSize = 120f
wheelItemCount = 6
value = 10
minValue = 0
maxValue = 99
layoutParams.width = MATCH_PARENT
setDividerColorResource(R.color.fade_green)
setDividerDistance(180)
setDividerThickness(10)
}
}
Text(
"%",
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._18ssp).toSp()
}, fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier
.align(CenterHorizontally)
.offset(y = (-5).dp)
)
}
Text(
"Max Limit per autosaving",
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._13ssp).toSp()
},
fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier.constrainAs(maxLimitTxt) {
top.linkTo(glMaxLimitTxt)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
)
TextField(
value = query.value,
onValueChange = { newValue -> query.value = newValue
if (newValue != "")
errorMsg.value = newValue.toInt() > 1500
},
label = {
Text(" Amount",
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._15ssp).toSp()
},
textAlign = TextAlign.Center
)
},
textStyle = TextStyle(
textAlign = TextAlign.Center,
color = colorResource(id = R.color.bright_green),
fontFamily = FontFamily(Font(R.font.poppins_regular)),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._15ssp).toSp()
},
),
modifier = Modifier.constrainAs(maxLimitTextField) {
top.linkTo(glMaxLimitTextField)
start.linkTo(glLeftTextField)
end.linkTo(glRightTextField)
width = Dimension.fillToConstraints
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
unfocusedIndicatorColor = colorResource(id = R.color.bright_green),
focusedIndicatorColor = colorResource(id = R.color.bright_green)
)
)
Text(
text =
"*Please enter amount less than Rs.1500",
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._8ssp).toSp()
},
color = colorResource(id = R.color.voodlee_red),
modifier = Modifier
.padding(top = 8.dp)
.alpha(
if (errorMsg.value) {
1f
} else 0f
)
.constrainAs(error) {
top.linkTo(maxLimitTextField.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
},
)
Button(
onClick = {
navController.navigate("fourth_screen")
},
modifier = Modifier.constrainAs(buttonSave) {
top.linkTo(glButtonSaveTop)
bottom.linkTo(glButtonSaveBottom)
start.linkTo(glLeft)
end.linkTo(glRight)
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
},
colors = ButtonDefaults.buttonColors(backgroundColor = colorResource(id = R.color.voodlee_red))
) {
Text(
"Save", color = colorResource(id = R.color.dark_blue),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._16ssp).toSp()
},
)
}
Text(
"What is autosaving?",
color = colorResource(id = R.color.text_highlight),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
},
fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier
.constrainAs(whatIsAutosaving) {
top.linkTo(glWhatIsAutoSaving)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
.clickable {
coroutineScope.launch {
scrollState.animateScrollTo(scrollToPosition.roundToInt())
}
},
)
Text(
stringResource(id = R.string.autosave_info),
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
}, fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
modifier = Modifier
.constrainAs(autoSaveInfo) {
top.linkTo(glAutoSaveInfo)
start.linkTo(glLeft)
end.linkTo(glRight)
width = Dimension.fillToConstraints
}
.onGloballyPositioned { coordinates ->
scrollToPosition = coordinates.positionInParent().y
},
)
Row(
modifier = Modifier
.padding(top = 40.dp, bottom = 50.dp)
.constrainAs(detailsRow) {
top.linkTo(autoSaveInfo.bottom)
start.linkTo(glLeft)
end.linkTo(glRight)
width = Dimension.fillToConstraints
},
) {
Text(
text = "For more details",
color = colorResource(id = R.color.bright_green),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
}, fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
)
Spacer(modifier = Modifier.padding(5.dp))
Text(
text = "Click here",
color = colorResource(id = R.color.text_highlight),
fontSize = with(LocalDensity.current) {
dimensionResource(id = R.dimen._11ssp).toSp()
},
fontFamily = FontFamily(
Font(R.font.poppins_regular)
),
)
}
Image(
painter = painterResource(id = R.drawable.ic_btn_upward),
modifier = Modifier
.height(32.dp)
.constrainAs(iconUp) {
top.linkTo(detailsRow.bottom)
start.linkTo(glLeft)
end.linkTo(glRightIcon)
width = Dimension.fillToConstraints
},
contentDescription = ""
)
Spacer(modifier = Modifier
.padding(bottom = 50.dp)
.constrainAs(spacer) {
top.linkTo(glSpacer)
start.linkTo(parent.start)
end.linkTo(parent.end)
},)
}
Card(
Modifier
.align(BottomCenter)
.fillMaxWidth()
.alpha(if (query.value == "") 1f else 0f),
backgroundColor = MaterialTheme.colors.secondaryVariant
) {
ProgressBar5UI(
Modifier
.padding(start = 40.dp, end = 40.dp, top = 10.dp)
)
}
Card(
Modifier
.align(BottomCenter)
.fillMaxWidth()
.alpha(if (errorMsg.value) 1f else 0f),
backgroundColor = MaterialTheme.colors.secondaryVariant
) {
ProgressBar6UI(
Modifier
.padding(start = 40.dp, end = 40.dp, top = 10.dp)
)
}
Card(
Modifier
.align(BottomCenter)
.fillMaxWidth()
.alpha(if (query.value != "" && !errorMsg.value) 1f else 0f),
backgroundColor = MaterialTheme.colors.secondaryVariant
) {
ProgressBar7UI(
Modifier
.padding(start = 40.dp, end = 40.dp, top = 10.dp)
)
}
}
}
Is there possibly any special way to scroll on clicking an element while using Constraint Layout?
You can use the onGloballyPositioned modifier to retrieve the position of a composable and then use the method scrollState.animateScrollTo to scroll to that position.
Something like:
val coroutineScope = rememberCoroutineScope()
val scrollState = rememberScrollState()
var scrollToPosition by remember { mutableStateOf(0F) }
Column(Modifier.verticalScroll(scrollState)) {
Text(
"Click here to scroll",
modifier = Modifier.clickable {
coroutineScope.launch {
scrollState.animateScrollTo(scrollToPosition.roundToInt())
}
}
)
//...
Text(
"Target",
modifier = Modifier.onGloballyPositioned { coordinates ->
scrollToPosition = coordinates.positionInParent().y
}
)
}