diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0765b5 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# JetPackCompose Basic + +In this project, you will know how to open keyboard at screen start-up and get focus on TextField. + +First know this, + +➡ FocusRequester: +The FocusRequester is used in conjunction with Modifier.focusRequester to send requests to change focus. + +➡ SoftwareKeyboardController: +SoftwareKeyboardController that can control the current software keyboard. + +Steps: +1. Initialize FocusRequester and SoftwareKeyboardController +val keyboard = LocalSoftwareKeyboardController.current +val focusRequester = remember { FocusRequester() } + +2. Call requestFocus() method to get focus and show the keyboard and put all this code inside LanchedEffect to run at once +LaunchedEffect(Unit) { + focusRequester.requestFocus() + keyboard?.show() +} +3. Add focusRequester modifier and pass focusRequester of the TextField +TextField(Modifier.focusRequester(focusRequester),..) + +4. Add a keyboard Options as Done and Action to hide keyboard when submit input. + +keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), +keyboardActions = KeyboardActions( + onDone = { + keyboard?.hide() +}) + +# Video +https://github.com/KaushalVasava/JetPackCompose_Basic/assets/49050597/97046668-2033-4c53-b374-da35b5ead465 + +# Author +Kaushal Vasava + diff --git a/app/build.gradle b/app/build.gradle index 75677b5..c057e38 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { android { namespace 'com.lahsuak.apps.jetpackcomposebasic' - compileSdk 33 + compileSdk 34 defaultConfig { applicationId "com.lahsuak.apps.jetpackcomposebasic" minSdk 23 - targetSdk 33 + targetSdk 34 versionCode 1 versionName "1.0" @@ -27,17 +27,17 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '17' } buildFeatures { compose true } composeOptions { - kotlinCompilerExtensionVersion '1.1.1' + kotlinCompilerExtensionVersion '1.4.7' } packagingOptions { resources { @@ -48,15 +48,15 @@ android { dependencies { - implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' - implementation 'androidx.activity:activity-compose:1.6.1' + implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1' + implementation 'androidx.activity:activity-compose:1.7.2' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.compose.material3:material3:1.1.0-alpha03' + implementation 'androidx.compose.material3:material3:1.2.0-alpha03' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.4' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" diff --git a/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/MainActivity.kt b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/MainActivity.kt index 187ee32..60734b5 100644 --- a/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/MainActivity.kt +++ b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/MainActivity.kt @@ -3,13 +3,36 @@ package com.lahsuak.apps.jetpackcomposebasic import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.lahsuak.apps.jetpackcomposebasic.ui.screen.SplashScreen import com.lahsuak.apps.jetpackcomposebasic.ui.theme.JetPackComposeBasicTheme class MainActivity : ComponentActivity() { @@ -22,29 +45,56 @@ class MainActivity : ComponentActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - Greeting("Android") + LoginScreen() } } } } } -/*** -Composable functions : -A composable function is a regular function annotated with @Composable. -This enables your function to call other @Composable functions within it. -You can see how the Greeting function is marked as @Composable. -This function will produce a piece of UI hierarchy displaying the given input, -String. Text is a composable function provided by the library. -***/ + +@OptIn(ExperimentalComposeUiApi::class) @Composable -fun Greeting(name: String) { - Text(text = "Hello $name!") +fun LoginScreen() { + val keyboard = LocalSoftwareKeyboardController.current + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(Unit) { + // requesting to get focus + focusRequester.requestFocus() + // show keyboard at start-up + keyboard?.show() + } + var name by rememberSaveable { + mutableStateOf("") + } + + Column(Modifier.fillMaxSize().padding(16.dp)) { + OutlinedTextField( + value = name, + onValueChange = { + name = it + }, + placeholder = { + Text("Enter your name") + }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions( + onDone = { + // hide keyboard when submit input + keyboard?.hide() + }), + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) // add focusRequester to get focus on textfield + .background(MaterialTheme.colorScheme.surfaceVariant), + ) + } } @Preview(showBackground = true) @Composable fun DefaultPreview() { JetPackComposeBasicTheme { - Greeting("Android") + LoginScreen() } } \ No newline at end of file diff --git a/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/NavigationItem.kt b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/NavigationItem.kt new file mode 100644 index 0000000..db0615c --- /dev/null +++ b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/NavigationItem.kt @@ -0,0 +1,2 @@ +package com.lahsuak.apps.jetpackcomposebasic.ui.screen + diff --git a/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/SplashScreen.kt b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/SplashScreen.kt new file mode 100644 index 0000000..523a214 --- /dev/null +++ b/app/src/main/java/com/lahsuak/apps/jetpackcomposebasic/ui/screen/SplashScreen.kt @@ -0,0 +1,115 @@ +package com.lahsuak.apps.jetpackcomposebasic.ui.screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.LocationOn +import androidx.compose.material.icons.filled.Person +import androidx.compose.material3.Button +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.FilledTonalIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.lahsuak.apps.jetpackcomposebasic.R + +@Composable +fun SplashScreen() { + Box(Modifier.fillMaxSize()) { + Column( + Modifier + .fillMaxWidth() + .padding(16.dp), + verticalArrangement = Arrangement.Center, + ) { + Text( + "Annpurna", + fontSize = 20.sp, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Spacer(modifier = Modifier.height(16.dp)) + Image( + painter = painterResource(id = R.drawable.food_logo), contentDescription = "food", + contentScale = ContentScale.Crop, + modifier = Modifier + .size(300.dp) + .align(Alignment.CenterHorizontally) + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + "A good food make your life healthier", + fontSize = 32.sp, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.onSurface, + textAlign = TextAlign.Center, + fontFamily = FontFamily.Serif, + letterSpacing = 2.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Spacer(modifier = Modifier.height(16.dp)) + FilledTonalButton( + onClick = {}, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) { + Icon(Icons.Default.LocationOn, contentDescription = null) + Spacer(modifier = Modifier.width(4.dp)) + Text("Choose language") + } + Spacer(modifier = Modifier.height(16.dp)) + Text( + "Login or registration", + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onSurface + ) + Spacer(modifier = Modifier.height(8.dp)) + FilledTonalButton( + onClick = { /*TODO*/ }, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) { + Icon(Icons.Default.Person, contentDescription = null) + Spacer(modifier = Modifier.width(4.dp)) + Text("Google SignIn") + } + Spacer(modifier = Modifier.height(16.dp)) + Text("OR", Modifier.align(Alignment.CenterHorizontally)) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { /*TODO*/ }, Modifier.fillMaxWidth()) { + Text("Login") + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewSplashScreen() { + MaterialTheme { + Surface(modifier = Modifier.background(MaterialTheme.colorScheme.background)) { + SplashScreen() + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/food_logo.webp b/app/src/main/res/drawable/food_logo.webp new file mode 100644 index 0000000..987f701 Binary files /dev/null and b/app/src/main/res/drawable/food_logo.webp differ diff --git a/build.gradle b/build.gradle index e868fc8..9546bb2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ buildscript { ext { - compose_version = '1.3.2' + compose_version = '1.4.7' } }// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '7.3.0' apply false - id 'com.android.library' version '7.3.0' apply false - id 'org.jetbrains.kotlin.android' version '1.6.10' apply false + id 'com.android.application' version '8.1.0' apply false + id 'com.android.library' version '8.1.0' apply false + id 'org.jetbrains.kotlin.android' version '1.8.21' apply false } \ No newline at end of file