Padding for Text() within Column not working? - android-jetpack-compose

I have a Jetpack Compose composable in a column beginning with a icon, title, textbody and a pager row:
Box(modifier = Modifier
.fillMaxSize()
.background(color = TVTheme.colors.blue)
) {
val bigPadding = 334.dp
val smallPadding = 24.dp
Column(
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier
.requiredSize(164.dp, 28.dp),
icon = R.drawable.calendar_a_icon
)
// title
val title = "Lorem Ipsum Dolor Sit"
if (title.isNotEmpty()) {
Text(
text = title,
textAlign = TextAlign.Center,
modifier = Modifier
.padding(top = dimensionResource(id = R.dimen.vertical), start = bigPadding, end = bigPadding)
.fillMaxWidth(),
overflow = TextOverflow.Visible
)
}
// body
val body = "Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit. Lorem ipsum dolor sit."
if (body.isNotEmpty()) {
Text(
text = body,
textAlign = TextAlign.Center,
modifier = Modifier
.padding(top = dimensionResource(id = R.dimen.vertical), start = bigPadding, end = bigPadding)
.fillMaxWidth(),
overflow = TextOverflow.Visible
)
}
Row(
modifier = Modifier
.padding(top = 44.dp, bottom = smallPadding, start = smallPadding, end = smallPadding)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
val text = AnnotatedString.Builder(item.skipButtonText).toAnnotatedString()
ClickableText(
maxLines = 1,
text = "Skip",
onClick = {
skip()
}
)
Pager(
modifier = Modifier
.align(Alignment.CenterVertically),
index = currentPageIndex,
pageNumbers = totalPages)
}
}
}
which produces this screen:
The left and right paddings for the title and body is set to 334.dp. The example screenshot has a width of 1800 dp and according to proportions the paddings are much more than given 334.dp. That would mean, the width of title and body is 1132.dp ?!:
I tried to make the proportions visible.
How can I apply correct paddings for title and body text composables?

Related

Resizing text dynamically in LazyColumn depending on scroll - Jetpack Compose

I want to make the text to be resizing dynamically when I scroll and them to stay that size when I stop scrolling.
For example here the number 4 to be 20.sp and the numbers 3 and 5 to be 18.sp (one index away) and 2 - 6 to be 16.sp and so on. I think that could be created with
Modifier.scale(), but have not found a way for now.
#OptIn(ExperimentalSnapperApi::class)
#Composable
fun Example() {
val listStateHour = rememberLazyListState()
val hourTexts: List<String> = (1..23).map { it.toString().padStart(2, '0') }
Box(
modifier = Modifier.background(color = Color.LightGray).fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.background(color = Color.Black.copy(0.2f)),
) {}
LazyColumn(
modifier = Modifier.height(200.dp),
state = listStateHour,
horizontalAlignment = Alignment.Start,
contentPadding = PaddingValues(vertical = 116.dp),
flingBehavior = rememberSnapperFlingBehavior(lazyListState = listStateHour)
) {
itemsIndexed(hourTexts) { index, item ->
Box(
modifier = Modifier.height(32.dp),
contentAlignment = Alignment.Center
) {
Text(
text = item,
color = Color.Black,
fontSize = 20.sp
)
}
}
}
}
}
External dependencies that I am using -> implementation 'dev.chrisbanes.snapper:snapper:0.3.0'
You can observe listStateHour.firstVisibleItemIndex and calculate a scaling factor depending on the distance an item has to that value.
I didn't test it with the flingBehaviour you're using but this might help you:
val listStateHour = rememberLazyListState()
val firstVisibleItemIndex by remember { derivedStateOf { listStateHour.firstVisibleItemIndex } }
val hourTexts: List<String> = (1..23).map { it.toString().padStart(2, '0')
Box(
modifier = Modifier
.background(color = Color.LightGray)
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.background(color = Color.Black.copy(0.2f)),
) {}
LazyColumn(
modifier = Modifier.height(200.dp),
state = listStateHour,
horizontalAlignment = Alignment.Start,
contentPadding = PaddingValues(vertical = 116.dp)
) {
itemsIndexed(hourTexts) { index, item ->
Box(
modifier = Modifier.height(32.dp),
contentAlignment = Alignment.Center
) {
Text(
text = item,
color = Color.Black,
fontSize = 20.sp,
modifier = Modifier.scale(
scaleText(
firstVisibleIndex = firstVisibleItemIndex,
itemIndex = index
)
)
)
}
}
}
}
fun scaleText(firstVisibleIndex: Int, itemIndex: Int): Float {
val distance = abs( firstVisibleIndex - itemIndex)
return 1f - distance * .2f
}

How to handle error on outlined edit text checking regex in compose

I have this outlined edit text, and I want to display a red error color when user tries to put '#' on the outline edit text when they're trying to sign in. I was wondering how I can handle error on an edit text in jetpack compose
UserInputTextField(
fieldState = usernameState.value,
onFieldChange = { usernameState.value = it },
label = "Enter Name",
)
#Composable
fun UserInputTextField(
fieldState: String,
onFieldChange: (String) -> Unit,
label: String,
modifier: Modifier = Modifier,
) {
androidx.compose.material.OutlinedTextField(
value = fieldState, onValueChange = {
onFieldChange(it)
},
label = { androidx.compose.material.Text(text = label) },
modifier = modifier
.fillMaxWidth()
.padding(top = 16.dp)
.semantics { testTag = TestTags.LoginContent.USERNAME_FIELD },
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Blue,
unfocusedBorderColor = Color.Black
)
)
}
Use isError attribute of TextField.
Example
isError = fieldState.contains("#"),
Sample code for reference
#Composable
fun ErrorCheck() {
val (text, setText) = remember {
mutableStateOf("")
}
UserInputTextField(
fieldState = text,
onFieldChange = setText,
label = "Email",
)
}
#Composable
fun UserInputTextField(
fieldState: String,
onFieldChange: (String) -> Unit,
label: String,
modifier: Modifier = Modifier,
) {
androidx.compose.material.OutlinedTextField(
value = fieldState,
onValueChange = {
onFieldChange(it)
},
isError = fieldState.contains("#"),
modifier = modifier
.fillMaxWidth()
.padding(
all = 16.dp,
),
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = Color.Blue,
unfocusedBorderColor = Color.Black,
)
)
}

Stretch the surface along the entire height which is in row

I have a lazy column in which there is a list of cards in which there is a row and two columns in it, the height of the first column is much larger than the second. The second column has text with a different background made using a surface. The fillMaxHeight modifiers do not work. Already tried to do it by other means:
1)
Row(
modifier = Modifier
.height(IntrinsicSize.Min)
However, there is a problem, this only works with static components, and this is a lazy line in my columns, and the composition starts to crash
2) Get the height in this way.
//Save height
val heightIs = remember {
mutableStateOf(0.dp)
}
//Get the context
val localDensity = LocalDensity.current
Column(modifier = Modifier.fillMaxWidth(0.7f).onSizeChanged{cord->
heightIs.value = with(localDensity){
cord.height.toDp()
}
The problem with this solution is that when there is no lazy row, it doesn't properly distribute the height.
Short code:
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 2.dp, vertical = 4.dp), elevation = 4.dp
) {
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
Column(Modifier.fillMaxWidth(0.7f)) {
Surface(
color = MaterialTheme.colors.primaryVariant,
modifier = Modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = historyOrderItem.id.toString(),
style = MaterialTheme.typography.h6,
modifier = Modifier.padding(4.dp)
)
Text(
text = historyOrderItem.status,
style = MaterialTheme.typography.h6,
modifier = Modifier.padding(4.dp)
)
}
}
LazyRow(modifier = modifier.fillMaxWidth()) {
items(items = historyOrderItem.items, key = { it.itemId }) {
ItemDoneOrderShort(it)
}
}
Spacer(modifier = Modifier.weight(1f))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
TextButton(onClick = { onCopy(historyOrderItem) }) {
Text(
text = "ПОВТОРИТЬ",
style = MaterialTheme.typography.h6,
textAlign = TextAlign.Right,
maxLines = 1,
)
}
}
}
Surface(color = MaterialTheme.colors.colorAccent) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = "Оплатить",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h5,
)
}
}
}
}

goneMargin in ConstraintLayout with Compose

I'm trying to use ConstraintLayout in Compose. I want the second Composable to be constrained at the end of the first Composable. The first composable can exist or not. In each case, I would like to have different margins. Thus, I use goneMargin but this seems to not be respected. Do I need to do something else?
ConstraintLayout {
val (firstItemRef, secondItemRef) = createRefs()
if (isFirstItemVisible) {
Text(
text = "First",
modifier = Modifier.constrainAs(firstItemRef) {
top.linkTo(anchor = parent.top)
start.linkTo(anchor = parent.start)
}
)
}
Text(
text = "Second",
modifier = Modifier.constrainAs(secondItemRef) {
top.linkTo(anchor = parent.top)
start.linkTo(anchor = firstItemRef.end, margin = 8.dp, goneMargin = 16.dp)
}
)
}
As a workaround, we could do something like that, but this seems to counterfeit the purpose of goneMargin
Text(
text = "Second",
modifier = Modifier.constrainAs(secondItemRef) {
val margin = if (isFirstItemVisible) 8.dp else 16.dp
val end = if (isFirstItemVisible) firstItemRef.end else parent.end
top.linkTo(anchor = parent.top)
start.linkTo(anchor = end, margin = margin)
}
)
You have to use the visibility property in ConstrainScope like this:
ConstraintLayout(Modifier.fillMaxSize()) {
val (firstItemRef, secondItemRef) = createRefs()
Text(
text = "First",
modifier = Modifier.constrainAs(firstItemRef) {
top.linkTo(anchor = parent.top)
start.linkTo(anchor = parent.start)
// >> This is what you want <<<
visibility = if (isFirstItemVisible) Visibility.Visible else Visibility.Gone
}
)
Text(
text = "Second",
modifier = Modifier.constrainAs(secondItemRef) {
top.linkTo(anchor = parent.top)
start.linkTo(anchor = firstItemRef.end, margin = 8.dp, goneMargin = 16.dp)
}
)
}

How to Snap the Row/Column elements to end in JetPack Compose

I am using the below code to show the textviews, image and a textfield to show at each corners after the image (start and end). It is basically a Card with Image on the start and later a column with a two text views and with another column with a textview and basictextfield for input.
#Composable
fun BaseCard() {
Card(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(Alignment.CenterVertically, true)
.wrapContentHeight()
.clip(RoundedCornerShape(8.dp)),
elevation = 10.dp,
backgroundColor = Color.White
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
)
{
Image(
modifier = Modifier
.size(35.dp, 35.dp) //50dp
.clip(RoundedCornerShape(8.dp))
.clickable {
navController.navigate("meta") {
launchSingleTop = true
}
},
painter = img,
alignment = Alignment.Center,
contentDescription = "",
contentScale = ContentScale.Crop,
)
Spacer(modifier = Modifier.width(8.dp))
Column(horizontalAlignment = Alignment.Start) {
Text(
text = "US Dollar" + "($)",
color = Color.Gray,
style = Typography.subtitle2
)
Text(
text = "USD",
Modifier.padding(0.dp),
color = MaterialTheme.colors.onPrimary,
style = Typography.h5,
)
}
Spacer(modifier = Modifier.width(8.dp))
Column(horizontalAlignment = Alignment.End) {
Text(
text = "Amount",
color = Color.Gray,
style = Typography.subtitle2
)
BasicTextField(
value = typedValue,
onValueChange = {
----
},
textStyle = LocalTextStyle.current.copy(
fontFamily = NunitoFontFamily,
fontWeight = FontWeight.W600,
letterSpacing = 0.sp,
fontSize = 24.sp,
textAlign = TextAlign.End
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
)
)
}
}
}
}
However, it is showing up as below.
How to remove the extra space and align the elements properly at each end?
There are multiple ways to implement what you ask
One is using Spacer(modifier=Modifier.weight(1f) instead of
Spacer(modifier = Modifier.width(8.dp))
for the Spacer here, since it's inside a Row it will take all the space that don't have weight modifier.
// Change this Spacer's modifier to Modifier.weight(1f)
Spacer(modifier = Modifier.width(8.dp))
Column(horizontalAlignment = Alignment.End) {
Text(
text = "Amount",
color = Color.Gray,
style = Typography.subtitle2
)
BasicTextField(
value = typedValue,
onValueChange = {
----
},
textStyle = LocalTextStyle.current.copy(
fontFamily = NunitoFontFamily,
fontWeight = FontWeight.W600,
letterSpacing = 0.sp,
fontSize = 24.sp,
textAlign = TextAlign.End
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
)
)
}
Second one is to use a Box instead of Row and have 2 composables one aligned to
Box(modifier = Modifier
.fillMaxWidth()
.padding(8.dp)) {
Column(modifier = Modifier.align(Alignment.CenterStart)) {
}
Column(modifier = Modifier.align(Alignment.CenterEnd)) {
}
}

Resources