Tugas 7 - Login Page sederhana
Nama : Widian Sasi Disertasiani
NRP : 5025211024
Kelas : PPB D
Materi : Membuat Login Page Sederhana
Pada tugas kali ini, kami ditugaskan untuk membuat aplikasi login page sederhana.
Github: SimpleLoginPage
Yt: Demo
Code :
package com.example.simpleloginpage
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.simpleloginpage.ui.theme.SimpleLoginPageTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
SimpleLoginPageTheme {
LoginScreen()
}
}
}
}
@Composable
fun LoginScreen() {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var isPasswordVisible by remember { mutableStateOf(false) }
var passwordError by remember { mutableStateOf<String?>(null) }
// Validate password (must contain at least one uppercase letter and one number)
fun validatePassword(pass: String) {
passwordError = when {
!pass.any { it.isUpperCase() } -> "Password must contain at least one uppercase letter."
!pass.any { it.isDigit() } -> "Password must contain at least one number."
else -> null
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
listOf(Color(0xFFF6F8FB), Color(0xFFEBEDF0))
)
)
.padding(horizontal = 32.dp, vertical = 48.dp)
) {
Column(
modifier = Modifier
.fillMaxSize()
.wrapContentHeight()
.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
"Welcome Back!",
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
color = Color(0xFF2C3E50)
)
Text(
"Please sign in to continue",
fontSize = 16.sp,
color = Color.Gray,
modifier = Modifier.padding(top = 4.dp, bottom = 32.dp)
)
// Username Field
OutlinedTextField(
value = username,
onValueChange = { username = it },
placeholder = { Text("Enter username") },
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp)),
colors = OutlinedTextFieldDefaults.colors(
unfocusedBorderColor = Color(0xFFE0E0E0),
focusedBorderColor = Color(0xFF448AFF),
unfocusedContainerColor = Color.White,
focusedContainerColor = Color.White
)
)
Spacer(modifier = Modifier.height(16.dp))
// Password Field
OutlinedTextField(
value = password,
onValueChange = {
password = it
validatePassword(it)
},
placeholder = { Text("Password") },
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp)),
colors = OutlinedTextFieldDefaults.colors(
unfocusedBorderColor = Color(0xFFE0E0E0),
focusedBorderColor = Color(0xFF448AFF),
unfocusedContainerColor = Color.White,
focusedContainerColor = Color.White
),
visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
trailingIcon = {
TextButton(
onClick = { isPasswordVisible = !isPasswordVisible },
contentPadding = PaddingValues(0.dp)
) {
Text(
if (isPasswordVisible) "Hide" else "Show",
fontSize = 13.sp,
color = Color(0xFF448AFF)
)
}
}
)
// Display password validation error
passwordError?.let {
Text(
it,
color = Color.Red,
fontSize = 12.sp,
modifier = Modifier.padding(top = 4.dp)
)
}
Spacer(modifier = Modifier.height(16.dp))
Text(
"Forgot Password?",
color = Color(0xFF448AFF),
fontSize = 13.sp,
modifier = Modifier
.align(Alignment.End)
.clickable { /* TODO */ }
)
Spacer(modifier = Modifier.height(24.dp))
// Sign In Button
Button(
onClick = { /* TODO */ },
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFEF5350)),
shape = RoundedCornerShape(12.dp)
) {
Text("Sign In", fontSize = 16.sp, color = Color.White)
}
Spacer(modifier = Modifier.height(32.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
Divider(modifier = Modifier.weight(1f))
Text(" or continue with ", color = Color.Gray, fontSize = 13.sp)
Divider(modifier = Modifier.weight(1f))
}
Spacer(modifier = Modifier.height(16.dp))
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier.fillMaxWidth()
) {
SocialLoginIcon(R.drawable.ic_google)
SocialLoginIcon(R.drawable.ic_apple)
SocialLoginIcon(R.drawable.ic_facebook)
}
Spacer(modifier = Modifier.height(32.dp))
Row {
Text("Not a member? ", fontSize = 14.sp)
Text(
"Register now",
color = Color(0xFF448AFF),
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
modifier = Modifier.clickable { /* TODO */ }
)
}
}
}
}
@Composable
fun SocialLoginIcon(iconRes: Int) {
Surface(
shape = RoundedCornerShape(12.dp),
shadowElevation = 2.dp,
color = Color.White,
modifier = Modifier.size(48.dp)
) {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = Color.Unspecified,
modifier = Modifier.padding(12.dp)
)
}
}
.png)
Komentar
Posting Komentar