问题: 我正在使用 Flutter 开发一个移动应用程序,我想实现一个注册/登录流程,当用户执行某些操作(例如购买或与某些功能交互)时,系统会提示用户注册或登录。
所需的流程如下:当用户执行需要身份验证的操作时,应出现一个弹出卡,提示他们注册或登录。最初,该卡应仅请求姓名和电话号码等基本信息。但是,当用户单击卡右下角的箭头时,它应该展开以显示电子邮件和密码等其他字段。
我对 Flutter 和 UI 设计比较陌生,所以我不知道如何解决这个问题。有人可以提供有关如何在 Flutter 中实现渐进式披露的注册/登录弹出窗口的指导吗?具体来说,我正在寻找以下方面的建议:
用于创建弹出卡的最佳 Flutter 小部件或库。 如何实现渐进式公开功能,其中附加字段在用户交互时显示。 演示类似实现的任何示例代码或教程。 任何正确方向的帮助或指示将不胜感激!
我基本上是在尝试创建这个:
导致这个:
这是我期望发生的事情:
当用户与该功能交互时,应该会出现弹出卡。 最初,弹出卡应仅显示用户姓名和电话号码的字段。 单击箭头按钮后,该卡应展开以显示电子邮件和密码的其他字段。
你不需要任何包来处理这个 UI,你可以简单地使用一些 Flutter 组件来创建它,即使用:
showDialog
、 StateFullBuilder
、 Dialog
和 AnimatedContainer
Widgets。
首先,您需要在分支中创建这两个属性:
late double _containerHeigt;
bool _isLargHeiht = false;
然后在
build
方法中(在我的例子中,我构建了广告附加信息screenHeight
,你可以直接给它一个值):
@override
Widget build(BuildContext context) {
_containerHeigt = context.screenHeight * .3;
return Scaffold(
body: Center(
child: SizedBox(
width: context.screenWidth * .8,
height: context.screenHeight * .08,
child: MaterialButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return StatefulBuilder(
builder: (context, StateSetter setState) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: AnimatedContainer(
padding: const EdgeInsets.all(10),
duration: const Duration(seconds: 2),
height: _containerHeigt,
decoration: BoxDecoration(
color: const Color(0xFFDDDDDD),
borderRadius: BorderRadius.circular(20),
),
child: const Stack(
children: [
Column(
children: <Widget>[],
),
],
),
),
);
},
);
},
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Colors.orange,
child: const Text("Show Log in"),
),
),
),
);
}
选择您想要的小部件 点击它以显示
Dialog
(在此示例中为 MaterialButton
)
然后,当用户按下按钮
showDialog
方法时,它会返回一个 StatefulBuilder
,这对于更改 showDialog
方法中的状态非常重要,因为 setState
的 StatefulWidget
不起作用,
之后,您将给出
AnimatedContainer
属性 _containerHeigt
的高度
然后创建一个方法,根据
_containerHeigt
值更改 _isLargHeiht
值,如下所示:
void _changeContainerHeight({required StateSetter setState}) {
setState(
() {
_isLargHeiht = !_isLargHeiht;
if (_isLargHeiht) {
_containerHeigt = context.screenHeight * .6;
} else {
_containerHeigt = context.screenHeight * .3;
}
},
);
}
然后创建将调用此方法的按钮,在上面的 UI 中它将是 Stack 的子级,如下所示:
Positioned(
bottom: 20,
right: 0,
child: GestureDetector(
onTap: () {
_changeContainerHeight(setState: setState);
},
child: const CircleAvatar(
backgroundColor: Colors.black,
child: Icon(
Icons.arrow_downward_rounded,
color: Colors.white,
),
),
),
)
最后您可以在以下位置创建自定义 UI:
Column(
children: <Widget>[],
),
这是
Stack
Widget 的第一个子组件
这是完整的 UI 示例:
class AnimationLogInWidget extends StatefulWidget {
const AnimationLogInWidget({super.key});
@override
State<AnimationLogInWidget> createState() => _AnimationLogInWidgetState();
}
class _AnimationLogInWidgetState extends State<AnimationLogInWidget> {
late double _containerHeigt;
bool _isLargHeiht = false;
void _changeContainerHeight({required StateSetter setState}) {
setState(
() {
_isLargHeiht = !_isLargHeiht;
if (_isLargHeiht) {
_containerHeigt = context.screenHeight * .6;
} else {
_containerHeigt = context.screenHeight * .3;
}
},
);
}
@override
Widget build(BuildContext context) {
_containerHeigt = context.screenHeight * .3;
return Scaffold(
body: Center(
child: SizedBox(
width: context.screenWidth * .8,
height: context.screenHeight * .08,
child: MaterialButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return StatefulBuilder(
builder: (context, StateSetter setState) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: AnimatedContainer(
padding: const EdgeInsets.all(10),
duration: const Duration(seconds: 2),
height: _containerHeigt,
decoration: BoxDecoration(
color: const Color(0xFFDDDDDD),
borderRadius: BorderRadius.circular(20),
),
child: Stack(
children: [
Column(
children: <Widget>[
const Text(
"Create new account",
style: TextStyle(fontSize: 20),
),
Expanded(
child: SingleChildScrollView(
physics: _isLargHeiht
? const AlwaysScrollableScrollPhysics()
: const NeverScrollableScrollPhysics(),
child: Column(
children: <Widget>[
const CustomTextFeildWidget(
lable: "Your Name",
),
const CustomTextFeildWidget(
lable: "Phon number",
),
const CustomTextFeildWidget(
lable: "Email",
),
SizedBox(
height: context.screenHeight * .07,
width: context.screenWidth * .6,
child: MaterialButton(
onPressed: () {},
color: Colors.black,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(20),
),
child: const Text(
"LOG IN",
style: TextStyle(
color: Colors.white,
),
),
),
)
],
),
),
),
],
),
Positioned(
bottom: 20,
right: 0,
child: GestureDetector(
onTap: () {
_changeContainerHeight(setState: setState);
},
child: const CircleAvatar(
backgroundColor: Colors.black,
child: Icon(
Icons.arrow_downward_rounded,
color: Colors.white,
),
),
),
),
],
),
),
);
},
);
},
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Colors.orange,
child: const Text("Show Log in"),
),
),
),
);
}
}
class CustomTextFeildWidget extends StatelessWidget {
const CustomTextFeildWidget({
super.key,
required this.lable,
});
final String lable;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
decoration: InputDecoration(
label: Text(lable),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: Colors.orange,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: Colors.orange,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: Colors.orange,
),
),
),
),
);
}
}
您可以使用
_isLargHeiht
和 _containerHeigt
自定义所有内容。
希望对你有帮助!!