加载数据时制作骨架屏幕的最简单方法

时间:2018-08-03 17:12:32

标签: flutter

我是新手,我正在尝试制作类似于片段中示例的内容。 用飞镖和扑打做这件事的最简单方法是什么。

基本上,当服务器数据仍在下载时,我想将发光动画应用于容器。

谢谢

div {
    margin: auto;
		width: 500px;
		height: 600px; /* change height to see repeat-y behavior */
    
		background-image:
			radial-gradient( circle 50px at 50px 50px, lightgray 99%, transparent 0 ),
			linear-gradient( 100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 80% ),
			linear-gradient( lightgray 20px, transparent 0 ),
			linear-gradient( lightgray 20px, transparent 0 ),
			linear-gradient( lightgray 20px, transparent 0 ),
			linear-gradient( lightgray 20px, transparent 0 );

		background-repeat: repeat-y;

		background-size:
			100px 200px, /* circle */
			50px 200px, /* highlight */
			150px 200px,
			350px 200px,
			300px 200px,
			250px 200px;

		background-position:
			0 0, /* circle */
			0 0, /* highlight */
			120px 0,
			120px 40px,
			120px 80px,
			120px 120px;

		animation: shine 1s infinite;
	}

	@keyframes shine {
		to {
			background-position:
				0 0,
				100% 0, /* move highlight to right */
				120px 0,
				120px 40px,
				120px 80px,
				120px 120px;
		}
	}
<div></div>

2 个答案:

答案 0 :(得分:4)

您可以将StackPositioned.fillFractionallySizedBox结合使用,以将这种渐变放置在另一个小部件的顶部。

然后,您可以将其组合到AnimationControllerAnimatedBuilderAlignFractionallySizedBox上,以随时间变化渐变的位置。

您将拥有:

class LoadAnimation extends StatefulWidget {
  final Widget child;

  LoadAnimation({@required this.child, Key key}) : super(key: key);

  @override
  _LoadAnimationState createState() => _LoadAnimationState();
}

class _LoadAnimationState extends State<LoadAnimation>
    with SingleTickerProviderStateMixin {
  AnimationController controller;

  @override
  void initState() {
    controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    )..repeat();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        widget.child,
        Positioned.fill(
          child: ClipRect(
              child: AnimatedBuilder(
            animation: controller,
            builder: (context, child) {
              return FractionallySizedBox(
                widthFactor: .2,
                alignment: AlignmentGeometryTween(
                  begin: Alignment(-1.0 - .2 * 3, .0),
                  end: Alignment(1.0 + .2 * 3, .0),
                ).chain(CurveTween(curve: Curves.easeOut)).evaluate(controller),
                child: child,
              );
            },
            child: const DecoratedBox(
              decoration: const BoxDecoration(
                gradient: const LinearGradient(
                  colors: const [
                    Color.fromARGB(0, 255, 255, 255),
                    Colors.white,
                  ],
                ),
              ),
            ),
          )),
        ),
      ],
    );
  }
}

然后您可以通过包装任何给定的小部件来使用它:

LoadAnimation(
  child: Container(
    height: 100.0,
    width: 200.0,
    color: Colors.lime,
  ),
),

enter image description here

答案 1 :(得分:0)

尽管Rèmi发布了一个非常好的解决方案,但还应提及此软件包:https://pub.dev/packages/shimmer