Divide one column for 2 rows in jetpack compose android - android

I would like to divide one column with long text to 2 the same height and width row. It would be in case if text would be too long. Is It possible to divide one column with one Text for 2 rows in its half?
I couldn't make it, I have no idea.

use weight
Column() {
Row(
Modifier.weight(1f).background(Blue)
){
Text(text = "Weight = 1", color = Color.White)
}
Row(
Modifier.weight(1f).background(Yellow)
) {
Text(text = "Weight = 1")
}
}

You can use a row and set modifier weight: 1f:
Row {
TextField(
value = "Test Test Test Test Test Test Test Test Test Test Test Test" +
" Test Test Test Test Test Test Test Test ",
onValueChange = {},
modifier = Modifier.weight(1f)
)
TextField(
value = "Test Test Test Test Test Test TesTest Test Test Test " +
"Test Test Test Test Test Test Test Test Test ",
onValueChange = {},
modifier = Modifier.weight(1f)
)
}
and if you want to have the second TextField in the next line if it's breaking line, you can use FlowRow
https://google.github.io/accompanist/flowlayout

check this out this can be accomplished by using box.
Box(modifier = Modifier.fillMaxWidth()) {
var size by remember { mutableStateOf(Size.Zero) }
val height: #Composable () -> Dp = { with(LocalDensity.current) { size.height.toDp() } }
Text(
text = longText,
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(.45F)
// if second text is larger than first text call it on second text
.onGloballyPositioned { size = it.size.toSize() },
textAlign = TextAlign.Justify
)
Divider(
modifier = Modifier
.width(1.dp)
.height(height())
.align(Alignment.Center),
color = Color.Black
)
Text(
text = longText,
modifier = Modifier
.padding(8.dp)
.align(Alignment.TopEnd)
.fillMaxWidth(.45F),
textAlign = TextAlign.Justify
)
}

Related

How to add compose modifiers based on other surrounding views?

I am unable to get the expected results as shown in the picture below. There are 2 rules to follow
The horizontal line should not continue till the bottom text. Instead, it should just be the height of the right text (multiline).
Bottom text should align with the Right Text from the left side.
Current Incorrect Snippet
#Composable
fun Sample() {
Row(
modifier = Modifier
.height(IntrinsicSize.Min)
.padding(10.dp)
) {
Text("Left Text")
Divider(
Modifier
.padding(horizontal = 10.dp)
.fillMaxHeight()
.width(4.dp),
color = Color.Black
)
Column {
Text("Right Looooong Text")
Text("Bottom Text")
}
}
}
Visual Representation
You can achieve this in various ways including
Option 1: You can either redesign your Composable
Option 2: Apply Modifier.layoutId() your Composables then set their position relative to each other using Layout and getting measurables via this ids then placing them based on one that they depend on.
I post only the option one which is the easiest one.
#Composable
fun Sample(horizontalPadding: Dp = 10.dp, dividerWidth: Dp = 4.dp) {
Row(
modifier = Modifier.padding(10.dp)
) {
Text("Left Text")
Column {
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
Divider(
Modifier
.padding(horizontal = horizontalPadding)
.fillMaxHeight()
.width(dividerWidth),
color = Color.Black
)
Text("Right Loooooooooooooooooooong Text")
}
Text(
"Bottom Text",
modifier = Modifier.offset(x = horizontalPadding * 2 + dividerWidth)
)
}
}
}
Result
You can use the modifier extension .onSizeChanged{}, which returns its composable's size in Int, to set the vertical divider's height as follows:
var divHeight: Int = 0 // Must be initialized
Row() {
Text(text = "Left Text")
Divider(
modifier = Modifier
.padding(horizontal = 10.dp)
.width(4.dp)
.height(divHeight.dp) // .dp converts measurement from Int to Dp
)
Column {
Text(
modifier = Modifier
.onSizeChanged { divHeight = it.height },
text = "Right Looooong Text"
)
Text(text = "Bottom Text")
}
}
Hope you found this helpful!

jetpack compose removing elements from list of text fields

.
I want my code to remove elements from list of text fields properly.
Each element has an X button to remove it's text field.
If I start removing elements from the bottom it works but it doesn't work for removing random elements
I want to use forEachIndexed for displaing the list
Please help me with solving this problem. I've been trying to do this for some time but every trial is unsuccessful.
This is a piece of code that I've managed to write but removing elements doesn't work properly
val listOfWords = mutableStateListOf<String>()
#Composable
fun Main() {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Words",
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 4.dp),
style = MaterialTheme.typography.h6
)
listOfWords.forEachIndexed { index, word ->
Input(word, 30, "Word", 1,
{newWord ->
listOfWords[index] = newWord
Log.d("text ",word)
},
{
listOfWords.removeAt(index)
}
)
}
IconButton(
onClick = {
listOfWords.add("")
}
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "Add"
)
}
}
}
#Composable
fun Input(
word: String,
maxChar: Int,
label: String,
maxLines: Int,
onEdit: (word: String) -> (Unit),
onRemove: () -> (Unit)
) {
var text by remember { mutableStateOf(word) }
Column(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp, 0.dp, 8.dp, 0.dp)
) {
OutlinedTextField(
value = text,
onValueChange = {
if (it.length <= maxChar) text = it
onEdit(text)
},
modifier = Modifier.fillMaxWidth(),
label = { Text(label) },
leadingIcon = {
Icon(Icons.Default.Edit, null)
},
trailingIcon = {
IconButton(onClick = {
onRemove()
}) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "Back"
)
}
},
maxLines = maxLines
)
Text(
text = "${text.length} / $maxChar",
textAlign = TextAlign.End,
style = MaterialTheme.typography.caption,
modifier = Modifier
.fillMaxWidth()
.padding(end = 16.dp)
)
}
}
The problem is here.
var text by remember { mutableStateOf(word) }
Without supplying a key to Input's remember, compose will not be able refresh/update your remaining Input's states during Main's re-composition every time an Input is removed.
You can use the word parameter as key for remember to re-calculate every composition pass (i.e when you add/remove or typed a value in the TextField), and your code should probably work as you expected.
var text by remember(word) { mutableStateOf(word) }
Have you tried doing the following instead?
listOfWords.forEachIndexed { index, word ->
... // rest of code
{
listOfWords.removeAt(index)
}

Jetpack Compose Text and Image get overlapped inside Column layout issue

I am using Jetpack Compose for designing dynamic Layout inside android app. Column layout is used to place elements like Vertical layout. This kind of behaviour is achieved using LinearLayout orientation Vertical usage without compose. Inside Column I have added one Image on top and one text I want to display below it. But after placing the Text inside the Compose Column layout it is getting overlapped. How to resolve this.
The code for adding Image and Text is as follows
#Composable
fun GreetingSectionExperimental(
name: String = "Philipp"
) {
//var text by remember { mutableStateOf(TextFieldValue("")) }
Column(
verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxSize()
) {
Image(
painterResource(id = R.drawable.ic_launcher_background),
modifier = Modifier
.fillMaxWidth()
.height(80.dp).offset(0.dp,35.dp),
alignment = Alignment.Center,
contentDescription = ""
)
Text(
text = "Login / Sign Up",
Modifier.padding(10.dp).align(CenterHorizontally),
color = textColor, fontSize = 18.sp,
fontWeight = FontWeight.SemiBold
)
}
}
I am getting output as
How to resolve this ? Inside the current what is missing or Column does not support different kind of elements.
You need to remove the property "Offset" from your image
the code should looks like
#Composable
fun GreetingSectionExperimental(
name: String = "Philipp"
) {
//var text by remember { mutableStateOf(TextFieldValue("")) }
Column(
verticalArrangement = Arrangement.Top,
modifier = Modifier.fillMaxSize()
) {
Image(
painterResource(id = R.drawable.ic_launcher_background),
modifier = Modifier
.fillMaxWidth()
.height(80.dp), //Remove the offset here
alignment = Alignment.Center,
contentDescription = ""
)
Text(
text = "Login / Sign Up",
Modifier.padding(10.dp).align(CenterHorizontally),
color = textColor, fontSize = 18.sp,
fontWeight = FontWeight.SemiBold
)
}
}
Best solution is to use Spacer(modifier = Modifier.height(20.dp)). It will create space between the those Elements this in between this is added.

Issue with defining weight to views in Jetpack compose

I want to make a simple jetpack compose layout, using weights. below is the code
Row() {
Column(
Modifier.weight(1f).background(Blue)){
Text(text = "Weight = 1", color = Color.White)
}
Column(
Modifier.weight(2f).background(Yellow)
) {
Text(text = "Weight = 2")
}
}
which will result in a layout like this
but what if my inner views are coming from some other Composable function, which is unaware that its going to be a child of a column or a row?
Row() {
// Calling Some composable function here
}
In that case i am not able to access the Modifier.weight(..) function, because it thinks that its not in the row or column scope, because it is an independent function.
You can add the modifier as parameter in your Composable.
Something like:
#Composable
fun myCard(modifier: Modifier = Modifier, name:String){
Box(modifier){
Text(name,textAlign = TextAlign.Center,)
}
}
In this way the myCard is unaware that its going to be a child of a Column or a Row.
Then in your implementation you can use:
Row(Modifier.padding(16.dp).height(50.dp)) {
myCard(Modifier.weight(1f).background(Color.Yellow),"Weight = 1")
myCard(Modifier.weight(2f).background(Color.Red),"Weight = 2")
}
You can prefix RowScope. or ColumnScope. to your function declaration
#Composable
fun RowScope.SomeComposable() {
// weights should work in here
Column(Modifier.weight(1f)){ /**/ }
}
Row(
modifier = mainRowModifier,
verticalAlignment = rowCenterVerticallyAlign
) {
Row(
verticalAlignment = rowCenterVerticallyAlign,
horizontalArrangement = rowContentArrangementCenter,
modifier = Modifier.weight(.5f, true).wrapContentHeight()
) {
Text(
text = "971",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
Icon(
painter = painterResource(id = resIdDropDownIcon),
contentDescription = null,
modifier = Modifier.padding(start = startPaddingDropdownIcon.dp)
)
}
Divider(
color = dividerColor,
modifier = dividerModifier
)
SimpleTextField(
modifier = Modifier.weight(2f),
value = "",
placeHolder = textFieldPlaceholder,
keyboardType = KeyboardType.Phone,
singleLine = true
)
Text(
text = optionalTextTxt,
modifier = Modifier.weight(.5f, true),
style = MaterialTheme.typography.bodySmall,
fontSize = optionalTextFontSize.sp
)
}
no weight is issue to main row, then i will assign subrow weight to 0.5 and for textField weight will be 2f and last textview weight is issue to 0.5f
then Output will be looks like

Make a Row of rotated Text in Jetpack compose

I want to make a Row of -90 degrees rotated Text Composables to make something like below:
However this code (repro case):
#Preview(showBackground = true, backgroundColor = 0xffffffff)
#Composable
fun Preview_Row_With_Rotated_Text() {
Row {
Text(
text = "A text",
modifier = Modifier
.padding(2.dp)
.rotate(-90f),
maxLines = 1,
)
Text(
text = "A text which is a bit longer",
modifier = Modifier
.padding(2.dp)
.rotate(-90f),
maxLines = 1,
)
Text(
text = "A text which is kinda longer than previous one",
modifier = Modifier
.padding(2.dp)
.rotate(-90f),
maxLines = 1,
)
}
}
produces this:
The Row uses old width of Text composables (the width of non-rotated Text) to place them one after another.
Where is the reason of this problem?
You can try using it in a Column and then rotating that Column by -90f:
#Composable
fun Main() {
Column(
modifier = Modifier
.width(200.dp)
.rotate(-90f)
) {
MyText(text = "Financial Advice")
MyText(text = "Strategy and Marketing")
MyText(text = "Information Technology")
}
}
#Composable
fun MyText(text: String) {
Text(
text = text,
modifier = Modifier
.padding(4.dp)
.fillMaxWidth()
.background(MaterialTheme.colors.secondary)
.padding(16.dp),
textAlign = TextAlign.Center,
maxLines = 1
)
}

Categories

Resources