十一、使用Jetpack Compsoe编写一个写小说的Android应用:页面传参进阶与AlertDialog的使用

在完成了基础之后,现在我们有了一个近乎完整的软件框架了,现在就一步步实现对应功能就好了。

本篇要实现的就是:

功能1:首页中的修改小说名称

功能2:删除小说。

但是交互略显低端,之后有需要的话再优化。

说一下实现逻辑:

功能1:首先点击主页中小说条目左侧的笔的按钮,跳转到新建小说页面,对小说名字进行修改

功能2:点击主页中小说条目右侧的垃圾桶的按钮,弹出提示框,确认后删除

1、功能1的实现

1.1PageNavHost修改

为了对特定名字进行修改,首先我们要获取小说的id和名字,并将他们传递到修改名字页面去。

因此要现在PageNavHost中定义变量:

composable(
            "fic_name_page?fictionId={fictionId}?fictionName={fictionName}",
            arguments = listOf(
                navArgument("fictionId") {
                    defaultValue = 0
                    type = NavType.IntType} ,
                navArgument("fictionName") {
                    defaultValue = ""
                    type = NavType.StringType}
            )
        ) { backStackEntry ->
            //backStackEntry里面封装了参数
            FictionNamePage(navController, backStackEntry)
        }

这其中和之前的有些许不同,主要体现在路线route上

当我们传递无默认值参数时可以这样写

"fic_name_page/{fictionId}/{fictionName}"

但是当我们想传递有默认值参数时,则需要写成上面那种形式,同时在下面的代码中添加defaultValue值,注意,这里最好指定参数的数据类型,不然他会默认都按照String类型传递。 

1.2主页面跳转路线修改

之后,我们只需要给按钮添加带参数的路线即可:

navController.navigate("fic_name_page?fictionId=${it.fictionId}?fictionName=${it.fictionName}")

注意这里的东西一点都不能少,少了就报错。

这也会影响原来主页面右上角加号按钮的跳转,修改代码为:

navController.navigate("fic_name_page"){ popUpTo("main_page") }

这里加了个popUpTo,这个是指定返回时跳转到什么页面,具体好不好用现在还看不出来。

1.3数据接收

数据发送就算完成了,接受这边就更简单了,转到FictionNamePage,只需要将值取出即可。

var fictionNameText by remember { mutableStateOf("") }
    val fictionName = backStackEntry.arguments?.getString("fictionName")
    val fictionId = backStackEntry.arguments?.getInt("fictionId")
    fictionNameText = fictionName!!

这里额外定义了fictionNameText 全局值,这个变量用来存放输入框的值,所以不能去掉。

接下来就是按钮里判断一下的事了:

IconButton(onClick = {

                            if (fictionId == 0) {
                                viewModel.insertBook(fictionNameText)
                                Toast.makeText(context, "创建成功", Toast.LENGTH_SHORT).show()
                                navController.popBackStack("main_page", false)
                            } else {
                                viewModel.updateBook(fictionId!!, fictionNameText)
                                Toast.makeText(context, "修改成功", Toast.LENGTH_SHORT).show()
                                navController.popBackStack("main_page", false)
                            }

                        }, modifier = Modifier.size(50.dp)) {
                            Image(
                                painter = painterResource(id = R.drawable.btn_finish),
                                contentDescription = "add a book"
                            )
                        }

双感叹号就是强制确定它不为空,当然这是在确定的情况下,随便乱用会报错。

2、功能2的实现(AlertDialog)

这个功能的实现有一个关键,就是弹提示框:AlertDialog。

提示框可以稍微自定义一下,但是我抄的基本和原来的没啥区别:

@Composable
fun CustomAlertDialog(
    title:String,
    message:String,
    onConfirm:() -> Unit,
    onDismiss:() -> Unit
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        title = {
            Text(text = title)
        },
        text = { Text(text = message) },
        confirmButton = {
            TextButton(onClick = onConfirm) {
                Text(text = "确认")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text(text = "取消")
            }
        }
    )
}

那么有了自定义的AlertDialog之后,我们就要应用到页面中了。

这里有个小注意的点,AlertDialog只能在有布局的页面中,所以要放到MainPage的最外层与Scaffold并列,这样就能全屏显示提示框了。

首先定义变量:

var openDialogFlag by remember { mutableStateOf(false) }
    var deteleId by remember { mutableStateOf(0) }

一个用于控制对话框的显示,一个用于传递参数,这个后面就能看到。

然后就可以写提示框代码了:

if (openDialogFlag) {
        CustomAlertDialog(
            title = "警告",
            message = "确认要删除吗?这将删除本书所有信息!",
            onConfirm = {
                openDialogFlag = false
                viewModel.deleteBookAndAll(deteleId)
                deteleId = 0
            },
            onDismiss = {
                openDialogFlag = false
            }
        )
    }

可以看到deteleId用于这里传递参数。

之后就是按钮的操作代码:

IconButton(onClick = {
                            deteleId = it.fictionId
                            openDialogFlag = true
                        },}

其实重点就是onclick里面的两行。deteleId的实际作用就是将it中的参数传递出来。

这样代码就完成了,一起看看效果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HO灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值