Jetpack Compose 实战之仿微信UI -完成登陆页(一)

前言

在上一篇文章中,我说将运用Jetpack Compose仿微信UI来开端我的Jetpack Compose学习之旅,咱们都知道,微信是一个庞大的系统,页面许多,我仅仅挑选一些页面去完成,这一期我将完成微信的登陆页UI。在学习了compose根底组件之后,我发现和 flutter 很像,比如Text,Row,Column等,就连在 flutter 常用的脚手架Scaffold也有,或许都是同一个爹的原因(都出自谷歌),所以运用起来也是比较容易的。

页面构成

登陆模块涉及的页面许多,我首要完成的页面包含:登陆主页(当咱们退出登陆来到的页面),登陆其他帐号和手机号登陆三个页面。我将运用一个Activity和三个组合函数页面构成。

Jetpack Compose 实战之仿微信UI -完成登陆页(一)

作用图

登陆主页

Jetpack Compose 实战之仿微信UI -完成登陆页(一)

登陆其他帐号底部弹窗

Jetpack Compose 实战之仿微信UI -完成登陆页(一)

登陆其他帐号页面

Jetpack Compose 实战之仿微信UI -完成登陆页(一)

手机号登陆页面

Jetpack Compose 实战之仿微信UI -完成登陆页(一)

代码完成

我先创立一个LoginNavScreen,它包含登陆主页,登陆其他帐页面和手机号登陆页面,内部运用navigation跳转对应的页面,完成代码如下:

@Composable
fun LoginNavScreen() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = LOGIN //默认的发动页
    ) {
        composable(route = LOGIN) {
            LoginScreen(navController = navController)
        }
        composable(route = LOGIN_OTHER) {
            LoginOtherScreen(navController = navController)
        }
        composable(
            route = "$LOGIN_PHONE/{phone}",
            arguments = listOf(navArgument("phone") {
                type = NavType.StringType
            })
        ) {
            val phone = it.arguments?.getString("phone") ?: ""
            LoginPhoneScreen(navController = navController, phone = phone)
        }
    }
}

登陆主页的完成

这个页面的布局比较简单,首要包含头像,手机号,暗码(验证码)输入框,暗码和验证码切换,登陆按钮和底部三个选项构成,代码完成如下:

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
@Composable
fun LoginScreen(navController: NavHostController) {
    val context = LocalContext.current as Activity
    rememberSystemUiController().setStatusBarColor(Color.Transparent, darkIcons = true)
    val password = EasyDataStore.getData("password", "")
    var pwdText by remember { mutableStateOf(password) }
    val loading = remember { mutableStateOf(false) }
    var isFocus by remember { mutableStateOf(false) }
    var isPwdAuth by remember { mutableStateOf(true) }
    val scope = rememberCoroutineScope()
    val modalBottomSheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
    Surface(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .autoCloseKeyboard()
    ) {
        Scaffold(
            content = { innerPadding ->
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(Color(0xffEDEDED))
                        .padding(innerPadding)
                ) {
                    LazyColumn(contentPadding = innerPadding) {
                        /**
                         * 导航栏到头像的距离
                         */
                        item {
                            Spacer(modifier = Modifier.height(50.dp))
                        }
                        /**
                         * 头像
                         */
                        item {
                            Box(
                                modifier = Modifier.height(70.dp)
                                    .fillMaxWidth(),
                                contentAlignment = Alignment.Center
                            ) {
                                Image(
                                    painter = rememberCoilPainter(request = myAvatar),
                                    contentDescription = null,
                                    contentScale = ContentScale.Crop,
                                    modifier = Modifier.size(70.dp)
                                )
                            }
                        }
                        /**
                         * 手机号
                         */
                        item {
                            Box(
                                modifier = Modifier
                                    .wrapContentHeight()
                                    .fillMaxWidth()
                                    .padding(top = 10.dp, bottom = 40.dp),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "18230000000",
                                    fontSize = 18.sp
                                )
                            }
                        }
                        /**
                         * 暗码输入框
                         */
                        item {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(start = 15.dp, end = 15.dp)
                                    .wrapContentHeight(),
                            ) {
                                TextField(
                                    value = pwdText,
                                    onValueChange = {
                                        pwdText = it
                                    },
                                    colors = TextFieldDefaults.outlinedTextFieldColors(
                                        containerColor = Color.Transparent,
                                        focusedBorderColor = Color.Transparent,
                                        unfocusedBorderColor = Color.Transparent,
                                        cursorColor = Color(0xff5ECC71)
                                    ),
                                    textStyle = TextStyle(
                                        fontSize = 16.sp
                                    ),
                                    leadingIcon = {
                                        Text(
                                            text = if (isPwdAuth) "暗码" else "验证码",
                                            fontSize = 18.sp,
                                            modifier = Modifier.width(90.dp)
                                        )
                                    },
                                    modifier = Modifier.fillMaxWidth().onFocusChanged {
                                        isFocus = when {
                                            it.isFocused -> true
                                            else -> false
                                        }
                                    },
                                    placeholder = {
                                        Text(
                                            text = if (isPwdAuth) "请填写微信暗码" else "请填写验证码",
                                            fontSize = 16.sp,
                                            color = Color(0xff888888),
                                        )
                                    }
                                )}
                        }
                        /**
                         * 获取验证码
                         */
                        item {
                            if (!isPwdAuth) {
                                Box(
                                    modifier = Modifier
                                        .padding(start = 110.dp, end = 15.dp, bottom = 4.dp)
                                        .fillMaxWidth(),
                                    contentAlignment = Alignment.CenterStart
                                ) {
                                    Text(
                                        text = "获取验证码",
                                        fontSize = 16.sp,
                                        modifier = Modifier
                                            .wrapContentHeight()
                                            .wrapContentWidth()
                                            .clip(RoundedCornerShape(8.dp))
                                            .background(Color(0xffE1E1E1))
                                            .padding(
                                                start = 10.dp,
                                                top = 2.dp,
                                                end = 10.dp,
                                                bottom = 6.dp
                                            )
                                    )
                                }
                            }
                        }
                        /**
                         * 手机号底部的下划线
                         */
                        item {
                            Box(modifier = Modifier.padding(start = 15.dp, end = 15.dp)) {
                                CQDivider(thickness = 1.dp, colorId = if (isFocus) R.color.green else  R.color.gray_10)
                            }
                        }
                        item {
                            Text(
                                text = if (isPwdAuth) "用短信验证码登陆" else "暗码登陆",
                                fontSize = 14.sp,
                                color = Color(0xff5F6594),
                                modifier = Modifier
                                    .padding(15.dp)
                                    .clickable {
                                        isPwdAuth = !isPwdAuth
                                    }
                            )
                        }
                        item {
                            Box(
                                modifier = Modifier
                                    .padding(top = 40.dp)
                                    .fillMaxWidth()
                                    .wrapContentHeight(),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "登陆",
                                    fontSize = 16.sp,
                                    color = Color.White,
                                    modifier = Modifier
                                        .wrapContentHeight()
                                        .wrapContentWidth()
                                        .clip(RoundedCornerShape(8.dp))
                                        .background(Color(0xff5ECC71))
                                        .padding(
                                            top = 10.dp,
                                            bottom = 10.dp,
                                            start = 80.dp,
                                            end = 80.dp
                                        )
                                        .click {
                                            if (pwdText == "") {
                                                context.toast(if (isPwdAuth) "请输入暗码" else "请输入验证码")
                                                return@clickable
                                            }
                                            if (pwdText != "123456") {
                                                context.toast(if (isPwdAuth) "暗码不正确" else "验证码不正确")
                                                return@clickable
                                            }
                                            loading.value = true
                                            scope.launch {
                                                delay(2000)
                                                loading.value = false
                                                MainActivity.navigate(context)
                                                EasyDataStore.putData("password", pwdText)
                                            }
                                        },
                                    textAlign = TextAlign.Center
                                )
                            }
                        }
                        item {
                            if (loading.value) {
                                ProcessDialogComponent(
                                    loading = loading,
                                    content = "正在登陆..."
                                )
                            }
                        }
                    }
                    /**
                     * 底部布局(找回暗码等)
                     */
                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.BottomCenter) {
                        Column(modifier = Modifier
                            .fillMaxWidth()
                            .wrapContentHeight(),
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {
                            /**
                             * 中心的分割线
                             */
                            Row(
                                modifier = Modifier
                                    .wrapContentWidth()
                                    .padding(top = 60.dp)
                            ) {
                                Text(
                                    text = "找回暗码",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .wrapContentWidth()
                                        .padding(top = 15.dp, end = 15.dp),
                                )
                                Box(modifier = Modifier
                                    .height(50.dp)
                                    .width(0.5.dp)
                                    .padding(top = 15.dp, bottom = 8.dp)
                                    .background(Color(0xff888888))
                                )
                                Text(
                                    text = "紧急结冻",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier.wrapContentWidth()
                                        .padding(top = 15.dp, start = 15.dp, end=15.dp),
                                )
                                Box(modifier = Modifier
                                    .height(50.dp)
                                    .width(0.5.dp)
                                    .padding(top = 15.dp, bottom = 8.dp)
                                    .background(Color(0xff888888))
                                )
                                Text(
                                    text = "更多",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .wrapContentWidth()
                                        .padding(top = 15.dp, start = 15.dp)
                                        .click {
                                            scope.launch { modalBottomSheetState.show() }
                                        },
                                    textAlign = TextAlign.Start
                                )
                            }
                        }
                    }
                }
                /**
                 * 底部更多弹窗
                 */
                ModalBottomSheetDialog(
                    titles = listOf("登陆其他帐号","注册","安全问题","反应问题"),
                    coroutineScope = scope,
                    modalBottomSheetState = modalBottomSheetState,
                    onSelect = {index, title ->
                        Log.d("LoginScreen", "index====$index  title=====$title")
                        // 导航到登陆其他帐号
                        if (index == 0) {
                            navController.navigate(LOGIN_OTHER)
                        }
                    }
                )
            }
        )
    }
}

ModalBottomSheetDialog

ModalBottomSheetDialog是我封装的底部挑选弹窗,完成的代码如下:

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ModalBottomSheetDialog(
    titles: List<String>,
    coroutineScope: CoroutineScope,
    modalBottomSheetState: ModalBottomSheetState,
    onSelect: (index: Int, title: String) -> Unit
){
    ModalBottomSheetLayout(
        sheetState = modalBottomSheetState,
        sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp),
        sheetContent = {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight()
            ) {
                titles.forEachIndexed { index, title ->
                    Box(
                        modifier = Modifier.fillMaxWidth().height(45.dp)
                            .clickable {
                                onSelect(index, title)
                                coroutineScope.launch { modalBottomSheetState.hide() }
                            },
                        contentAlignment = Alignment.Center
                    ) {
                        Text(text = title,
                            modifier = Modifier
                                .wrapContentWidth()
                                .wrapContentHeight(),
                            fontSize = 16.sp,
                            textAlign = TextAlign.Center
                        )
                    }
                    CQDivider()
                }
                Spacer(
                    modifier = Modifier
                        .height(10.dp)
                        .fillMaxWidth()
                        .background(Color(0xffF7F7F7))
                )
                Box(
                    modifier = Modifier.fillMaxWidth().height(45.dp),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = "撤销",
                        modifier = Modifier
                            .wrapContentWidth()
                            .wrapContentHeight()
                            .clickable {
                                coroutineScope.launch { modalBottomSheetState.hide() }
                            },
                        fontSize = 16.sp,
                        textAlign = TextAlign.Center
                    )
                }
            }
        }
    ) {}
}

细节优化

当咱们运用Modifier.clickable{}处理组件的点击事情时,会呈现说波纹作用,体会不是很好,在这儿我封装了Modifier的拓宽函数,代码如下:

**
 * 自定义去掉水波纹的点击拓宽函数
 *
 * example Modifier.click{ doSomething() }
 */
fun Modifier.click(
    onClick: () -> Unit
): Modifier = composed {
    this.clickable(
        indication = null,
        onClick = onClick,
        interactionSource = remember {
            MutableInteractionSource()
        }
    )
}

登陆其他帐号

咱们是在底部的“更多”跳转登陆其他帐号的,

相关代码

Text(
    text = "更多",
    fontSize = 16.sp,
    color = Color(0xff5F6594),
    modifier = Modifier
        .wrapContentWidth()
        .padding(top = 15.dp, start = 15.dp)
        .click {
            /**
             * 显现底部弹窗
             */
            scope.launch { modalBottomSheetState.show() }
        },
    textAlign = TextAlign.Start
)
ModalBottomSheetDialog(
    titles = listOf("登陆其他帐号","注册","安全问题","反应问题"),
    coroutineScope = scope,
    modalBottomSheetState = modalBottomSheetState,
    onSelect = {index, title ->
        Log.d("LoginScreen", "index====$index  title=====$title")
        /**
         * 导航到登陆其他帐号
         */
        if (index == 0) {
            navController.navigate(LOGIN_OTHER)
        }
    }
)

登陆其他帐号页面的完成

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginOtherScreen(navController: NavHostController) {
    val context = LocalContext.current as Activity
    rememberSystemUiController().setStatusBarColor(Color.Transparent, darkIcons = true)
    var isPhone by remember { mutableStateOf(true) }
    var phoneText by remember { mutableStateOf("")}
    var pwdOrPhoneText by remember { mutableStateOf("") }
    val loading = remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()
    Surface(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .autoCloseKeyboard()
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = {},
                    navigationIcon = {
                        IconButton(
                            onClick = {
                                //返回上一页
                                navController.popBackStack()
                            }) {
                            Icon(
                                imageVector = Icons.Filled.Close,
                                contentDescription = null,
                                modifier = Modifier.size(28.dp),
                            )
                        }
                    }
                )
            },
            content = { innerPadding ->
                Box(modifier = Modifier.padding(innerPadding)) {
                    LazyColumn(contentPadding = innerPadding) {
                        /**
                         * 导航栏到title的距离
                         */
                        item {
                            Spacer(modifier = Modifier.height(20.dp))
                        }
                        /**
                         * 手机号登陆title
                         */
                        item {
                            Box(
                                modifier = Modifier
                                    .height(50.dp)
                                    .fillMaxWidth(),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = if (isPhone) "手机号登陆" else "微信号/QQ号/邮箱登陆",
                                    fontSize = 20.sp
                                )
                            }
                        }
                        /**
                         * 手机号输入框
                         */
                        item {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(start = 15.dp, end = 15.dp)
                                    .wrapContentHeight(),
                            ) {
                                TextField(
                                    readOnly = isPhone,
                                    value = phoneText,
                                    onValueChange = {
                                        phoneText = it
                                    },
                                    colors = TextFieldDefaults.outlinedTextFieldColors(
                                        containerColor = Color.Transparent,
                                        focusedBorderColor = Color.White,
                                        unfocusedBorderColor = Color.White,
                                    ),
                                    textStyle = TextStyle(
                                        fontSize = 16.sp
                                    ),
                                    leadingIcon = {
                                        Text(
                                            text = if (isPhone) "国家/区域" else "帐号",
                                            fontSize = 18.sp,
                                            modifier = Modifier.width(if (isPhone) 120.dp else 90.dp)
                                        )
                                    },
                                    modifier = Modifier.fillMaxWidth(),
                                    placeholder = {
                                        Text(
                                            text = if (!isPhone) "请填写微信号/QQ号/..." else "中国大陆(+86)",
                                            fontSize = 16.sp,
                                            color = Color(0xff888888),
                                        )
                                    }
                                )}
                        }
                        /**
                         * 手机号底部的下划线
                         */
                        item {
                            Box(modifier = Modifier.padding(start = 15.dp, end = 15.dp)) {
                                CQDivider(thickness = 1.dp)
                            }
                        }
                        /**
                         * 暗码输入框
                         */
                        item {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(start = 15.dp, end = 15.dp)
                                    .wrapContentHeight(),
                            ) {
                                TextField(
                                    value = pwdOrPhoneText,
                                    onValueChange = {
                                        pwdOrPhoneText = it
                                    },
                                    colors = TextFieldDefaults.outlinedTextFieldColors(
                                        containerColor = Color.Transparent,
                                        focusedBorderColor = Color.Green,
                                        unfocusedBorderColor = Color(0xff888888),
                                        cursorColor = Color.Green
                                    ),
                                    textStyle = TextStyle(
                                        fontSize = 16.sp
                                    ),
                                    leadingIcon = {
                                        Text(
                                            text = if (isPhone) "手机号" else "暗码",
                                            fontSize = 18.sp,
                                            modifier = Modifier.width(if (isPhone) 120.dp else 90.dp)
                                        )
                                    },
                                    modifier = Modifier.fillMaxWidth(),
                                    placeholder = {
                                        Text(
                                            text = if (isPhone)"请填写手机号" else "请填写暗码",
                                            fontSize = 16.sp,
                                            color = Color(0xff888888),
                                        )
                                    }
                                )}
                        }
                        item {
                            Text(
                                text = if (!isPhone) "用手机号登陆" else "微信号/QQ号/邮箱登陆",
                                fontSize = 16.sp,
                                color = Color(0xff5F6594),
                                modifier = Modifier.padding(15.dp)
                                    .clickable {
                                        isPhone = !isPhone
                                    }
                            )
                        }
                        item {
                            if (loading.value) {
                                ProcessDialogComponent(
                                    loading = loading,
                                    content = "正在登陆..."
                                )
                            }
                        }
                    }
                    /**
                     * 底部布局(登陆按钮,找回暗码等)
                     */
                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.BottomCenter) {
                        Column(modifier = Modifier
                            .fillMaxWidth()
                            .wrapContentHeight()) {
                            Box(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .wrapContentHeight()
                                    .padding(bottom = 20.dp),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = if (isPhone) "上述手机号仅用于验证登陆" else "上述微信号/QQ号/邮箱登陆仅用于验证登陆",
                                    fontSize = 12.sp,
                                    color = Color(0xff888888),
                                )
                            }
                            Box(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .wrapContentHeight(),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "同意并持续",
                                    fontSize = 16.sp,
                                    color = Color.White,
                                    modifier = Modifier
                                        .wrapContentHeight()
                                        .wrapContentWidth()
                                        .clip(RoundedCornerShape(8.dp))
                                        .background(Color(0xff5ECC71))
                                        .padding(
                                            top = 10.dp,
                                            bottom = 10.dp,
                                            start = 80.dp,
                                            end = 80.dp
                                        )
                                        .clickable {
                                            if (phoneText == "" && !isPhone) {
                                                context.toast("请输入帐号")
                                                return@clickable
                                            }
                                            if (pwdOrPhoneText == "") {
                                                context.toast(if (isPhone) "请输入手机号" else "请输入暗码")
                                                return@clickable
                                            }
                                            if (isPhone) {
                                                // 导航到手机登陆页
                                                navController.navigate(
                                                    "$LOGIN_PHONE/$pwdOrPhoneText",
                                                )
                                            } else {
                                                loading.value = true
                                                scope.launch {
                                                    delay(2000)
                                                    loading.value = false
                                                    MainActivity.navigate(context)
                                                    }
                                                }
                                        },
                                    textAlign = TextAlign.Center
                                )
                            }
                            /**
                             * 中心的分割线
                             */
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(top = 60.dp)
                            ) {
                                Text(
                                    text = "找回暗码",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .padding(15.dp)
                                        .weight(1f),
                                    textAlign = TextAlign.End
                                )
                                Box(modifier = Modifier
                                    .height(50.dp)
                                    .width(0.5.dp)
                                    .padding(top = 15.dp, bottom = 8.dp)
                                    .background(Color(0xff888888))
                                )
                                Text(
                                    text = "更多选项",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .padding(15.dp)
                                        .weight(1f),
                                    textAlign = TextAlign.Start
                                )
                            }
                        }
                    }
                }
            }
        )
    }
}

手机号登陆页面的完成

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginPhoneScreen(navController: NavHostController, phone: String) {
    val context = LocalContext.current as Activity
    rememberSystemUiController().setStatusBarColor(Color.Transparent, darkIcons = true)
    var phoneText by remember { mutableStateOf("+86$phone") }
    var pwdText by remember { mutableStateOf("") }
    val loading = remember { mutableStateOf(false) }
    var isPwdAuth by remember { mutableStateOf(true) }
    var isFocus by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()
    Surface(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .autoCloseKeyboard()
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = {},
                    navigationIcon = {
                        IconButton(
                            onClick = {
                                //返回上一页
                                navController.popBackStack()
                            }) {
                            Icon(
                                imageVector = Icons.Filled.Close,
                                contentDescription = null,
                                modifier = Modifier.size(28.dp),
                            )
                        }
                    }
                )
            },
            content = { innerPadding ->
                Box(modifier = Modifier.padding(innerPadding)) {
                    LazyColumn(contentPadding = innerPadding) {
                        /**
                         * 导航栏到title的距离
                         */
                        item {
                            Spacer(modifier = Modifier.height(40.dp))
                        }
                        /**
                         * 手机号登陆title
                         */
                        item {
                            Box(
                                modifier = Modifier
                                    .height(50.dp)
                                    .fillMaxWidth(),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "手机号登陆",
                                    fontSize = 20.sp
                                )
                            }
                        }
                        /**
                         * 手机号输入框
                         */
                        item {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(start = 15.dp, end = 15.dp)
                                    .wrapContentHeight(),
                            ) {
                                TextField(
                                    readOnly = true,
                                    value = phoneText,
                                    onValueChange = {
                                        phoneText = it
                                    },
                                    colors = TextFieldDefaults.outlinedTextFieldColors(
                                        containerColor = Color.Transparent,
                                        focusedBorderColor = Color.Transparent,
                                        unfocusedBorderColor = Color.Transparent,
                                    ),
                                    textStyle = TextStyle(
                                        fontSize = 16.sp
                                    ),
                                    leadingIcon = {
                                        Text(
                                            text = "手机号",
                                            fontSize = 18.sp,
                                            modifier = Modifier.width(90.dp)
                                        )
                                    },
                                    modifier = Modifier.fillMaxWidth(),
                                )}
                        }
                        /**
                         * 手机号底部的下划线
                         */
                        item {
                            Box(modifier = Modifier.padding(start = 15.dp, end = 15.dp)) {
                                CQDivider(thickness = 0.5.dp)
                            }
                        }
                        /**
                         * 暗码输入框
                         */
                        item {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(start = 15.dp, end = 15.dp)
                                    .wrapContentHeight(),
                            ) {
                                TextField(
                                    value = pwdText,
                                    onValueChange = {
                                        pwdText = it
                                    },
                                    colors = TextFieldDefaults.outlinedTextFieldColors(
                                        containerColor = Color.Transparent,
                                        focusedBorderColor = Color.Transparent,
                                        unfocusedBorderColor = Color.Transparent,
                                        cursorColor = Color(0xff5ECC71)
                                    ),
                                    textStyle = TextStyle(
                                        fontSize = 16.sp
                                    ),
                                    leadingIcon = {
                                        Text(
                                            text = if (isPwdAuth) "暗码" else "验证码",
                                            fontSize = 18.sp,
                                            modifier = Modifier.width(90.dp)
                                        )
                                    },
                                    modifier = Modifier.fillMaxWidth().onFocusChanged {
                                        isFocus = when {
                                            it.isFocused -> true
                                            else -> false
                                        }
                                    },
                                    placeholder = {
                                        Text(
                                            text = if (isPwdAuth) "请填写微信暗码" else "请填写验证码",
                                            fontSize = 16.sp,
                                            color = Color(0xff888888),
                                        )
                                    }
                                )}
                        }
                        item {
                            if (!isPwdAuth) {
                                Box(
                                    modifier = Modifier
                                        .padding(start = 110.dp, end = 15.dp, bottom = 4.dp)
                                        .fillMaxWidth(),
                                    contentAlignment = Alignment.CenterStart
                                ) {
                                    Text(
                                        text = "获取验证码",
                                        fontSize = 16.sp,
                                        modifier = Modifier
                                            .wrapContentHeight()
                                            .wrapContentWidth()
                                            .clip(RoundedCornerShape(8.dp))
                                            .background(Color(0xffE1E1E1))
                                            .padding(
                                                start = 10.dp,
                                                top = 2.dp,
                                                end = 10.dp,
                                                bottom = 6.dp
                                            )
                                    )
                                }
                            }
                        }
                        item {
                            Box(modifier = Modifier.padding(start = 15.dp, end = 15.dp)) {
                                CQDivider(thickness = 1.dp, colorId = if (isFocus) R.color.green else  R.color.gray_10)
                            }
                        }
                        item {
                            Text(
                                text = if (isPwdAuth) "用短信验证码登陆" else "暗码登陆",
                                fontSize = 14.sp,
                                color = Color(0xff5F6594),
                                modifier = Modifier
                                    .padding(15.dp)
                                    .clickable {
                                        isPwdAuth = !isPwdAuth
                                    }
                            )
                        }
                        /**
                         * 进度框
                         */
                        item {
                            if (loading.value) {
                                ProcessDialogComponent(
                                    loading = loading,
                                    content = "正在登陆..."
                                )
                            }
                        }
                    }
                    /**
                     * 底部布局(登陆按钮,找回暗码等)
                     */
                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.BottomCenter) {
                        Column(modifier = Modifier
                            .fillMaxWidth()
                            .wrapContentHeight()) {
                            Box(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .wrapContentHeight(),
                                contentAlignment = Alignment.Center
                            ) {
                                Text(
                                    text = "登陆",
                                    fontSize = 16.sp,
                                    color = Color.White,
                                    modifier = Modifier
                                        .wrapContentHeight()
                                        .wrapContentWidth()
                                        .clip(RoundedCornerShape(8.dp))
                                        .background(Color(0xff5ECC71))
                                        .padding(
                                            top = 10.dp,
                                            bottom = 10.dp,
                                            start = 80.dp,
                                            end = 80.dp
                                        )
                                        .clickable {
                                            if (pwdText == "") {
                                                context.toast(if (isPwdAuth) "请输入暗码" else "请输入验证码")
                                                return@clickable
                                            }
                                            if (pwdText != "123456") {
                                                context.toast(if (isPwdAuth) "暗码不正确" else "验证码不正确")
                                                return@clickable
                                            }
                                            loading.value = true
                                            scope.launch {
                                                delay(2000)
                                                loading.value = false
                                                MainActivity.navigate(context)
                                            }
                                        },
                                    textAlign = TextAlign.Center
                                )
                            }
                            /**
                             * 中心的分割线
                             */
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(top = 60.dp)
                            ) {
                                Text(
                                    text = "找回暗码",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .padding(15.dp)
                                        .weight(1f),
                                    textAlign = TextAlign.End
                                )
                                Box(modifier = Modifier
                                    .height(50.dp)
                                    .width(0.5.dp)
                                    .padding(top = 15.dp, bottom = 8.dp)
                                    .background(Color(0xff888888))
                                )
                                Text(
                                    text = "更多选项",
                                    fontSize = 16.sp,
                                    color = Color(0xff5F6594),
                                    modifier = Modifier
                                        .padding(15.dp)
                                        .weight(1f),
                                    textAlign = TextAlign.Start
                                )
                            }
                        }
                    }
                }
            }
        )
    }
}

总结

到这儿,就完成了仿微信登陆模块的首要页面了,这些页面运用了 Scaffold 脚手架,水平布局和垂直布局分别运用了 RowColumn 组件,滚动布局运用了 LazyColumn,输入框运用了 TextField 组件,页面跳转运用了导航组件 Navigation ,网络图片加载运用了 coil。这儿边还有一个比较生疏的是remember,它是Jetpack Compose是一个强壮的功能,用于在界面重构期间保存和康复界面状况,是一个Composable函数,用于记住Composable的内部状况,以便在界面重构时可以轻松地保存和康复界面状况,这儿边我首要运用它完成一些条件的UI切换。