skip to Main Content

I have a flip animation on an AnimatedSwitcher between two Card children.

Both Cards contain wrappable text of variable length. So they have different heights – one card might have 1 line of text, the other could have 10. The widths are the same.

When animated as a flipping animation, this looks odd, since it’s supposed to be a card flip but the front and back are different heights. It also causes some jank on the flip animation (the height snaps to the taller height when the animation starts).

I would like to fix this by making the shorter Card grow to the same height as the taller Card.

In other words the current flip animation is like this:

------------      ------------------
| Card one |  ->  | Taller card 2  | 
------------      | with more text |
                  ------------------

I would like to change it to:

------------      ------------------
| Card one |  ->  | Taller card 2  | 
|          |      | with more text |
------------      ------------------

The text can be variable length, so I don’t know how to pre-compute a fixed height (maybe there is a way?). And unlike a Row or something, the container only holds 1 card at the start & end of the animation, so I guess there is no easy way to just make the shorter Card "grow" since the taller Card is not even there?

2

Answers


  1. Chosen as BEST ANSWER

    My solution ended up being to use a addPostFrameCallback in initState to get the height of the front after rendering, and then forcing the back card to have that height.

        WidgetsBinding.instance.addPostFrameCallback((_) {
          final box =
              _frontGlobalKey.currentContext?.findRenderObject() as RenderBox;
          _heightNum = box.size.height;
        });
    

    This is not a fully correct solution b/c it fails on two points:

    1. The front card must always be taller than the back card. In my case, I was able to make this guarantee.

    2. If the card size changes, the height may not be correct. For example, if you load an image that changes the height.

    But for my purposes it's good enough and I think with a little more work on top of this approach, the other issues can be solved too.


  2. The simplest approach to achieve it is to use IntrinsicHeight

    1. Wrap your Row with IntrinsicHeight
    2. Set the Row‘s crossAxisAlignment into CrossAxisAlignment.stretch (for stretching the layout to max row sibling height)

    This is the example code:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Column(
              children: [
                IntrinsicHeight(
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Container(
                        color: Colors.blue,
                        width: 100,
                        child: Text('Box 1'),
                      ),
                      Container(
                        color: Colors.green,
                        width: 150,
                        child: Text('Box 2nwithndifferentnheights'),
                      ),
                      Container(
                        color: Colors.orange,
                        width: 75,
                        child: Text('Box 3'),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    *the code above is runnable in dartpad

    And this is the result:

    demo 1
    demo 2

    Hopefully it can solve your problem, Thanks 😉

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search