Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easiest way to make a skeleton screen when data is loading

Tags:

flutter

I am new to flutter and i am trying to make something that looks like in the example included in the snippet. What is the easiest way to do this with dart and flutter.

basically i want to apply a shine animation to a container when the data from the server is still being downloaded.

Thanks

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>
like image 911
Antoine Avatar asked Aug 03 '18 17:08

Antoine


1 Answers

You can combine a Stack and Positioned.fill with a FractionallySizedBox to position such gradient on the top of another widget.

Then you can combine it to an AnimationController, an AnimatedBuilder and an Align or FractionallySizedBox to animate the position of the gradient over time.

You'd have this :

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,
                  ],
                ),
              ),
            ),
          )),
        ),
      ],
    );
  }
}

Which you can then use by wrapping any given widget :

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

enter image description here

like image 168
Rémi Rousselet Avatar answered Sep 25 '22 22:09

Rémi Rousselet