Jetpack Glance version 1.0.0-alpha03
I want to do the following
Row {
Text(text = "Test text", modifier = GlanceModifier.weight(1f))
Image(...)
}
However, it looks like there is no weight modifier for GlanceModifier?
If not what is the best way to get the same result?
I figured out how to make it work:
Row(modifier = GlanceModifier.fillMaxWidth()) {
Text(text = "Test text", modifier = GlanceModifier.defaultWeight())
Image(...)
}
Related
I am trying to make the title of a screen editable.
MediumTopAppBar(
title = {
val name: String? = "Some Title"
var input by remember { mutableStateOf(name ?: "") }
when (state.isEditingTitle) {
true ->
TextField(
value = input,
onValueChange = { input = it },
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {
callbacks.onEditTitleChange(editTitle = false, updatedTitle = input)
})
)
false -> {
Text(
modifier = Modifier.clickable { callbacks.onEditTitleChange(true, null) },
text = name ?: "(No Title)"
)
}
}
},
... more app bar parameters
}
When I click on the title Text(...) and the view gets recomposed the AppBar shows two TextFields
How do I ignore the top one and only show the one in the bottom, like the Text() is only shown in the bottom?
(Fyi: the two TextInputs have their own remembered state and calls the callback with their own respective value)
Bonus question: How do I handle the remembered state "input" so that it resets every time the onDone keyboard action is triggered? Instead of val name: String? = "Some Title" it would of course be something in the line of val name: String? = state.stateModel.title
I found out why it does this, but I have no idea how to solve it (except for just making my own views and placing it close by)
It's easy to see when looking at the function for the MediumTopBar
// androidx.compose.material3.AppBar.kt
#ExperimentalMaterial3Api
#Composable
fun MediumTopAppBar(
title: #Composable () -> Unit,
modifier: Modifier = Modifier,
navigationIcon: #Composable () -> Unit = {},
actions: #Composable RowScope.() -> Unit = {},
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TwoRowsTopAppBar(
modifier = modifier,
title = title,
titleTextStyle = MaterialTheme.typography.fromToken(TopAppBarMediumTokens.HeadlineFont),
smallTitleTextStyle = MaterialTheme.typography.fromToken(TopAppBarSmallTokens.HeadlineFont),
titleBottomPadding = MediumTitleBottomPadding,
smallTitle = title, // <- this thing, right here
navigationIcon = navigationIcon,
actions = actions,
colors = colors,
windowInsets = windowInsets,
maxHeight = TopAppBarMediumTokens.ContainerHeight,
pinnedHeight = TopAppBarSmallTokens.ContainerHeight,
scrollBehavior = scrollBehavior
)
}
There's some internal state shenanigans going on, probably checking for a Text being shown in the 2nd TopAppBarLayout (more digging required to find that), but not for any other view.
TwoRowsTopAppBar and TopAppBarLayout are not public, and can't be used directly.
This is explains why, but it would be interesting to see how to solve it (still using Medium or Large -TopAppBar)
it is stupid thing devs overlooked and should be warned against, at least. The answer is do not give default colors to your Typography TextStyles.
private val BodySmall = TextStyle(
fontSize = 10.sp,
lineHeight = 12.sp,
fontWeight = FontWeight.SemiBold,
fontFamily = Manrope,
color = Color.Black // REMOVE THIS
)
val OurTypography = Typography(
...
bodySmall = BodySmall
)
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,
)
)
}
I am going to design a layout with a bottomsheetscaffold with sheetPeekHeight to be 100 dp in order to show the sheet content. I also need to put a lazyColumn for the main content of the bottomsheetscaffold. But when the lazy column scrolls to the end, the final item will be behind the bottom sheet. How can I make the final item of the column be above the sheet?
Here is the code for the bottom sheet:
#ExperimentalMaterialApi
#Composable
fun HomeScreen() {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)
val coroutineScope = rememberCoroutineScope()
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
Text("this is test", modifier = Modifier.fillMaxWidth().height(60.dp))
},
sheetPeekHeight = 100.dp,
sheetShape = RoundedCornerShape(topEnd = 52.dp, topStart = 52.dp),
backgroundColor = Color.White
) {
MainContent()
}
}
#Composable
fun MainContent() {
LazyColumn {
items(count = 5) { itemIndex ->
when (itemIndex) {
0 -> {
Image(modifier = Modifier
.fillMaxWidth()
.height(100.dp), contentDescription = "test",
painter = painterResource(id = R.drawable.image))
}
}
}
}
}
Spacer(modifier=Modifier.height(100.dp)) I think fits better than a box here.
In your case it is easier to use fixed height, but if your content is dynamic you can also calculate bottomSheet height based on screenheight - bottomSheetOffset
fun YourComposable{
...
val bottomSheetHeight =
configuration.screenHeightDp.dp - bottomSheetScaffoldState.bottomSheetState.offset.value.pxToDp
...
}
private val Float.pxToDp: Dp
get() = (this / Resources.getSystem().displayMetrics.density).dp
As a workaround, I added an empty box with the same height as peekheight to the end of the lazycloumn. But I'm still interested in a better solution.
I am working in Android Jetpack Compose.
I have three TextField in a in a Column. I would like the third and/or last text field to be scrollable. How can I do that?
TextField example with horizontalScroll
#Composable
fun Test() {
TextField(
value = "long1 long2 long3 long4 long5 long6 long7 long8 long9 long10 long11 long12 text",
onValueChange = {},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(rememberScrollState())
)
}
TextField example with scrollable
#Composable
fun Test() {
var offset by remember { mutableStateOf(0f) }
TextField(value = "long1 long2 long3 long4 long5 long6 long7 long8 long9 long10 long11 long12 text",
onValueChange = {},
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.scrollable(
orientation = Orientation.Horizontal,
state = rememberScrollableState { delta ->
offset += delta
delta
}
)
)
}
more info there
https://developer.android.com/jetpack/compose/gestures?authuser=1#scrollable-modifier.
I have a function:
#Composable
fun sendNewSmsText(passedModifier: Modifier){
Text(text = stringResource(R.string.when_sms_not_received),
style = Typography.body2.copy(),
modifier = Modifier.padding(4.dp)
)
}
how to add a passedModifier to the text's end?
like:
#Composable
fun sendNewSmsText(modifier: Modifier){
Text(text = stringResource(R.string.when_sms_not_received),
style = Typography.body2.copy(),
modifier = Modifier.padding(4.dp).passedModifier
)
}
Using Modifier.then()
https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#then(androidx.compose.ui.Modifier)
Modifier.padding(4.dp).then(passedModifier)