自学内容网 自学内容网

flutter 充电气泡

前言:

之前一直看到 有手机充电的时候 有气泡从Type-C 的位置冒泡上来 慢慢上移, 然后和上面的圆圈 会和,感觉还是挺好看的。今天试了下用 Flutter 实现了一版本。大致效果如下,而且气泡 和 气泡直接还可以粘黏

 实现原理:

大致的布局就是这样的: Stack 包裹住所有的元素,需要位置移动的是 AnimatedBuilder,这里是把他们独立出来,方便随机的时候打散处理。

代码实现:

  • PageBubble.dart 整个页面 气泡的粘连效果 有点吃性能
    import 'dart:math';
    import 'dart:ui';
    
    import 'package:flutter/material.dart';
    import 'package:untitled1a/pages/example1/bubble_dot.dart';
    
    class PageBubble extends StatefulWidget {
      const PageBubble({Key? key}) : super(key: key);
    
      @override
      State<PageBubble> createState() => _PageBubbleState();
    }
    
    class _PageBubbleState extends State<PageBubble>
        with SingleTickerProviderStateMixin {
      late AnimationController _animationController;
      final Random random = Random();
      @override
      void initState() {
        _animationController = AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 2500),
        );
        _animationController.repeat();
        super.initState();
      }
    
      @override
      void dispose() {
        _animationController.dispose();
    
        // TODO: implement dispose
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text('充电气泡'),
          ),
          body: Align(
            alignment: Alignment(0.0, 1),
            child: Container(
              height: MediaQuery.of(context).size.height / 3 * 2,
              width: 250,
              // color: Colors.blue,
              child: Stack(
                alignment: Alignment.topCenter,
                children: [
                  ...buildAnimatedPositioned(),
                  Padding(
                    padding: const EdgeInsets.only(
                      top: 40,
                      left: 0,
                    ),
                    child: RotationTransition(
                      alignment: Alignment.center,
                      turns: _animationController,
                      child: Container(
                        width: 200,
                        height: 200,
                        decoration: const BoxDecoration(
                          color: Colors.deepPurple,
                          borderRadius: BorderRadius.only(
                            topRight: Radius.circular(70),
                            topLeft: Radius.circular(90),
                            bottomRight: Radius.circular(60),
                            bottomLeft: Radius.circular(80),
                          ),
                        ),
                      ),
                    ),
                  ),
                  //这个效果很有意思 就是有费性能  不需要可以移除掉
                  BackdropFilter(
                    filter: ImageFilter.dilate(radiusX: 3.0, radiusY: 3.0),
                    child: Container(),
                  ),
                  Positioned(
                    left: 35,
                    top: 45,
                    child: Container(
                      width: 180,
                      height: 180,
                      decoration: BoxDecoration(
                        color: Colors.black,
                        borderRadius: BorderRadius.circular(90),
                      ),
                      child: const Center(
                        child: Text(
                          '89%',
                          style: TextStyle(
                            fontSize: 40,
                            color: Colors.white,
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    
      int getRandomNumber(int min, int max) {
        var random = Random();
        return min + random.nextInt(max - min + 1);
      }
    
      List<Widget> buildAnimatedPositioned() {
        List<Widget> _list = [];
        List.generate(
            9,
            (index) => {
                  _list.add(BubbleDot(time: getRandomNumber(2000, 3500))),
                });
    
        return _list;
      }
    }
    

  • BubbleDot.dart    气泡效果    之所以把气泡单独出来是为了后面的随机打散操作
    import 'dart:math';
    import 'package:flutter/material.dart';
    
    class BubbleDot extends StatefulWidget {
      final int time;
      const BubbleDot({super.key, required this.time});
    
      @override
      State<BubbleDot> createState() => _BubbleDotState();
    }
    
    class _BubbleDotState extends State<BubbleDot>
        with SingleTickerProviderStateMixin {
      late AnimationController _animationController;
      late Animation<double> _animation;
      final Random random = Random();
      late double _leftPos = 0;
      late double _dotWidth = 0;
      @override
      void initState() {
        _animationController = AnimationController(
          vsync: this,
          duration: Duration(milliseconds: widget.time),
        );
        _animation = _animationController.drive(
            Tween<double>(begin: getRandomNumber(660, 800).toDouble(), end: 100));
        //_leftPos = random.nextDouble() * 200;
        _leftPos = getRandomNumber(35, 180).toDouble();
        _dotWidth = getRandomNumber(30, 66).toDouble();
    
        _animationController.addStatusListener(
            (AnimationStatus status) => {print('status  $status')});
        _animationController.repeat();
        // TODO: implement initState
        super.initState();
      }
    
      @override
      void dispose() {
        // TODO: implement dispose
        _animationController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
          animation: _animation,
          builder: (BuildContext context, Widget? child) {
            return Positioned(
              top: _animation.value,
              //top: 240,
              left: _leftPos,
              child: ClipOval(
                child: Container(
                  width: _dotWidth,
                  height: _dotWidth,
                  decoration: BoxDecoration(
                    color: Colors.deepPurple,
                    boxShadow: [
                      BoxShadow(
                        color: Colors.deepPurple.withOpacity(0.5),
                        spreadRadius: 6,
                        blurRadius: 8,
                        offset: Offset(4, 4), // changes position of shadow
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        );
      }
    
      int getRandomNumber(int min, int max) {
        return min + random.nextInt(max - min + 1);
      }
    }
    


原文地址:https://blog.csdn.net/nicepainkiller/article/details/140493066

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!