Jetpack compose Justified and RTL Text - android-jetpack-compose

In jetpack Compose, you can Justify a Text like this:
Text(
text = text,
textAlign = TextAlign.Justify
)
If you want support RTL, you achive this by:
Text(
text = text,
textAlign = TextAlign.Right
)
How can a Text() support RTL text and justify it same time in Jetpack Compose?

After several hour testing, I reach this:
#Composable
fun JustifiedRTLText(
text: String,
modifier: Modifier = Modifier
) {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
Text(
text = text,
textAlign = TextAlign.Justify,
modifier = modifier,
)
}
}

In Jetpack Compose RTL or LTR will automatically set by according to the text content. But we can force it by changing the textDirection of style to TextDirection.Content or TextDirection.RTL
Text(
text = text,
textAlign = TextAlign.Justify,
style = TextStyle(textDirection = TextDirection.Content)
)

Related

Compose Column with vertical scrollable modifier not working

I am trying to create a similar-to-scrollview behavior with Jetpack Compose, which should be simple but I find it not working (I can't scroll the Column). I have been following the example from here:
https://github.com/vinaygaba/Learn-Jetpack-Compose-By-Example/blob/master/app/src/main/java/com/example/jetpackcompose/scrollers/VerticalScrollableActivity.kt#L104
And this is my code:
#Composable
fun MainScreen() {
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.scrollable(
state = scrollState,
orientation = Orientation.Vertical
)
) {
Text(
text = "This is my first Compose App",
fontSize = 24.sp,
fontWeight = FontWeight.Light,
lineHeight = 40.sp,
color = Color.Black,
modifier = Modifier.padding(top = 32.dp, start = 24.dp)
)
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color(0xFF6A0DAD))
.height(2200.dp))
{}
}
}
as mentioned #bylazy using Modifier.verticalScroll(scrollState) solves it

How do I fix ConstraintLayout that include Balloon(gives strange results) in jetpack compose?

I'm trying to make a help pop ups in my first app. the problem that came up after making the pop up work is that the icon which I'm using becomes a button taking up whole screen height.
I'm using the only code I found for balloon popups in jetpack compose.
the layout is fine until I add the BalloonAnchor.
this is the code:
#Composable
fun GiveHelp(helpText: String) {
Surface{
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
ConstraintLayout {
val (icon, text) = createRefs()
Icon(
modifier = Modifier
.constrainAs(icon) {
top.linkTo(parent.top)
start.linkTo(parent.start)
},
painter = painterResource(id = R.drawable.ic_help),
contentDescription = "help Icon"
)
Text(
modifier = Modifier
.constrainAs(text) {
top.linkTo(icon.top)
start.linkTo(icon.end)
bottom.linkTo(icon.bottom)
}
.padding(horizontal = 10.dp),
text = "Is your task:"
)
BalloonAnchor(
reference = icon,
modifier = Modifier
.aspectRatio(0.1f),
balloon = BalloonUtils.getTitleBalloon(
context = context,
title = helpText,
lifecycle = lifecycleOwner
),
onAnchorClick = { balloon, anchor -> balloon.showAlignTop(anchor) }
)
}
}
}
The problem here is the aspectRatio you are using in the Modifier of BalloonAnchor. Try something like Modifier.aspectRatio(0.99f). Using this, your Icon will not take the entire screen height. Or, your can use something like below code to get a desirable look.
BalloonAnchor(
reference = icon,
modifier = Modifier
.height(40.dp),
balloon = BalloonUtils.getTitleBalloon(
context = context,
title = helpText,
lifecycle = lifecycleOwner
),
onAnchorClick = { balloon, anchor -> balloon.showAlignTop(anchor) }
)

How can I remove paddins from my styled text in jetpack compose?

I'm trying to remove the padding at the bottom and top of the text, but I haven't been able to remove the padding successfully, any suggestions?
Text(
text = "DT",
color = androidx.compose.ui.graphics.Color.Black,
style = androidx.compose.ui.text.TextStyle(
fontFamily = poppinsFamily,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center
),
fontSize = 54.sp,
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 0.dp),
)
You can use PlatformTextStyle attribute to set includeFontPadding = false
Example:
Text(
text = text,
style = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = false
)
)
)
Details:
https://android-developers.googleblog.com/2022/05/whats-new-in-jetpack-compose.html

scrollable Text crashes

I want Text to be of max 4 lines but scrollable, as the following. Is that the way to do it?
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 6.dp, horizontal = 8.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
Row {
Text(
text = longText,
maxLines = 4,
modifier = Modifier
.padding(end = 5.dp)
.verticalScroll(rememberScrollState(0)),
textAlign = TextAlign.Start,
fontSize = dimensionResource(dimen.normal_text).value.sp,
)
}
}
But I got crash messages. I don't have a lazycolumn. I would like Column to be scrollable as well. That can not be done at the same time?
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.
at androidx.compose.foundation.ScrollKt.assertNotNestingScrollableContainers-K40F9xA(Scroll.kt:383)
at androidx.compose.foundation.ScrollingLayoutModifier.measure-3p2s80s(Scroll.kt:337)
at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:40)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.measure-BRTryo0(DelegatingLayoutNodeWrapper.kt:96)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:405)
at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:40)
at androidx.compose.foundation.layout.PaddingModifier.measure-3p2s80s(Padding.kt:364)
at androidx.compose.ui.node.ModifiedLayoutNode.measure-BRTryo0(ModifiedLayoutNode.kt:40)
at androidx.compose.ui.node.LayoutNode$performMeasure$1.invoke(LayoutNode.kt:1342)
at androidx.compose.ui.node.LayoutNode$performMeasure$1.invoke(LayoutNode.kt:1341)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:126)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:88)
.......
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
Update: I found if I don't limit the number of lines but the height of the composable, like the following, then scrolling works, without crash.
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 6.dp, horizontal = 8.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
Row {
Text(
text = longText,
modifier = Modifier
.padding(end = 5.dp)
.height(100.dp)
.verticalScroll(rememberScrollState(0)),
textAlign = TextAlign.Start,
fontSize = dimensionResource(dimen.normal_text).value.sp,
)
}
}
I think you can use SubcomposeLayout for this.
val longText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum"
Column(
/* I checked with your Column params and it worked */
) {
Row {
val localDensity = LocalDensity.current
SubcomposeLayout { constraints ->
// This modifier must be used in the fake text and real content
// if you need to set text size, you should use it on both contents
val textModifier = Modifier.padding(6.dp)
// Here it's calculated the height of a Text with 4 lines
val fourLinesHeight = subcompose("SomeRandomId") {
Text(text = "A\nB\nC\nD", modifier = textModifier)
}.first().measure(constraints).height
// The height is in pixels. Converting to Dp
val heightInDp = with(localDensity) { (fourLinesHeight / density).dp }
// Now the real content is measured.
val placeables = subcompose("RealContentSlotId") {
Text(
text = longText,
modifier = Modifier
.height(heightInDp) // here is the secret
.then(textModifier)
.verticalScroll(rememberScrollState(0)),
textAlign = TextAlign.Start,
)
}.first().measure(constraints)
layout(placeables.width, placeables.height) {
placeables.placeRelative(0, 0)
}
}
}
}
Here is the result:

Jetpack Compose - Fit Text in a specific box

How can I fit a text, inside a specific Box / Container (i.e of Size 100.dp)
Is there a way to Fit a string inside a Box, in Compose?
Here is what I tried:
#Composable
fun playText() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF242E38)),
contentAlignment = Alignment.Center
) {
Row(modifier = Modifier
.background(Color(0xFFEEEEEE))
.width(100.dp)
.height(100.dp)
) {
Text(
text = "FIT ME",
modifier = Modifier
.fillMaxSize()
.wrapContentSize(
Alignment.Center,
unbounded = true
)
.requiredSize(100.dp),
color = Color(0xFF242E38),
fontSize = 50.sp,
style = TextStyle.Default.copy(
background = Color(0xFFEAC43D)
)
)
}
}
}
#Preview(showBackground = true)
#Composable
fun show() {
playText()
}
Here is the current result:
Here is the expected result (which I achieved by decreasing the font size, just to demonstrate what is expected):

Resources