Как создать анимацию разбрызгивания слева направо или сверху вниз во Flutter - PullRequest
2 голосов
/ 19 июня 2020

Невозможно создать анимацию разбрызгивания оверлея над макетом во флаттере.

enter image description here

class AnimateContainer extends StatelessWidget {
  final String assetPath;

  AnimateContainer(this.assetPath);
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 100,
      child: Image.asset(
        'assets/$assetPath',
      ),
    );
  }
}

Ответы [ 3 ]

2 голосов
/ 19 июня 2020

Добавлено

Я обновил код, чтобы он выглядел как прикрепленный gif.


Вы можете использовать виджет AnimatedPositioned, как показано ниже.

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "App",
      theme: new ThemeData(primarySwatch: Colors.amber),
      home: Test(),
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
  double rightValue = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Title",
      theme: new ThemeData(primarySwatch: Colors.amber),
      home: Scaffold(
        body: SafeArea(
          child: Stack(
            children: <Widget>[
              Container(
                decoration: BoxDecoration(
                  color: Colors.transparent,
                  image: DecorationImage(
                    fit: BoxFit.fill,
                    image: AssetImage(
                      'assets/bg.png',
                    ),
                  ),
                ),
                height: 200.0,
              ),
              AnimatedPositioned(
                // left: 0,
                left: 70 + rightValue,
                duration: Duration(milliseconds: 1000),
                child: Center(
                  child: Container(
                    color: Colors.black.withOpacity(0.5),
                    width: MediaQuery.of(context).size.width,
                    height: 200.0,
                  ),
                ),
              ),
              AnimatedPositioned(
                // left: 0,
                left: rightValue,
                duration: Duration(milliseconds: 1000),
                child: Center(
                  child: ShaderMask(
                    shaderCallback: (rect) {
                      return LinearGradient(
                        begin: Alignment.centerRight,
                        end: Alignment.centerLeft,
                        colors: [Color(0xFF45ced5), Colors.transparent],
                      ).createShader(
                          Rect.fromLTRB(0, 0, rect.width, rect.height));
                    },
                    blendMode: BlendMode.dstIn,
                    child: Container(
                      color: Color(0xFF45ced5),
                      width: 70.0,
                      height: 200.0,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              rightValue = MediaQuery.of(context).size.width;
            });
          },
          child: Icon(Icons.navigation),
          backgroundColor: Colors.green,
        ),
      ),
    );
  }
}

enter image description here

0 голосов
/ 20 июня 2020

Вы можете использовать стек с контейнером с декором и многократно анимировать его размер с помощью AnimationController

class MyWidget extends StatefulWidget {
  @override
  MyWidgetState createState() => MyWidgetState();
}

class MyWidgetState extends State<MyWidget>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> myTween;

  @override
  void initState() {
    super.initState();
    // the controller of the animation, cotnrol the duration, add a curve if you want
    controller = AnimationController(
        vsync: this,
        animationBehavior: AnimationBehavior.preserve,
        duration: const Duration(milliseconds: 500));
    //A tween with a beginning value of 1 and ends in zero (to make it looks like go from left to right)
    myTween = Tween<double>(begin: 1, end: 0).animate(controller);
    controller.repeat(); //repeat, move forward or backward, whatever you want
  }

  @override
  void dispose(){
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
        width: 300,
        height: 100,
        child: Stack(children: [
          Image.asset('assets/$assetPath'),
          Align(
            alignment: Alignment.centerRight, //so it knows it should move the the alingment which is the right, just like your gif
              child: SizeTransition(
                sizeFactor: myTween,
                axis: Axis.horizontal, //to change size in the X direction
                axisAlignment: -1.0, //from the start to finish (left to right)
                // this value shrinks the black color and make it looks that the blue bar is moving to the right alignment
                child: Container(
                  decoration: BoxDecoration(
                  gradient: LinearGradient(
                    colors: [
                      Colors.transparent,
                      Color(0xFF45ced5).withOpacity(0.5),
                      Color(0xFF45ced5),
                      Colors.black54,
                      Colors.black54
                    ],
                  begin: Alignment.centerLeft,
                  end: Alignment.centerRight,
                  stops: [0.0, 0.1, 0.15, 0.15, 1.0], //you can change the end of the tween to 0.15 so the color never dissapears
              )),
            )
          )
          )
        ])
    );
  }
}
0 голосов
/ 19 июня 2020

Я добавляю новый ответ для повторения.
Надеюсь, это вам поможет.
Для повторения я использую пакет Animator.
https://pub.dev/packages/animator

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:animator/animator.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "App",
      theme: new ThemeData(primarySwatch: Colors.amber),
      home: Test(),
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
  double rightValue = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Title",
      theme: new ThemeData(primarySwatch: Colors.amber),
      home: Scaffold(
        body: SafeArea(
          child: Animator(
              tween: Tween<double>(
                  begin: 0.0, end: MediaQuery.of(context).size.width),
              repeats: 0,
              duration: const Duration(milliseconds: 1000),
              builder: (context, animatorState, child) {
                return Stack(
                  children: <Widget>[
                    Container(
                      decoration: BoxDecoration(
                        color: Colors.transparent,
                        image: DecorationImage(
                          fit: BoxFit.fill,
                          image: AssetImage(
                            'assets/bg.png',
                          ),
                        ),
                      ),
                      height: 200.0,
                    ),
                    Positioned(
                      // left: 0,
                      left: 70 + animatorState.value,
                      child: Center(
                        child: Container(
                          color: Colors.black.withOpacity(0.5),
                          width: MediaQuery.of(context).size.width,
                          height: 200.0,
                        ),
                      ),
                    ),
                    Positioned(
                      // left: 0,
                      left: animatorState.value,
                      child: Center(
                        child: ShaderMask(
                          shaderCallback: (rect) {
                            return LinearGradient(
                              begin: Alignment.centerRight,
                              end: Alignment.centerLeft,
                              colors: [Color(0xFF45ced5), Colors.transparent],
                            ).createShader(
                                Rect.fromLTRB(0, 0, rect.width, rect.height));
                          },
                          blendMode: BlendMode.dstIn,
                          child: Container(
                            color: Color(0xFF45ced5),
                            width: 70.0,
                            height: 200.0,
                          ),
                        ),
                      ),
                    ),
                  ],
                );
              }),
        ),
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...