如何在 Flutter 中实现渐进式披露的注册/登录弹窗?

问题描述 投票:0回答:1

问题: 我正在使用 Flutter 开发一个移动应用程序,我想实现一个注册/登录流程,当用户执行某些操作(例如购买或与某些功能交互)时,系统会提示用户注册或登录。

所需的流程如下:当用户执行需要身份验证的操作时,应出现一个弹出卡,提示他们注册或登录。最初,该卡应仅请求姓名和电话号码等基本信息。但是,当用户单击卡右下角的箭头时,它应该展开以显示电子邮件和密码等其他字段。

我对 Flutter 和 UI 设计比较陌生,所以我不知道如何解决这个问题。有人可以提供有关如何在 Flutter 中实现渐进式披露的注册/登录弹出窗口的指导吗?具体来说,我正在寻找以下方面的建议:

用于创建弹出卡的最佳 Flutter 小部件或库。 如何实现渐进式公开功能,其中附加字段在用户交互时显示。 演示类似实现的任何示例代码或教程。 任何正确方向的帮助或指示将不胜感激!

我基本上是在尝试创建这个:

导致这个:

这是我期望发生的事情:

当用户与该功能交互时,应该会出现弹出卡。 最初,弹出卡应仅显示用户姓名和电话号码的字段。 单击箭头按钮后,该卡应展开以显示电子邮件和密码的其他字段。

flutter flutter-animation
1个回答
1
投票

你不需要任何包来处理这个 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
自定义所有内容。

希望对你有帮助!!

© www.soinside.com 2019 - 2024. All rights reserved.