Jetpack compose date input text
Hi Everyone in this article i am sharing about the Jetpack compose date input text.
In this course you’ll create stunning animations using Jetpack Compose and learn about the API that allows you to create these animations in a snap.
Jetpack Compose is an innovative and super-cool toolkit that allows you to build an native Android UI in a declarative manner. The code that is written in a declarative manner specifies how the UI will appear based on the current state instead of altering the UI every time state changes. This is why Jetpack Compose lets you develop applications that use a more modular design by creating less code, and arranging it into smaller and reuseable components that are simpler to maintain. What is Jetpack Compose’s approach to Animations?
Jetpack compose date input text Example
Create a new Project with jetpack compose activity. and Build your project. after the follow below the steps.
Dependancies
dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' implementation 'androidx.activity:activity-compose:1.4.0' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" }
MainActivity.kt Source Code Jetpack compose date input text.
import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.* import androidx.compose.ui.text.input.* import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.jetpack.speechtotext.ui.theme.SpeechToTextTheme import java.text.SimpleDateFormat import java.time.LocalDateTime import java.time.ZoneId import java.util.*
class MainActivity : ComponentActivity() { private var talk by mutableStateOf("Click to button Speech text ") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { SpeechToTextTheme { Surface(color = MaterialTheme.colors.background) { Scaffold( topBar = { TopAppBar( title = { Text( text = "Jetpack Compose Date Input ", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Left ) } ) } ) { DateInput() } } } } }
Create a Function DateInput.
@Composable fun DateInput() { Column( modifier = Modifier .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { var date by remember { mutableStateOf( TextFieldValue( text = "dd-MM-yyyy" ) ) } DateTextField( value = date, onValueChange = { date = it } ) } } @OptIn(ExperimentalComposeUiApi::class) @Composable fun DateTextField( value: TextFieldValue, modifier: Modifier = Modifier, onValueChange: (TextFieldValue) -> Unit ) { var isBackspacePressed by remember { mutableStateOf(false) } OutlinedTextField( value = value, visualTransformation = DateFormatVisualTransformation(LocalTextStyle.current), keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Number, imeAction = ImeAction.Done ), onValueChange = { // ex: "01-1M-yyyy" -> "011" val date = it.text.takeDigitString() if (date.length < 9) { // if date length is 3 or 5, move cursor to index + 1 // ex: (| = cursor) "01-|1M-yyyy" to "01-1|M-yyyy" val selection = if (!isBackspacePressed) { when (date.length) { 3, 5 -> it.selection.start + 1 else -> it.selection.start } } else it.selection.start onValueChange( it.copy( text = TextFieldDateFormatter.format(it), selection = TextRange(selection) ) ) } }, modifier = modifier .onKeyEvent { event -> if (event.key == Key.Backspace) { isBackspacePressed = true return@onKeyEvent true } else { isBackspacePressed = false } false } ) } class DateFormatVisualTransformation( private val textStyle: TextStyle ): VisualTransformation { override fun filter(text: AnnotatedString): TransformedText { return TransformedText( text = buildAnnotatedString { for (word in text) { withStyle( textStyle.copy( color = if (word.isDigit() || word == '-') textStyle.color else Color.Gray ).toSpanStyle() ) { append(word) } } }, offsetMapping = OffsetMapping.Identity ) } } object TextFieldDateFormatter { private const val ddMMyyyy = "ddMMyyyy" /** * format "ddMMyyyy" to "dd-MMM-yyyy" * @return formatted string, ex: "11-01-2007" or "11-0M-YYYY" */ fun format( fieldValue: TextFieldValue, minYear: Int = 2000, maxYear: Int = 3000 ): String { val builder = StringBuilder() val s = fieldValue.text.replace( oldValue = listOf(" ", ".", ",", "-", "d", "M", "y"), newValue = "" ) if (s.length != 8) { for (i in 0 until 8) { builder.append( try { s[i] } catch (e: Exception) { ddMMyyyy[i] } ) } } else builder.append(s) repeat(3) { when (it) { 0 -> { val day = try { "${builder[0]}${builder[1]}".toInt() } catch (e: Exception) { null } if (day != null) { val dayMax = day .coerceIn( minimumValue = 1, maximumValue = 31, ) .toString() builder.replace( 0, 2, if (dayMax.length == 1) "0$dayMax" else dayMax ) } } 1 -> { val month = try { "${builder[2]}${builder[3]}".toInt() } catch (e: Exception) { null } if (month != null) { val monthMax = month .coerceIn( minimumValue = 1, maximumValue = 12, ) .toString() builder.replace( 2, 4, if (monthMax.length == 1) "0$monthMax" else monthMax ) } } 2 -> { val year = try { "${builder[4]}${builder[5]}${builder[6]}${builder[7]}".toInt() } catch (e: Exception) { null } if (year != null) { val yearMaxMin = year.coerceIn( minimumValue = minYear, maximumValue = maxYear ).toString() builder.replace(4, 6, yearMaxMin.substring(0, 2)) builder.replace(6, 8, yearMaxMin.substring(2, 4)) } } } } return builder.toString() .addStringBefore("-", 2) // dd-MMyyyy .addStringBefore("-", 5) // dd-MM-yyyy } /** * format time in milli second to formatted date * @return formatted string, ex: "11-01-2007" */ // fun format(timeInMillis: Long): String { // return SimpleDateFormat("dd-MM-yyyy", deviceLocale).format(timeInMillis) // } /** * check if formattedDate is valid * * "01-01-2000" -> valid * "01-0M-YYYY" -> not valid * @param formattedDate "01-01-2000" */ fun isValid(formattedDate: String): Boolean { return formattedDate.takeDigitString().length == 8 } /** * convert formatted string date to time in millis * @param formattedDate "01-01-2000" * @return time in millis */ @RequiresApi(Build.VERSION_CODES.O) fun parse(formattedDate: String): Long { val date = "${formattedDate[6]}${formattedDate[7]}${formattedDate[8]}${formattedDate[9]}-" .plus("${formattedDate[3]}${formattedDate[4]}-") .plus("${formattedDate[0]}${formattedDate[1]}") .plus("T00:00") return LocalDateTime.parse(date) .atZone(ZoneId.of(TimeZone.getDefault().id, ZoneId.SHORT_IDS)) .toInstant() .toEpochMilli() } } /** * take a string that is a number * * ex: * val s = "123a456b" * s.takeDigitString() => "123456" * @author kafri8889 */ fun String.takeDigitString(): String { var builder = "" forEach { if (it.isDigit()) builder += it } return builder } /** * add a new string before the given index * @author kafri8889 */ fun String.addStringBefore(s: String, index: Int): String { val result = StringBuilder() forEachIndexed { i, c -> if (i == index) { result.append(s) result.append(c) } else result.append(c) } return result.toString() } /** * Returns a new string with all occurrences of oldValue replaced with newValue. * @author kafri8889 */ fun String.replace( oldValue: List<String>, newValue: String, ignoreCase: Boolean = false ): String { var result = this oldValue.forEach { s -> if (this.contains(s)) { result = result.replace(s, newValue, ignoreCase) } } return result }
Now run your project and see the output. to enter the date month and year in input filed jetpack compose. Jetpack compose date input text.
Read More Tutorial