flutter 自定义loading

本文介绍了如何在Flutter中创建自定义的加载动画,包括连续旋转的`LoadingView.showSerially`和不连续旋转的`LoadingView.showDiscrete`。通过`OverlayEntry`和`Scaffold`将加载视图添加到屏幕,利用`RotationTransition`和`Transform.rotate`进行动画效果的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用:
LoadingView.showSerially(context);
LoadingView.showDiscrete(context);
源码:
LoadingView.showSerially(context);
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

class LoadingView {

  static LoadingView _instance;
  static LoadingView instance() {
    if(_instance == null) {
      _instance = LoadingView();
    }
    return _instance;
  }

  SeriallyLoadingView _seriallyLoadingView;
  DiscreteLoadingView _discreteLoadingView;
  OverlayEntry _discreteOverlayEntry;
  OverlayEntry _seriallyOverlayEntry;
  int _rotationType = 0;

  OverlayEntry discreteOverlayEntry() {
    if(_discreteOverlayEntry == null) {
      _discreteOverlayEntry = _createDiscreteOverlayEntry();
    }
    return _discreteOverlayEntry;
  }

  OverlayEntry seriallyOverlayEntry() {
    if(_seriallyOverlayEntry == null) {
      _seriallyOverlayEntry = _createSeriallyOverlayEntry();
    }
    return _seriallyOverlayEntry;
  }

  OverlayEntry _createSeriallyOverlayEntry() {
    return OverlayEntry(
        builder: (BuildContext context) {
          return Scaffold(
            backgroundColor: Colors.transparent,
            body: _seriallyLoadingView,
          );
        }
    );
  }

  OverlayEntry _createDiscreteOverlayEntry() {
    return OverlayEntry(
        builder: (BuildContext context) {
          return Scaffold(
            backgroundColor: Colors.transparent,
            body: _discreteLoadingView,
          );
        }
    );
  }

  static show(BuildContext context) {
    instance()._seriallyLoadingView = SeriallyLoadingView();
    Overlay.of(context).insert(instance().seriallyOverlayEntry());
  }

  /// 不连续的,间断地,默认旋转角22.5
  static showDiscrete(BuildContext context) {
    instance()._rotationType = 1;
    instance()._discreteLoadingView = DiscreteLoadingView();
    Overlay.of(context).insert(instance().discreteOverlayEntry());
  }

  static showSerially(BuildContext context) {
    instance()._rotationType = 0;
    instance()._seriallyLoadingView = SeriallyLoadingView();
    Overlay.of(context).insert(instance().seriallyOverlayEntry());
  }

  static hide() {
    if(instance()._rotationType == 1) {
      instance().discreteOverlayEntry().remove();
      instance()._discreteLoadingView.stopAnimation();
    } else {
      instance().seriallyOverlayEntry().remove();
      instance()._seriallyLoadingView.stopAnimation();
    }
  }
}

class SeriallyLoadingView extends StatefulWidget {

  void stopAnimation() {
    _loadingState.stopAnimation();
  }
  final _loadingState = _SeriallyLoadingViewState();

  @override
  State<StatefulWidget> createState() {
    return _loadingState;
  }
}

class _SeriallyLoadingViewState extends State<StatefulWidget> with SingleTickerProviderStateMixin {

  AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 600),
    );
    _animationController.forward();
    _animationController.repeat();
  }

  void stopAnimation() {
    _animationController.stop();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: RotationTransition(
        turns: _animationController,
        alignment: Alignment.center,
        child: Container(
          width: 40,
          height: 40,
          child: Image.asset("resource/images/other/loading3.png"),
        ),
      ),
    );
  }
}

class DiscreteLoadingView extends StatefulWidget {

  void stopAnimation() {
    _state.stopAnimation();
  }
  final _state = _DiscreteLoadingViewState();

  @override
  State<StatefulWidget> createState() {
    return _state;
  }
}

class _DiscreteLoadingViewState extends State<DiscreteLoadingView> {

  double _angle = 0;
  Timer _timer;
  int rotateIndex = 0;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(Duration(milliseconds: 50), timerCallBack);
  }

  void timerCallBack(Timer timer) {
    rotateIndex ++;
    rotateIndex %= 15;
    setState(() {
      _angle = rotateIndex * math.pi / 8;
    });
  }

  void stopAnimation() {
    _timer.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Transform.rotate(
        angle: _angle,
        child: Container(
          width: 40,
          height: 40,
          child: Image.asset("resource/images/other/loading.png"),
        ),
      ),
    );
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值