flutter 好看的动画登陆页学习

import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,

        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

//定义全局获取颜色的方法
Color getRandomWhiteColor(Random random){
  //透明度0~200 255是不透明
  int a =random.nextInt(200);
  return Color.fromARGB(a, 255, 255, 255) ;
}



class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{

  List<BobbleBean> _list = [];
  //随机数
  Random _random =new Random(DateTime.now().millisecondsSinceEpoch);
  double _maxSpend = 1.0;
  double _maxRadius = 100;
  double _maxThate = 2*pi;


  AnimationController _animationController;
  AnimationController _fadeAnimationController;


  void initState() {
    setState(() {
      for(int i=0;i<20;i++){
        BobbleBean bean = new BobbleBean();
        print(i);
        bean.color =getRandomWhiteColor(_random);
        //设置位置 先来个默认的
        bean.position = Offset(-1,-1);
        bean.spend = _random.nextDouble() * _maxSpend;
        bean.radius = _random.nextDouble() * _maxRadius;
        bean.theta = _random.nextDouble() * _maxThate;
        _list.add(bean);
      }
      //创建动画一秒
      _animationController = new AnimationController(vsync: this,duration: Duration(microseconds: 1000));
      //执行刷新监听
      _animationController.addListener(() {
        setState(() {
        });
      });
      //重复执行

      // _animationController.repeat();
      _fadeAnimationController = new AnimationController(vsync: this,duration: Duration(microseconds: 1800));
      //执行刷新监听
      _fadeAnimationController.forward();
      _fadeAnimationController.addStatusListener((status){
        if(status==AnimationStatus.completed){
          _animationController.repeat();
        }

      });
    });
  }
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body:  Container(
        child: Stack(
          children: [
            //渐变背景
            buildBackground(),
            //气泡
            buildBobbleWidget(context),
            //高斯模糊
            buildBlurWidget(),
            buildBottomWidget(context),


          ],
        ),
      )
    );
  }

  buildBobbleWidget(BuildContext context){
    return CustomPaint(
      size:MediaQuery.of(context).size,
      painter: CustomMyPainter(list:_list,random:_random),
    );
  }
  buildBlurWidget(){
    return BackdropFilter(
      filter: ImageFilter.blur(sigmaX: .3,sigmaY: .3),
      child: Container(
        color: Colors.white.withOpacity(0.1),
     ),
    );
  }
  buildBottomWidget(BuildContext context){
    return Positioned(
      bottom: 80,left: 40,right: 40,
      child:FadeTransition(
        opacity: _fadeAnimationController,

        child:  Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextFileWidget(
                obscuretext:false,
                labelText:'账号',
                prefixIconData:Icons.phone_android
            ),
            SizedBox(
              height: 14,
            ),
            TextFileWidget(
                obscuretext:true,
                labelText:'密码',
                suffixIconData: Icons.visibility,
                prefixIconData:Icons.lock_outline
            ),
            // Container(
            //   height: 38,
            //   width: double.infinity,
            //   child: ElevatedButton(
            //
            //   ),
            // )
          ],

        ),
      )
    );
  }
}


class TextFileWidget extends StatelessWidget {
  Function(String value) onChanged;
  bool obscuretext;
  String labelText;
  IconData prefixIconData;
  IconData suffixIconData;
  TextFileWidget({this.onChanged,this.labelText,this.obscuretext,this.suffixIconData,this.prefixIconData});
  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: onChanged,
      obscureText: obscuretext,
      style: TextStyle(
        color: Colors.blue,
        fontSize: 14,
      ),
      decoration: InputDecoration(
        filled: true,
        labelText: labelText,
        enabledBorder: UnderlineInputBorder(
          borderSide: BorderSide.none,
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.all(Radius.circular(10)),
          borderSide: BorderSide(color: Colors.blue)
        ),
        prefixIcon: Icon(prefixIconData,size: 18,color:Colors.blue,),
          suffixIcon: Icon(suffixIconData,size: 18,color:Colors.blue,)
      ),
    );
  }
}



class CustomMyPainter extends CustomPainter{
  List<BobbleBean> list = [];
  Random random;
  CustomMyPainter({this.list, this.random});

  //先来个画笔
  Paint _paint = new Paint()..isAntiAlias = true;
  @override
  void paint(Canvas canvas,Size size){
    //绘制前重新计算每个点的位置
    list.forEach((element) {
      Offset newCenterOffset = calcuLateXy(element.spend,element.theta);
      double dx = newCenterOffset.dx+element.position.dx;
      double dy = newCenterOffset.dy+element.position.dy;
      if(dx <0||dx>size.width){
        dx = random.nextDouble()*size.width;
      }
      if(dy <0||dx>size.height){
        dy = random.nextDouble()*size.height;
      }
      element.position =Offset(dx,dy);
    });
    list.forEach((element) { 
      _paint.color = element.color;
      canvas.drawCircle(element.position, element.radius, _paint);
    });
  }
  @override
  bool shouldRepaint(covariant CustomMyPainter oldDelegate){
    //返回false 不刷新
    return true;
  }


  Offset calcuLateXy(double spend ,double theta){
    return Offset(spend*cos(theta),spend*sin(theta));
  }
}

class buildBackground extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration:  BoxDecoration(

        gradient:LinearGradient(
            begin:Alignment.topLeft,
            end:Alignment.bottomRight,
          colors: [
            Colors.lightBlueAccent.withOpacity(0.3),
            Colors.lightBlue.withOpacity(0.3),
            Colors.blue.withOpacity(0.3)
          ]
        )
      ),
    );
  }
}


class BobbleBean{
  //位置
  Offset position;
  //颜色

  Color color;
  //速度
  double spend;
  double theta;
  double radius;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值