@@ -2,6 +2,9 @@ package top.yukonga.miuix.kmp.basic
22
33import androidx.compose.animation.animateColorAsState
44import androidx.compose.animation.core.animateDpAsState
5+ import androidx.compose.animation.core.spring
6+ import androidx.compose.animation.fadeIn
7+ import androidx.compose.animation.fadeOut
58import androidx.compose.foundation.background
69import androidx.compose.foundation.border
710import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -48,6 +51,7 @@ import top.yukonga.miuix.kmp.utils.SmoothRoundedCornerShape
4851 * @param cornerRadius The corner radius of the [TextField].
4952 * @param label The label to be displayed when the [TextField] is empty.
5053 * @param labelColor The color of the label.
54+ * @param useLabelAsPlaceholder Whether to use the label as a placeholder.
5155 * @param enabled Whether the [TextField] is enabled.
5256 * @param readOnly Whether the [TextField] is read-only.
5357 * @param textStyle The text style to be applied to the [TextField].
@@ -73,6 +77,7 @@ fun TextField(
7377 cornerRadius : Dp = 18.dp,
7478 label : String = "",
7579 labelColor : Color = MiuixTheme .colorScheme.onSecondaryContainer,
80+ useLabelAsPlaceholder : Boolean = false,
7681 enabled : Boolean = true,
7782 readOnly : Boolean = false,
7883 textStyle : TextStyle = MiuixTheme .textStyles.main,
@@ -98,12 +103,12 @@ fun TextField(
98103 val isFocused by interactionSource.collectIsFocusedAsState()
99104 val borderWidth by animateDpAsState(if (isFocused) 2 .dp else 0 .dp)
100105 val borderColor by animateColorAsState(if (isFocused) MiuixTheme .colorScheme.primary else backgroundColor)
101- val labelOffsetY by animateDpAsState(if (value.text.isNotEmpty()) - (insideMargin.height / 2 ) else 0 .dp)
102- val innerTextOffsetY by animateDpAsState(if (value.text.isNotEmpty()) (insideMargin.height / 2 ) else 0 .dp)
103- val labelFontSize by animateDpAsState(if (value.text.isNotEmpty()) 10 .dp else 16 .dp)
106+ val labelOffsetY by animateDpAsState(if (value.text.isNotEmpty() && useLabelAsPlaceholder == false ) - (insideMargin.height / 2 ) else 0 .dp)
107+ val innerTextOffsetY by animateDpAsState(if (value.text.isNotEmpty() && useLabelAsPlaceholder == false ) (insideMargin.height / 2 ) else 0 .dp)
108+ val labelFontSize by animateDpAsState(if (value.text.isNotEmpty() && useLabelAsPlaceholder == false ) 10 .dp else 16 .dp)
104109 val border = Modifier .border(borderWidth, borderColor, RoundedCornerShape (cornerRadius))
105- val labelOffset = if (label != " " ) Modifier .offset(y = labelOffsetY) else Modifier
106- val innerTextOffset = if (label != " " ) Modifier .offset(y = innerTextOffsetY) else Modifier
110+ val labelOffset = if (label != " " && useLabelAsPlaceholder == false ) Modifier .offset(y = labelOffsetY) else Modifier
111+ val innerTextOffset = if (label != " " && useLabelAsPlaceholder == false ) Modifier .offset(y = innerTextOffsetY) else Modifier
107112
108113 BasicTextField (
109114 value = value,
@@ -144,14 +149,24 @@ fun TextField(
144149 .weight(1f )
145150 .then(paddingModifier)
146151 ) {
147- Text (
148- text = label,
149- textAlign = TextAlign .Start ,
150- fontWeight = FontWeight .Medium ,
151- fontSize = labelFontSize.value.sp,
152- modifier = Modifier .then(labelOffset),
153- color = labelColor
154- )
152+ androidx.compose.animation.AnimatedVisibility (
153+ visible = if (useLabelAsPlaceholder) value.text.isEmpty() else true ,
154+ enter = fadeIn(
155+ spring(stiffness = 2500f )
156+ ),
157+ exit = fadeOut(
158+ spring(stiffness = 5000f )
159+ )
160+ ) {
161+ Text (
162+ text = label,
163+ textAlign = TextAlign .Start ,
164+ fontWeight = FontWeight .Medium ,
165+ fontSize = labelFontSize.value.sp,
166+ modifier = Modifier .then(labelOffset),
167+ color = labelColor
168+ )
169+ }
155170 Box (
156171 modifier = Modifier .then(innerTextOffset),
157172 contentAlignment = Alignment .BottomStart
@@ -179,6 +194,7 @@ fun TextField(
179194 * @param cornerRadius The corner radius of the [TextField].
180195 * @param label The label to be displayed when the [TextField] is empty.
181196 * @param labelColor The color of the label.
197+ * @param useLabelAsPlaceholder Whether to use the label as a placeholder.
182198 * @param enabled Whether the [TextField] is enabled.
183199 * @param readOnly Whether the [TextField] is read-only.
184200 * @param textStyle The text style to be applied to the [TextField].
@@ -204,6 +220,7 @@ fun TextField(
204220 cornerRadius : Dp = 16.dp,
205221 label : String = "",
206222 labelColor : Color = MiuixTheme .colorScheme.onSecondaryContainer,
223+ useLabelAsPlaceholder : Boolean = false,
207224 enabled : Boolean = true,
208225 readOnly : Boolean = false,
209226 textStyle : TextStyle = MiuixTheme .textStyles.main,
@@ -229,12 +246,12 @@ fun TextField(
229246 val isFocused by interactionSource.collectIsFocusedAsState()
230247 val borderWidth by animateDpAsState(if (isFocused) 2.0 .dp else 0 .dp)
231248 val borderColor by animateColorAsState(if (isFocused) MiuixTheme .colorScheme.primary else backgroundColor)
232- val labelOffsetY by animateDpAsState(if (value.isNotEmpty()) - (insideMargin.height / 2 ) else 0 .dp)
233- val innerTextOffsetY by animateDpAsState(if (value.isNotEmpty()) (insideMargin.height / 2 ) else 0 .dp)
234- val labelFontSize by animateDpAsState(if (value.isNotEmpty()) 10 .dp else 16 .dp)
249+ val labelOffsetY by animateDpAsState(if (value.isNotEmpty() && useLabelAsPlaceholder == false ) - (insideMargin.height / 2 ) else 0 .dp)
250+ val innerTextOffsetY by animateDpAsState(if (value.isNotEmpty() && useLabelAsPlaceholder == false ) (insideMargin.height / 2 ) else 0 .dp)
251+ val labelFontSize by animateDpAsState(if (value.isNotEmpty() && useLabelAsPlaceholder == false ) 10 .dp else 16 .dp)
235252 val border = Modifier .border(borderWidth, borderColor, RoundedCornerShape (cornerRadius))
236- val labelOffset = if (label != " " ) Modifier .offset(y = labelOffsetY) else Modifier
237- val innerTextOffset = if (label != " " ) Modifier .offset(y = innerTextOffsetY) else Modifier
253+ val labelOffset = if (label != " " && useLabelAsPlaceholder == false ) Modifier .offset(y = labelOffsetY) else Modifier
254+ val innerTextOffset = if (label != " " && useLabelAsPlaceholder == false ) Modifier .offset(y = innerTextOffsetY) else Modifier
238255
239256 BasicTextField (
240257 value = value,
@@ -274,14 +291,24 @@ fun TextField(
274291 .weight(1f )
275292 .then(paddingModifier)
276293 ) {
277- Text (
278- text = label,
279- textAlign = TextAlign .Start ,
280- fontWeight = FontWeight .Medium ,
281- fontSize = labelFontSize.value.sp,
282- modifier = Modifier .then(labelOffset),
283- color = labelColor
284- )
294+ androidx.compose.animation.AnimatedVisibility (
295+ visible = if (useLabelAsPlaceholder) value.isEmpty() else true ,
296+ enter = fadeIn(
297+ spring(stiffness = 2500f )
298+ ),
299+ exit = fadeOut(
300+ spring(stiffness = 5000f )
301+ )
302+ ) {
303+ Text (
304+ text = label,
305+ textAlign = TextAlign .Start ,
306+ fontWeight = FontWeight .Medium ,
307+ fontSize = labelFontSize.value.sp,
308+ modifier = Modifier .then(labelOffset),
309+ color = labelColor
310+ )
311+ }
285312 Box (
286313 modifier = Modifier .then(innerTextOffset),
287314 contentAlignment = Alignment .BottomStart
0 commit comments