Как правильно анимировать виджет в flutter

#android #ios #flutter #dart

#Android #iOS #flutter #dart

Вопрос:

Я перепробовал множество пакетов, таких как Animated Size и Fade, а также виджет, подобный AnimatedSwitcher , и ничего не сработало, они просто меняют виджет без анимации.. вот мой код :

                 AnimatedSwitcher(
                    duration: Duration(milliseconds: 1),
                    child: isCompany
                        ? Container(
                      key: ValueKey<int>(0),
                      child: Padding(
                      padding: const EdgeInsets.fromLTRB(40, 0, 40, 0),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  TextField(
                                    decoration: InputDecoration(
                                        enabledBorder: UnderlineInputBorder(
                                          borderSide:
                                              BorderSide(color: Colors.white),
                                        ),
                                        prefixIcon: Image.asset(
                                            'assets/images/user_icon.png'),
                                        labelText: 'إسم المستخدم',
                                        labelStyle: TextStyle(
                                            color: Colors.white, fontSize: 18)),
                                  ),
                                  TextField(
                                    decoration: InputDecoration(
                                        enabledBorder: UnderlineInputBorder(
                                          borderSide:
                                              BorderSide(color: Colors.white),
                                        ),
                                        prefixIcon: Image.asset(
                                            'assets/images/password_icon.png'),
                                        suffixIcon: IconButton(
                                          icon: Image.asset(
                                              'assets/images/show_icon.png'),
                                          onPressed: () {},
                                        ),
                                        labelText: 'كلمة المرور',
                                        labelStyle: TextStyle(
                                            color: Colors.white, fontSize: 18)),
                                  ),
                                ],
                              ),
                            ),
                        )
                        : Container(
                      key: ValueKey<int>(1),
                      child: Padding(
                      padding: const EdgeInsets.fromLTRB(40, 40, 40, 40),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                children: [
                                  TextField(
                                    decoration: InputDecoration(
                                        enabledBorder: UnderlineInputBorder(
                                          borderSide:
                                              BorderSide(color: Colors.white),
                                        ),
                                        prefixIcon: Image.asset(
                                            'assets/images/user_icon.png'),
                                        labelText: 'رقم الجوال',
                                        labelStyle: TextStyle(
                                            color: Colors.white, fontSize: 18)),
                                  ),
                                  TextField(
                                    decoration: InputDecoration(
                                        enabledBorder: UnderlineInputBorder(
                                          borderSide:
                                              BorderSide(color: Colors.white),
                                        ),
                                        prefixIcon: Image.asset(
                                            'assets/images/password_icon.png'),
                                        suffixIcon: IconButton(
                                          icon: Image.asset(
                                              'assets/images/show_icon.png'),
                                          onPressed: () {},
                                        ),
                                        labelText: 'كلمة المرور',
                                        labelStyle: TextStyle(
                                            color: Colors.white, fontSize: 18)),
                                  ),
                                ],
                              ),
                            ),
                        )
                ),
  

Это просто изменение виджета одним щелчком мыши, без анимации вообще, и мне нужно, чтобы это было похоже на это видео :

https://youtu.be/Uwe8hHkfd8I

Ответ №1:

AnimatedSwitcher просто переключается между отображаемым виджетом.

Одна идея, о которой я думал о вашей проблеме, заключается в использовании стека с двумя расположенными элементами в качестве кнопок и одним PositionedTransition, который при нажатии преобразует положение вашего первого и второго расположенных виджетов.

Взгляните на этот пример: https://api.flutter.dev/flutter/widgets/PositionedTransition-class.html

Теперь у меня было время сделать быстрый и простой пример моей идеи, который выглядит следующим образом:

введите описание изображения здесь

(Он не отстает — это вызвано преобразованием видео в gif)

Код, который вы можете скопировать и вставить в качестве основы:

 import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  final double containerWidth = 150.0;
  final double containerHeight = 50.0;
  final double padding = 20.0;
  final double borderWidth = 5.0;

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

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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: LayoutBuilder(builder: (context, constraints) {
        final Size biggest = constraints.biggest;
        return Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          color: Colors.white,
          child: Stack(
            children: [
              PositionedTransition(
                rect: RelativeRectTween(
                  begin: RelativeRect.fromSize(
                      Rect.fromLTWH(
                          padding, padding, containerWidth, containerHeight),
                      biggest),
                  end: RelativeRect.fromSize(
                      Rect.fromLTWH(biggest.width - containerWidth - padding,
                          padding, containerWidth, containerHeight),
                      biggest),
                ).animate(CurvedAnimation(
                  parent: _controller,
                  curve: Curves.easeInOut,
                )),
                child: Container(
                  width: containerWidth,
                  height: containerHeight,
                  decoration:
                      BoxDecoration(border: Border.all(width: borderWidth)),
                ),
              ),
              Positioned(
                  top: padding   borderWidth,
                  left: padding   borderWidth,
                  child: GestureDetector(
                    onTap: () {
                      _controller.reverse();
                    },
                    child: Container(
                      width: containerWidth - 2 * borderWidth,
                      height: containerHeight - 2 * borderWidth,
                      child: Center(
                        child: Text(
                          "Text1",
                          style: TextStyle(color: Colors.black, fontSize: 20),
                        ),
                      ),
                    ),
                  )),
              Positioned(
                  top: padding   borderWidth,
                  left: biggest.width - containerWidth - padding   borderWidth,
                  child: GestureDetector(
                    onTap: () {
                      _controller.forward();
                    },
                    child: Container(
                      width: containerWidth - 2 * borderWidth,
                      height: containerHeight - 2 * borderWidth,
                      child: Center(
                        child: Text(
                          "Text2",
                          style: TextStyle(color: Colors.black, fontSize: 20),
                        ),
                      ),
                    ),
                  )),
            ],
          ),
        );
      }),
    );
  }
}

  

Будущая работа:
Чтобы добиться желаемого в видео, вы могли бы использовать AnimatedSwitcher, который вы уже пробовали, чтобы просто чередовать два поля ввода в зависимости от нажатия кнопки.