Text Field Gradient Border On Focus Jetpack Compose? - android

I am trying to change a gradient border on the input focus. The example below is what I want to achieve, but how can I make 'focusedBorderColor' into a gradient border?
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = md_theme_light_primary,
unfocusedBorderColor =md_theme_light_inversePrimary,
focusedLabelColor = Color.White,
trailingIconColor = Color.White,
// disabledTextColor = NaviBlue
),

You can use CardView() with BasicTextField()
var name by remember {
mutableStateOf("")
}
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
val focusRequester = remember {
FocusRequester()
}
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 20.dp)
.shadow(ambientColor = Color.Blue, spotColor = Color.Cyan, elevation = if (isFocused) 15.dp else 0.dp, clip = true, shape = CircleShape) ,
shape = CircleShape
) {
BasicTextField(
value = name,
onValueChange = { name = it },
interactionSource = interactionSource,
modifier = Modifier
.fillMaxWidth()
.border(
width = 1.dp,
brush = Brush.horizontalGradient(listOf(Color.Cyan, Color.Blue)),
shape = CircleShape
)
.padding(16.dp)
.background(Color.White)
.focusRequester(focusRequester),
)
}
Below is sample gif!

Related

Jetpack Compose Dialog view size(Height or width) is not updated after initial recomposition

I have a dialog where user have 2 option. each option have different Compose UI view. The problem is that the height of the dialog is never updated according to the user selected option. So Is there any way to change height of Dialog dynamically according to the content.
Here is my code which I am using to show a dialog
var type = remember { mutableStateOf("Adult") }
Dialog(
onDismissRequest = { onDismiss() }, properties = DialogProperties(
dismissOnBackPress = true, dismissOnClickOutside = true
),
) {
Card(
shape = RoundedCornerShape(12.dp),
modifier = Modifier.fillMaxWidth(),
elevation = 8.dp
) {
Column(
modifier = Modifier
.height(IntrinsicSize.Min)
.background(Color.White)
.padding(top = 10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row() {
SemiBoldTextSmall(
text = "Adult",
textColor = if (type.value == "Adult") Color.Black else Color.LightGray,
fontSize = 14.sp,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
.weight(1f)
.clickable {
type.value = "Adult"
})
SemiBoldTextSmall(text = "Kids",
textColor = if (type.value == "Kids") Color.Black else Color.LightGray,
fontSize = 14.sp,
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
.weight(1f)
.clickable {
type.value = "Kids"
})
}
if (type.value == "Kids") {
EditBox(modifier = Modifier
.padding(top = 10.dp, start = 20.dp, end = 20.dp)
.background(color = Color.White, shape = RoundedCornerShape(10.dp))
.border(
width = 1.dp,
color = Color.LightGray,
shape = RoundedCornerShape(10.dp)
)
.wrapContentSize(),
placeholder = "Mobile Number",
text = "",
textSize = 14.sp,
keyboardType = KeyboardType.Number,
onValueChange = {
})
} else {
EditBox(modifier = Modifier
.padding(top = 30.dp, start = 20.dp, end = 20.dp)
.background(color = Color.White, shape = RoundedCornerShape(10.dp))
.border(
width = 1.dp,
color = Color.LightGray,
shape = RoundedCornerShape(10.dp)
)
.wrapContentSize(),
placeholder = "Name",
text = "",
textSize = 14.sp,
onValueChange = {
})
EditBox(modifier = Modifier
.padding(top = 10.dp, start = 20.dp, end = 20.dp)
.background(color = Color.White, shape = RoundedCornerShape(10.dp))
.border(
width = 1.dp,
color = Color.LightGray,
shape = RoundedCornerShape(10.dp)
)
.wrapContentSize(),
placeholder = "Mobile Number",
text = "",
textSize = 14.sp,
keyboardType = KeyboardType.Number,
onValueChange = {
})
}
SemiBoldTextSmall(text = "+ ADD",
textColor = Color.White,
fontSize = 14.sp,
modifier = Modifier
.padding(top = 30.dp)
.fillMaxWidth()
.background(color = greenColor, shape = RectangleShape)
.padding(10.dp)
.clickable {
onSubmit()
})
}
}
}
Use Modifier.requiredHeight() instead of height()
Modifier.requiredHeight(): Declare the height of the content to be exactly the same as the min or max intrinsic height of the content.

jetpack compose shadow strange behaviour

I am trying to build an text field with shadow outside
This is the result I achieved so on.
But if you zoom in the picture you will see some rectangle background under white text field (please look at the corners outside of text field, there is a background)
How can I remove that background ?
#Composable
fun MyTextField() {
var text by remember {
mutableStateOf("")
}
Box(
modifier = Modifier
.padding(15.dp)
.shadow(5.dp)
.background(color = Color.White, shape = RoundedCornerShape(10.dp))
.fillMaxWidth()
.height(50.dp),
contentAlignment = Alignment.Center,
) {
TextField(
value = text,
onValueChange = { text = it },
label = { Text(text = "Phone number", color = Color.Gray, fontSize = 14.sp) },
modifier = Modifier
.fillMaxSize()
.background(color = Color.Transparent, shape = RoundedCornerShape(10.dp)),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
),
)
}
}
As default the shadow modifier uses a RectangleShape, it is the reason of your issue:
Apply the same shape to the shadow and background modifiers:
val shape = RoundedCornerShape(10.dp)
Box(
modifier = Modifier
.padding(15.dp)
.shadow(
elevation = 5.dp,
shape = shape
)
.background(color = Color.White, shape = shape)
.fillMaxWidth()
.height(50.dp),
contentAlignment = Alignment.Center,
)

BottomSheetScaffold is overriding the background color of its parent

I'm trying out BottomSheetScaffold and I just found a strange behavior (maybe a bug) when using it.
I put it inside a Box { } that has a cyan background color:
composable(route = "my_route") {
Box(
modifier = Modifier
.fillMaxSize()
.background(color = Color.Cyan),
) {
val coroutineScope = rememberCoroutineScope()
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState()
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
sheetPeekHeight = 0.dp,
sheetBackgroundColor = Color.Red,
sheetContent = {
Box(
modifier = Modifier
.fillMaxWidth()
.height(96.dp)
)
}
) { }
LaunchedEffect(key1 = null) {
delay(1_500)
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.expand()
}
}
Text(
modifier = Modifier
.align(alignment = Alignment.Center),
text = "Hello World",
fontSize = 28.sp
)
}
}
But when I run the app and check that screen, the cyan background color is gone:
Here's how the background part should be:
Am I forgetting to do something, is this the expected behavior or is this a bug?
White color comes from MaterialTheme.colors.background, which is default value of BottomSheetScaffold.backgroundColor parameter. It's drawn on top of your Box background so it's not visible.
Also you don't need a Box here, it's intended to place content inside content parameter:
val coroutineScope = rememberCoroutineScope()
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState()
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
sheetPeekHeight = 0.dp,
sheetBackgroundColor = Color.Red,
backgroundColor = Color.Cyan,
sheetContent = {
Box(
modifier = Modifier
.fillMaxWidth()
.height(96.dp)
)
}
) {
LaunchedEffect(key1 = null) {
delay(1_500)
coroutineScope.launch {
bottomSheetScaffoldState.bottomSheetState.expand()
}
}
Box(Modifier.fillMaxSize()) {
Text(
modifier = Modifier
.align(alignment = Alignment.Center),
text = "Hello World",
fontSize = 28.sp
)
}
}

Compose rounded Button with transparent background

I am trying to display a Button with rounded corners and a 50% transparent background. My current attempt looks like this:
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Yellow
) {
Column(modifier = Modifier.padding(10.dp)) {
Button(
modifier = Modifier
.clip(CircleShape),
onClick = { },
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White.copy(alpha = 0.5f))
) {
Text(
text = "My Button",
textAlign = TextAlign.Center
)
}
}
}
}
The result is not very pretty:
It looks like the issue is with with the shading, but I'm not sure how to remove it and just show the same color within the whole shape.
Turns out the shadow will disappear when the elevation is removed.
Button(
modifier = Modifier
.clip(CircleShape),
onClick = { },
elevation = null,
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White.copy(alpha = 0.5f))
) { ... }
Button is just a Surface wrapping the content that you provide. You could check the source. So, I just tweaked it a little
#Composable
fun HollowButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
colors: ButtonColors = ButtonDefaults.buttonColors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: #Composable RowScope.() -> Unit
) {
val contentColor by colors.contentColor(enabled)
Surface(
modifier = modifier,
shape = shape,
color = colors.backgroundColor(enabled).value.copy(0.5f), //Basically I refactored the alpha modification to here
contentColor = contentColor.copy(alpha = 1f),
border = border,
elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp,
onClick = onClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple()
) {
CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSize(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
Works like a charm.

How to create a TextField with underbar, without any background or border?

I'm trying to create a TextField, in Jetpack compose with an underbar but without any other border or background. How do I do this?
This is the code I'm currently using:
val query = remember {mutableStateOf("")}
TextField(
value = query.value,
onValueChange = { newValue -> query.value = newValue },
label={Text("Dummy", color = colorResource(id = R.color.fade_green))},
textStyle = TextStyle(
textAlign = TextAlign.Start,
color = colorResource(id = R.color.fade_green),
fontFamily = FontFamily(Font(R.font.poppins_regular)),
fontSize = 14.sp,
),
modifier = Modifier
.padding(start = 30.dp).border(0.dp, Color.Red),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent
)
)
Starting with 1.2.0 you can use the BasicTextField + TextFieldDecorationBox.
Something like:
BasicTextField(
value = text,
onValueChange = {text = it},
interactionSource = interactionSource,
textStyle = mergedTextStyle,
enabled = enabled,
singleLine = true,
modifier = Modifier
.background(
color = White, //Background color
shape = TextFieldDefaults.TextFieldShape
)
.indicatorLine(
enabled = enabled,
isError = false,
interactionSource = interactionSource,
colors = colors,
focusedIndicatorLineThickness = 2.dp, //width of the indicator
unfocusedIndicatorLineThickness = 2.dp
)
) {
TextFieldDefaults.TextFieldDecorationBox(
value = text,
enabled = enabled,
singleLine = true,
innerTextField = it,
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
label = { Text("Label") },
)
}
With the 1.0.0 you can just use the colors attribute to define a Color.Transparent background.
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = {
text = it
},
label = { Text("label") },
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
//Color of indicator = underbar
focusedIndicatorColor = ....,
unfocusedIndicatorColor = ....,
disabledIndicatorColor = ....
)
)
If you want to change the indicatorWidth currently there isn't a built-in parameter.
You can use the .drawBehind modifier to draw a line. Something like:
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
val indicatorColor = if (isFocused) Color.Red else Color.Gray
val indicatorWidth = 4.dp
TextField(
value = text,
onValueChange = {
text = it },
label={Text("Label")},
interactionSource = interactionSource,
modifier = Modifier
.drawBehind {
val strokeWidth = indicatorWidth.value * density
val y = size.height - strokeWidth / 2
drawLine(
indicatorColor,
Offset(0f, y),
Offset(size.width, y),
strokeWidth
)
},
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
focusedIndicatorColor = Transparent,
unfocusedIndicatorColor = Transparent,
disabledIndicatorColor = Transparent
)
)

Categories

Resources