0

目前,此代码用于调整容器大小以在不同内容之间切换,但它不是动画。我认为我需要提供一个 height 属性来使动画工作,并且当我提供一个在它之间切换的高度时确实匹配,如下所示:

height: selected ? 400 : 100,

容器在两种状态之间平滑地动画。然而,高度不再是自适应的。所以我尝试使用以下方法提供高度:

GlobalKey _key = GlobalKey();

_size = _key.currentContext.size;

height: _size.height,

但它给了我错误,我不知道如何解决它。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  bool selected = false;
//  GlobalKey _key = GlobalKey();
//  Size _size = _key.currentContext.size;




  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: ListView(
              children: [
                GestureDetector(
                  onTap: () {
                    setState(() {
                      selected = !selected;
//                      _size = _key.currentContext.size;
                    });
                  },
                  child: Padding(
                    padding: EdgeInsets.all(5),
                    child: AnimatedContainer(
//                      height: _size.height,
//                      key: _key,
                      duration: Duration(seconds: 1),
                      curve: Curves.fastOutSlowIn,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(15),
                        color: Colors.white,
                        boxShadow: [
                          BoxShadow(
                            blurRadius: 2.5,
                            spreadRadius: 0.4,
                            color: Colors.grey,
                            offset: Offset(0, 0.5),
                          ),
                        ],
                      ),
                      child: Padding(
                        padding: EdgeInsets.all(17),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Move fridge up stairs',
                              style: TextStyle(fontSize: 16),
                            ),
                            SizedBox(height: 5),
                            Text(
                              'Sarah - 2 days ago - 2.3km',
                              style: TextStyle(color: Colors.black54),
                            ),
                            if (selected)
                              Container(
                                child: Column(
                                  children: [
                                    Padding(
                                      padding: EdgeInsets.fromLTRB(0, 20, 0, 20),
                                      child: Text(
                                        'Fridge is a single door. Sitting in kitchen. Need one strong person as I will help move it.',
                                        style: TextStyle(
                                          color: Colors.black54,
                                        ),
                                      ),
                                    ),
                                    Padding(
                                      padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
                                      child: Row(
                                        children: [
                                          Icon(
                                            Icons.calendar_today,
                                            color: Colors.black54,
                                            size: 20,
                                          ),
                                          Text(
                                            ' In three days',
                                            style: TextStyle(
                                              color: Colors.black54,
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                    Padding(
                                      padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
                                      child: Row(
                                        children: [
                                          Icon(
                                            Icons.attach_money,
                                            color: Colors.black54,
                                          ),
                                          Text(
                                            ' 30',
                                            style: TextStyle(
                                              color: Colors.black54,
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                    Row(
                                      children: [
                                        Text('Price : '),
                                        Container(
                                          width: 140,
                                          margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
                                          decoration: BoxDecoration(
                                            borderRadius: BorderRadius.circular(20.0),
                                            color: Colors.white,
                                            border: Border.all(color: Colors.white),
                                          ),
                                          child: Container(
                                            child: TextField(
                                              decoration: new InputDecoration(
                                                  hintText: "Your price",
                                                  contentPadding: const EdgeInsets.all(10.0)),
                                              keyboardType: TextInputType.number,
                                              maxLines: null,
                                            ),
                                          ),
                                        ),
                                      ],
                                    ),
                                    Row(
                                      children: [
                                        Text('Reply : '),
                                        Expanded(
                                          child: TextField(
                                            decoration: new InputDecoration(
                                                hintText: "Enter your reply",
                                                contentPadding: const EdgeInsets.all(10.0)),
                                            keyboardType: TextInputType.multiline,
                                            maxLines: null,
                                          ),
                                        ),
                                      ],
                                    ),
                                    SizedBox(height:20),
                                    Row(
                                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                      children: [
                                        SizedBox(
                                          width: 10,
                                        ),
                                        FlatButton(
                                          shape: RoundedRectangleBorder(
                                            side: BorderSide(
                                                color: Colors.blue, width: 1, style: BorderStyle.solid),
                                            borderRadius: BorderRadius.circular(50),
                                          ),
                                          color: Colors.white,
                                          textColor: Colors.black,
                                          onPressed: () {
                                            /*...*/
                                          },
                                          child: Padding(
                                            padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
                                            child: Text(
                                              "Reply",
                                            ),
                                          ),
                                        ),
                                      ],
                                    )
                                  ],
                                ),
                              ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      )

    );
  }
}
4

2 回答 2

0

您可以使用自定义动画来执行此操作,如下所示:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  bool selected = false;
  GlobalKey _key1 = GlobalKey();
  GlobalKey _key2 = GlobalKey();
  AnimationController _controller;
  Animation _animation;
  bool foward = false;
  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: Duration(seconds: 1));
  }

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

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      setState(() {
        _animation = Tween<double>(
                begin: _key1.currentContext.size.height,
                end: _key2.currentContext.size.height +
                    _key1.currentContext.size.height)
            .chain(CurveTween(curve: Curves.fastOutSlowIn))
            .animate(_controller);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
            child: ListView(
      children: [
        Padding(
          padding: EdgeInsets.all(5),
          child: GestureDetector(
            onTap: () {
              if (foward) {
                _controller.reverse();
              } else {
                _controller.forward();
              }
              foward = !foward;
            },
            child: (_animation == null)
                ? _buildWidget(_key1, _key2)
                : AnimatedBuilder(
                    // curve: Curves.fastOutSlowIn,
                    animation: _controller,
                    builder: (context, child) {
                      return Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(15),
                            color: Colors.white,
                            boxShadow: [
                              BoxShadow(
                                blurRadius: 2.5,
                                spreadRadius: 0.4,
                                color: Colors.grey,
                                offset: Offset(0, 0.5),
                              ),
                            ],
                          ),
                          child: Padding(
                            padding: EdgeInsets.all(17.0),
                            child: Container(
                                height: _animation.value, child: child),
                          ));
                    },
                    child: _buildWidget(_key1, _key2)),
          ),
        ),
      ],
    )));
  }

  Widget _buildWidget(Key key1, Key key2) {
    return SingleChildScrollView(
      physics: const NeverScrollableScrollPhysics(),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Widget1(
            key: _key1,
          ),
          Widget2(
            key: _key2,
          ),
        ],
      ),
    );
  }
}

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

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

class _Widget1State extends State<Widget1> {
  @override
  Widget build(BuildContext context) {
    return Column(mainAxisSize: MainAxisSize.min, children: [
      Text(
        'Move fridge up stairs',
        style: TextStyle(fontSize: 16),
      ),
      SizedBox(height: 5),
      Text(
        'Sarah - 2 days ago - 2.3km',
        style: TextStyle(color: Colors.black54),
      ),
    ]);
  }
}

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

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

class Widget2State extends State<Widget2> {
  @override
  Widget build(BuildContext context) {
    return Column(mainAxisSize: MainAxisSize.min, children: [
      Container(
          child: Column(children: [
        Padding(
          padding: EdgeInsets.fromLTRB(0, 20, 0, 20),
          child: Text(
            'Fridge is a single door. Sitting in kitchen. Need one strong person as I will help move it.',
            style: TextStyle(
              color: Colors.black54,
            ),
          ),
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
          child: Row(
            children: [
              Icon(
                Icons.calendar_today,
                color: Colors.black54,
                size: 20,
              ),
              Text(
                ' In three days',
                style: TextStyle(
                  color: Colors.black54,
                ),
              ),
            ],
          ),
        ),
        Padding(
          padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
          child: Row(
            children: [
              Icon(
                Icons.attach_money,
                color: Colors.black54,
              ),
              Text(
                ' 30',
                style: TextStyle(
                  color: Colors.black54,
                ),
              ),
            ],
          ),
        ),
        Row(
          children: [
            Text('Price : '),
            Container(
              width: 140,
              margin: EdgeInsets.fromLTRB(0, 0, 0, 0),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20.0),
                color: Colors.white,
                border: Border.all(color: Colors.white),
              ),
              child: Container(
                child: TextField(
                  decoration: new InputDecoration(
                      hintText: "Your price",
                      contentPadding: const EdgeInsets.all(10.0)),
                  keyboardType: TextInputType.number,
                  maxLines: null,
                ),
              ),
            ),
          ],
        ),
        Row(
          children: [
            Text('Reply : '),
            Expanded(
              child: TextField(
                decoration: new InputDecoration(
                    hintText: "Enter your reply",
                    contentPadding: const EdgeInsets.all(10.0)),
                keyboardType: TextInputType.multiline,
                maxLines: null,
              ),
            ),
          ],
        ),
        SizedBox(height: 20),
        Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
          SizedBox(
            width: 10,
          ),
          FlatButton(
              shape: RoundedRectangleBorder(
                side: BorderSide(
                    color: Colors.blue, width: 1, style: BorderStyle.solid),
                borderRadius: BorderRadius.circular(50),
              ),
              color: Colors.white,
              textColor: Colors.black,
              onPressed: () {
                /*...*/
              },
              child: Padding(
                padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
                child: Text(
                  "Reply",
                ),
              ))
        ])
      ]))
    ]);
  }
}
于 2020-10-24T15:03:20.093 回答
0

我觉得 AnimatedContainer 不适合这种情况。我认为最好使用AnimatedCrossFade。当使用提供的曲线和持续时间更改属性的新旧值时,AnimatedContainer 将自动在它们之间进行动画处理。

以下代码为使用 AnimatedCrossFade 进行了重构:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool selected = false;
//  GlobalKey _key = GlobalKey();
//  Size _size = _key.currentContext.size;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        Expanded(
          child: ListView(
            children: [
              GestureDetector(
                onTap: () {
                  setState(() {
                    selected = !selected;
//                      _size = _key.currentContext.size;
                  });
                },
                child: Padding(
                  padding: EdgeInsets.all(5),
                  child: AnimatedCrossFade(
                    duration: Duration(seconds: 1),
                    crossFadeState: selected
                        ? CrossFadeState.showFirst
                        : CrossFadeState.showSecond,
                    firstChild: Container(
//                        height: !selected ? 100 : 400,
//                      key: _key,
                      width: double.infinity,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(15),
                        color: Colors.white,
                        boxShadow: [
                          BoxShadow(
                            blurRadius: 2.5,
                            spreadRadius: 0.4,
                            color: Colors.grey,
                            offset: Offset(0, 0.5),
                          ),
                        ],
                      ),
                      child: Padding(
                        padding: EdgeInsets.all(17),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Move fridge up stairs',
                              style: TextStyle(fontSize: 16),
                            ),
                            SizedBox(height: 5),
                            Text(
                              'Sarah - 2 days ago - 2.3km',
                              style: TextStyle(color: Colors.black54),
                            ),
                            if (selected)
                              Container(
                                child: Column(
                                  children: [
                                    Padding(
                                      padding:
                                          EdgeInsets.fromLTRB(0, 20, 0, 20),
                                      child: Text(
                                        'Fridge is a single door. Sitting in kitchen. Need one strong person as I will help move it.',
                                        style: TextStyle(
                                          color: Colors.black54,
                                        ),
                                      ),
                                    ),
                                    Padding(
                                      padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
                                      child: Row(
                                        children: [
                                          Icon(
                                            Icons.calendar_today,
                                            color: Colors.black54,
                                            size: 20,
                                          ),
                                          Text(
                                            ' In three days',
                                            style: TextStyle(
                                              color: Colors.black54,
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                    Padding(
                                      padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
                                      child: Row(
                                        children: [
                                          Icon(
                                            Icons.attach_money,
                                            color: Colors.black54,
                                          ),
                                          Text(
                                            ' 30',
                                            style: TextStyle(
                                              color: Colors.black54,
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                    Row(
                                      children: [
                                        Text('Price : '),
                                        Container(
                                          width: 140,
                                          margin:
                                              EdgeInsets.fromLTRB(0, 0, 0, 0),
                                          decoration: BoxDecoration(
                                            borderRadius:
                                                BorderRadius.circular(20.0),
                                            color: Colors.white,
                                            border:
                                                Border.all(color: Colors.white),
                                          ),
                                          child: Container(
                                            child: TextField(
                                              decoration: new InputDecoration(
                                                  hintText: "Your price",
                                                  contentPadding:
                                                      const EdgeInsets.all(
                                                          10.0)),
                                              keyboardType:
                                                  TextInputType.number,
                                              maxLines: null,
                                            ),
                                          ),
                                        ),
                                      ],
                                    ),
                                    Row(
                                      children: [
                                        Text('Reply : '),
                                        Expanded(
                                          child: TextField(
                                            decoration: new InputDecoration(
                                                hintText: "Enter your reply",
                                                contentPadding:
                                                    const EdgeInsets.all(10.0)),
                                            keyboardType:
                                                TextInputType.multiline,
                                            maxLines: null,
                                          ),
                                        ),
                                      ],
                                    ),
                                    SizedBox(height: 20),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.spaceBetween,
                                      children: [
                                        SizedBox(
                                          width: 10,
                                        ),
                                        FlatButton(
                                          shape: RoundedRectangleBorder(
                                            side: BorderSide(
                                                color: Colors.blue,
                                                width: 1,
                                                style: BorderStyle.solid),
                                            borderRadius:
                                                BorderRadius.circular(50),
                                          ),
                                          color: Colors.white,
                                          textColor: Colors.black,
                                          onPressed: () {
                                            /*...*/
                                          },
                                          child: Padding(
                                            padding: EdgeInsets.fromLTRB(
                                                0, 10, 0, 10),
                                            child: Text(
                                              "Reply",
                                            ),
                                          ),
                                        ),
                                      ],
                                    )
                                  ],
                                ),
                              ),
                          ],
                        ),
                      ),
                    ),
                    secondChild: Container(
//                        height: !selected ? 100 : 400,
//                      key: _key,
                                            width: double.infinity,

                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(15),
                        color: Colors.white,
                        boxShadow: [
                          BoxShadow(
                            blurRadius: 2.5,
                            spreadRadius: 0.4,
                            color: Colors.grey,
                            offset: Offset(0, 0.5),
                          ),
                        ],
                      ),
                      child: Padding(
                        padding: EdgeInsets.all(17),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Move fridge up stairs',
                              style: TextStyle(fontSize: 16),
                            ),
                            SizedBox(height: 5),
                            Text(
                              'Sarah - 2 days ago - 2.3km',
                              style: TextStyle(color: Colors.black54),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    ));
  }
}
于 2020-10-18T06:32:43.300 回答