Skip to content

Instantly share code, notes, and snippets.

@tensor-programming
Last active January 31, 2023 19:35
Show Gist options
  • Save tensor-programming/7bafc564d46740c5f1ac51711a6552b6 to your computer and use it in GitHub Desktop.
Save tensor-programming/7bafc564d46740c5f1ac51711a6552b6 to your computer and use it in GitHub Desktop.
Flutter Column Animated expanded widgets
class ExpandableText extends StatefulWidget {
ExpandableText(this.text);
final String text;
@override
_ExpandableTextState createState() => _ExpandableTextState();
}
class _ExpandableTextState extends State<ExpandableText>
with TickerProviderStateMixin<ExpandableText> {
bool isExpanded = false;
@override
Widget build(BuildContext context) {
return Column(children: <Widget>[
AnimatedSize(
vsync: this,
duration: const Duration(milliseconds: 500),
child: ConstrainedBox(
constraints: isExpanded
? BoxConstraints()
: BoxConstraints(maxHeight: 50.0),
child: Text(
widget.text,
softWrap: true,
overflow: TextOverflow.fade,
))),
isExpanded
? ConstrainedBox(constraints: BoxConstraints())
: FlatButton(
child: const Text('...'),
onPressed: () => setState(() => isExpanded = true))
]);
}
}
class DemoPage extends StatefulWidget {
final Widget child;
DemoPage({Key key, this.child}) : super(key: key);
_DemoPageState createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
String descText =
"Description Line 1\nDescription Line 2\nDescription Line 3\nDescription Line 4\nDescription Line 5\nDescription Line 6\nDescription Line 7\nDescription Line 8";
bool descTextShowFlag = false;
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(descText,
maxLines: descTextShowFlag ? 8 : 2, textAlign: TextAlign.start),
InkWell(
onTap: () {
setState(() {
descTextShowFlag = !descTextShowFlag;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
descTextShowFlag
? Text(
"Show Less",
style: TextStyle(color: Colors.blue),
)
: Text("Show More", style: TextStyle(color: Colors.blue))
],
),
),
],
),
);
}
}
class CollapseWidget extends StatefulWidget {
@override
_CollapseWidgetState createState() => _CollapseWidgetState();
}
class _CollapseWidgetState extends State<CollapseWidget>
with TickerProviderStateMixin {
GlobalKey _keyFoldChild;
bool collapsed = false;
double _childWidth;
AnimationController _controller;
Animation<double> _sizeAnimation;
@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));
_keyFoldChild = GlobalKey();
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
}
void _afterLayout(_) {
final RenderBox renderBox = _keyFoldChild.currentContext.findRenderObject();
_sizeAnimation =
Tween<double>(begin: renderBox.size.height, end: 0.0).animate(_controller);
_childWidth = renderBox.size.width;
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {
collapsed = !collapsed;
});
if (collapsed) {
_controller.forward();
} else {
_controller.reverse();
}
},
child: Text("Click me"),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AnimatedContainer(
duration: Duration(seconds: 1),
height: collapsed ? 0 : 100,
color: Colors.orange,
child: Text("Just some text"),
),
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
if (_sizeAnimation == null) {
return child;
} else {
return ClipRect(
child: SizedOverflowBox(
size: Size(_childWidth, _sizeAnimation.value),
child: child,
),
);
}
},
child: Container(
key: _keyFoldChild,
color: Colors.red,
child: Text("Lorem Ipsum Dolar Sit"),
),
),
],
)
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment