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), )) ], ) ], ); }}