flutter实现水波纹登录页

class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  State createState() => _LoginPageState();
}

class _LoginPageState extends State
    with SingleTickerProviderStateMixin {
  bool showPassword = false;
  bool rememberMe = false;
  String? userName = '';
  String? passWord = '';
  bool loginEnable = false;

  TextEditingController nameController = TextEditingController();
  TextEditingController pwdController = TextEditingController();

  ///动画控制器
  late AnimationController _animationController;

  Future sharedPreferences = SharedPreferences.getInstance();

  void getData() async {
    SharedPreferences preferences = await sharedPreferences;
    rememberMe = preferences.getBool("rememberMe") == null
        ? false
        : preferences.getBool("rememberMe")!;
    userName = preferences.getString("username");
    passWord = preferences.getString("password");

    nameController.text = userName!;
    pwdController.text = passWord!;
    setState(() {});
    if (rememberMe) {
      loginEnable = true;
    }
  }

  @override
  void initState() {
    super.initState();
    getData();
    //创建动画控制器
    _animationController = AnimationController(
      //默认的初始值
      value: 0.0,
      //执行时间
      duration: const Duration(seconds: 10),
      //值变化范围
      upperBound: 1,
      lowerBound: -1,
      vsync: this,
    );
    //重复执行
    _animationController.repeat();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();

  }

  @override
  Widget build(BuildContext context) {
    //获取当前组件的大小
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      //允许键盘弹出布局文件上移
      resizeToAvoidBottomInset: true,
      body: Container(
        width: size.width,
        height: size.height,
        child: Stack(
          children: [
            //第一部分 水波纹背景
            buildFirstAnimation(size),

            buildTopIcon(size),

            buildBottomButton(size),
          ],
        ),
      ),
    );
  }

  void send() async {
    String uName = nameController.text;
    String uPwd = pwdController.text;
    try {
      var result = await LoginDao.login(uName, uPwd, rememberMe);
      if (result['code'] == 200) {
        showToast(result['message']);
        saveOrDeleteData(rememberMe, uName, uPwd);
        Get.offNamed("/");
      } else {
        showWarnToast(result['message']);
      }
    } on HiNetError catch (e) {
      print(e);
    }

    print('rememberMe$rememberMe,-username$uName,-password$uPwd');
// Get.back();
  }

  void saveOrDeleteData(bool rememberMe, String name, String pwd) async {
    if (rememberMe) {
      SharedPreferences preferences = await sharedPreferences;
      preferences.setBool('rememberMe', rememberMe);
      preferences.setString("username", name);
      preferences.setString("password", pwd);
    } else {
      SharedPreferences preferences = await sharedPreferences;
      preferences.setBool('rememberMe', rememberMe);
      preferences.remove("username");
      preferences.remove("password");
    }
  }

  void checkInput() {
    bool enable;
    if (isNotEmpty(userName) && isNotEmpty(passWord)) {
      enable = true;
    } else {
      enable = false;
    }

    setState(() {
      loginEnable = enable;
    });
  }

  ///  构建 AnimatedBuilder 与裁剪水波纹
  ///
  AnimatedBuilder buildFirstAnimation(Size size) {
    return AnimatedBuilder(
      //绑定动画控制器
      animation: _animationController,
      builder: (BuildContext context, Widget? child) {
        //裁剪组件
        return ClipPath(
          //自定义裁剪路径
          clipper: HeaderClipper(_animationController.value),
          //裁剪的子Widget
          child: Container(
            //高度
            height: size.height * 0.48,
            //线性渐变颜色的样式
            decoration: const BoxDecoration(
              gradient: LinearGradient(
                //线性渐变的方向
                  begin: Alignment.bottomLeft,
                  end: Alignment.topRight,
                  // colors: [Color(0xFFE0647B), Color(0xFFFCDD89)]),
                  colors: [Color(0xFF0C8EEA), Color(0xFFFFFFFF)]),
            ),
          ),
        );
      },
    );
  }

  Positioned buildTopIcon(Size size) {
    return Positioned(
      top: size.height * 0.18,
      left: 0,
      right: 0,
      child: Center(
        child: TImage(
          Assets.images.login.logo.path,
          width: 292,
          height: 80,
        ),
      ),
    );
  }

  ///底部对齐的输入框
  Positioned buildBottomButton(Size size) {
    return Positioned(
      bottom: 60,
      left: 0,
      right: 0,
      child: Column(
        //包裹子Widget
        mainAxisSize: MainAxisSize.min,
        //主方向子Widget 底部对齐 (Column的垂直方向)
        mainAxisAlignment: MainAxisAlignment.end,
        //次方向子Widget居中对齐 (Column的水平方向)
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Container(
              width: size.width * 0.8,
              margin: const EdgeInsets.only(top: 18),
              child: TextField(
                controller: nameController,
                onChanged: (text) {
                  userName = text;
                  checkInput();
                },
                decoration: const InputDecoration(
                  labelText: '用户名',
                  hintText: '请输入用户名',
                  hintStyle: TextStyle(color: Color(0xFFACACAC), fontSize: 14),
                  //输入内容的内边距
                  contentPadding:
                  EdgeInsets.only(top: 20, bottom: 20, left: 38),
                  //输入框可用时的边框样式
                  enabledBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.lightBlueAccent),
                    borderRadius: BorderRadius.all(Radius.circular(30.0)),
                  ),
                  //输入框获取输入焦点时的边框样式
                  focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: Colors.green),
                    borderRadius: BorderRadius.all(Radius.circular(30.0)),
                  ),
                ),
              )),
          Container(
            width: size.width * 0.8,
            margin: const EdgeInsets.only(top: 18),
            child: TextField(
              controller: pwdController,
              obscureText: !showPassword,
              onChanged: (text) {
                passWord = text;
                checkInput();
              },
              decoration: InputDecoration(
                labelText: '密码',
                hintText: '请输入密码',
                suffixIcon: IconButton(
                  icon: Icon(
                    showPassword ? Icons.visibility_off : Icons.visibility,
                  ),
                  onPressed: () {
                    setState(() {
                      showPassword = !showPassword;
                    });
                  },
                ),
                hintStyle: const TextStyle(color: Color(0xFFACACAC), fontSize: 14),
                //输入内容的内边距
                contentPadding:
                const EdgeInsets.only(top: 20, bottom: 20, left: 38),
                //输入框可用时的边框样式
                enabledBorder: const OutlineInputBorder(
                  borderSide: BorderSide(color: Colors.lightBlueAccent),
                  borderRadius: BorderRadius.all(Radius.circular(30.0)),
                ),
                //输入框获取输入焦点时的边框样式
                focusedBorder: const OutlineInputBorder(
                  borderSide: BorderSide(color: Colors.green),
                  borderRadius: BorderRadius.all(Radius.circular(30.0)),
                ),),
            ),
          ),
          Container(
            margin: const EdgeInsets.only(top: 20),
            padding: const EdgeInsets.only(bottom: 20),
            width: size.width * 0.7,
            child: ElevatedButton(
              onPressed: loginEnable ? send : null,
              child: const Text(
                '登录',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 20,
                ),
              ),
            ),
          ),
          MediaQuery.of(context).size.width <
              MediaQuery.of(context).size.height?
          _buildOthers():_buildWidth()
        ],
      ),


    );
  }

  _buildOthers() {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Checkbox(
              value: rememberMe,
              onChanged: (value) {
                setState(() {
                  rememberMe = !rememberMe;
                });
              },
            ),
            const Text('保存密码'),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Text('还没有账号,联系开通:'),
            TextButton(
                onPressed: null,
                child: Text(
                  '',
                  style: TextStyle(color: Colors.blueAccent),
                ))
          ],
        )
      ],
    );
  }

  _buildWidth() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Checkbox(
              value: rememberMe,
              onChanged: (value) {
                setState(() {
                  rememberMe = !rememberMe;
                });
              },
            ),
            const Text('保存密码 '),
          ],
        ),
        const SizedBox(width: 40,),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Text(' 还没有账号,联系开通:'),
            TextButton(
                onPressed: null,
                child: Text(
                  '',
                  style: TextStyle(color: Colors.blueAccent),
                ))
          ],
        )
      ],
    );
  }
}

你可能感兴趣的:(flutter,dart)