import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:rive/rive.dart'; import 'package:trackoffical_app/generated/assets.dart'; import 'package:trackoffical_app/screen.dart'; import 'package:trackoffical_app/view/login/sign_up2_view.dart'; import 'package:trackoffical_app/view/web_view.dart'; import '../../styles/color_schemes.g.dart'; import '../../utils.dart'; import 'login_controller.dart'; import 'common.dart'; import 'package:vector_math/vector_math.dart' as vec; final _duration = 2.seconds; class AnimationPage extends StatefulWidget { const AnimationPage({super.key}); @override State createState() { return _AnimationPageState(); } } class _AnimationPageState extends State with SingleTickerProviderStateMixin { late Animation animation; late AnimationController animationController; @override void initState() { super.initState(); animationController = AnimationController(duration: _duration, vsync: this); animation = Tween(begin: 0, end: 1).animate(animationController); animationController.forward(); } @override void dispose() { animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { SizeFit.screenInit(context); return wPageLeft(); } Widget wPageLeft() { return Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage(Assets.commonPageBg), fit: BoxFit.cover)), child: Column( children: [ Expanded( flex: 1, child: Container( // color: const Color(0xffffcb00), padding: const EdgeInsets.only(bottom: 32), alignment: Alignment.bottomCenter, child: Stack( alignment: Alignment.center, children: [ Image.asset( Assets.imagesImCompassNoMap, height: 15.0.wp, fit: BoxFit.fitHeight, ), SizedBox( height: 10.0.wp, child: const RiveAnimation.asset( 'assets/images/am_app_start_arrow.riv', fit: BoxFit.fitHeight, )) ], ), )), Expanded( flex: 1, child: Column( // mainAxisAlignment: MainAxisAlignment.start, children: [ AnimatedText(animation: animation), Expanded( child: Stack( alignment: Alignment.center, children: [ Center( child: AnimatedColors( animation: animation, ), ), // Positioned( // bottom: 2.6.wp, // child: // Image.asset(Assets.imagesIcLogo, height: 5.0.wp)) ], )) ], )), ], ), ); } } class AnimatedText extends AnimatedWidget { const AnimatedText({super.key, required Animation animation}) : super(listenable: animation); @override Widget build(BuildContext context) { final animation = listenable as Animation; var style = (context.textTheme.titleLarge ?? const TextStyle()) .copyWith(height: 0.14.wp, color: Colors.white, fontSize: 2.2.wp); return Opacity( opacity: animation.value, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( height: 0.9.wp, ), Text('确定方向 ', style: style), Text(' 发现你自己的路!', style: style), Text('Orienting, Discover Your Own Way!', style: style.copyWith( color: const Color(0xffade0ff), fontWeight: FontWeight.bold, fontSize: 1.4.wp)), ], )); } } class AnimatedColors extends AnimatedWidget { const AnimatedColors({super.key, required Animation animation}) : super(listenable: animation); @override Widget build(BuildContext context) { final animation = listenable as Animation; var style = (context.textTheme.titleLarge ?? const TextStyle()) .copyWith(color: Colors.white, fontSize: 8.33.wp); var children = []; for (var i = 0; i < hrPColors.length; i++) { final color = hrPColors[i]; var opacity = 0.0; if (i < animation.value * hrPColors.length) { opacity = 1; } children.add(Opacity( opacity: opacity, child: Container( width: 1.02.wp, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(2.0.wp), border: Border.all(color: Colors.white.withAlpha(100))), ))); } return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox(height: 5.36.wp), SizedBox( width: 7.6.wp, height: 2.5.wp, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: children, )), // Text('支持心率带检测身体数据', // style: style.copyWith( // color: const Color(0xffffcb00), fontSize: 3.3.wp)), ], ); } } class LoginView extends GetView { const LoginView({super.key}); static Bindings loginBind() { return BindingsBuilder(() { Get.lazyPut(() => LoginController()); // Get.put(LoginController()); }); } @override Widget build(BuildContext context) { return Scaffold( // appBar: AppTopBar(title: '登录账号', hasBackText: true, height: context.height*0.3), backgroundColor: Colors.white, body: Container( height: double.infinity, decoration: const BoxDecoration(color: Colors.white), alignment: Alignment.center, clipBehavior: Clip.hardEdge, child: Row( children: [ const Expanded( flex: 2, child: AnimationPage(), ), Expanded( flex: 3, child: wPageRight(context), ) ], ), ), ); } Widget wPageRight(BuildContext context) { return Container( margin: EdgeInsets.fromLTRB(6.wp, 5.6.wp, 6.wp, 2.wp), padding: const EdgeInsets.all(10.0), decoration: const BoxDecoration( // color: Color(0xffffcb00), image: DecorationImage( image: AssetImage(Assets.loginRightBg), alignment: Alignment.topCenter, fit: BoxFit.fitWidth), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( '定向运动活动现场监控系统', textAlign: TextAlign.center, style: TextStyle(fontSize: 22.0.rpx, fontWeight: FontWeight.bold), ), SizedBox( height: context.height * 0.45, child: wInput() ), SizedBox( height: 3.wp, child: Image.asset(Assets.loginXfldx) ), // Expanded(flex: 10,child: wExtra()), ], )); } InputDecoration wInputDecoration(hintText) { return InputDecoration( // isCollapsed: true, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), hintText: hintText, // hintStyle: TextStyle(fontSize: 12.0.rpx), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: const BorderSide( color: Colors.blue, width: 1.0, ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(4.0), borderSide: const BorderSide( color: Color(0xffaaaaaa), width: 1.0, ), ), ); } Widget wInput() { return Container( margin: EdgeInsets.fromLTRB(6.wp, 3.wp, 6.wp, 2.wp), padding: EdgeInsets.fromLTRB(6.wp, 3.6.wp, 6.wp, 2.wp), decoration: BoxDecoration( color: const Color(0xffffffff), borderRadius: BorderRadius.circular(1.0.wp), boxShadow: const [BoxShadow(color: Color(0x38000000), offset: Offset(0.0, 3.0), blurRadius: 6)], ), child: Column( children: [ // const Spacer(flex: 20), TextFormField( decoration: wInputDecoration('请输入手机号'), validator: (String? value) { if (value == null || !value.isPhoneNumber) { return '请输入正确的手机号'; } return null; }, onChanged: (value) { controller.phone.value = value; }, keyboardType: TextInputType.phone), const Spacer(flex: 50), Stack( alignment: Alignment.centerRight, children: [ TextFormField( decoration: wInputDecoration('请输入验证码'), onChanged: (value) { controller.password.value = value; }, keyboardType: TextInputType.number, ), Padding( padding: const EdgeInsets.only(right: 4), child: SizedBox( width: 84, height: 37, child: Obx(() => GetCodeButton( codeRetryLeft: controller.codeRetryLeft.value, onPressed: () => controller.onGetCode(), )), ), ), ], ), // _TextContract(), const Spacer(flex: 80), button( '登 录', () => controller.onSignIn(), ), const Spacer(flex: 10), ], )); } Widget wExtra() { return Padding( padding: EdgeInsets.only(left: 41.67.rpx, right: 41.67.rpx), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ divider(), Padding( padding: EdgeInsets.only(left: 22.9.rpx, right: 22.9.rpx), child: Text( '其他登录方式', style: TextStyle(fontSize: 25.0.rpx), )), divider(), ], ), SizedBox(height: 76.5.rpx), Row(), const Spacer(), Text.rich(TextSpan( text: '还不是我们的会员?', style: TextStyle(fontSize: 33.33.rpx, color: Colors.black), children: [ TextSpan( text: '点击注册', style: const TextStyle(color: Color(0xffffb40b)), recognizer: TapGestureRecognizer() ..onTap = () { SignUpView.show(); }, ), ])), SizedBox(height: 76.5.rpx), ], )); } Widget divider() { return Expanded( child: Container( height: 2.0.rpx, color: Colors.black, )); } } class _TextContract extends GetView { @override Widget build(BuildContext context) { const color = Color(0xffffb40b); return Row( children: [ Obx(() => Checkbox( value: controller.isAgreeContract.value, onChanged: (v) => controller.isAgreeContract.value = (v ?? false), )), Expanded( child: Text.rich(TextSpan( text: '我已阅读并同意', style: const TextStyle(fontSize: 11, color: Color(0xFF999999)), children: [ TextSpan( text: '《用户协议》', style: const TextStyle(color: color), recognizer: TapGestureRecognizer() ..onTap = () { Get.to(() => WebView( url: 'https://www.beswell.com/ot_agreement.html')); }, ), const TextSpan(text: '和'), TextSpan( text: '《隐私政策》', style: const TextStyle(color: color), recognizer: TapGestureRecognizer() ..onTap = () { Get.to(() => WebView(url: 'https://beswell.com/privacy-ot.html')); }, ), ]))) ], ); } } void main() { Get.put(LoginController()); runPreview(LoginView()); }