|
1 | 1 | import 'package:flutter/material.dart'; |
2 | 2 |
|
3 | | -class FlexibleSpaceCustom extends StatelessWidget { |
4 | | - const FlexibleSpaceCustom({Key key, this.title}) : super(key: key); |
5 | 3 |
|
| 4 | +class AppBarExpandable extends StatefulWidget { |
| 5 | + const AppBarExpandable({Key key, this.leading, this.title = '', this.actions, this.scrollController}) : super(key: key); |
| 6 | + |
| 7 | + final ScrollController scrollController; |
| 8 | + final Widget leading; |
6 | 9 | final String title; |
| 10 | + final List<Widget> actions; |
7 | 11 |
|
8 | 12 | @override |
9 | | - Widget build(BuildContext context) { |
10 | | - var _theme = Theme.of(context); |
| 13 | + _AppBarExpandableState createState() => _AppBarExpandableState(); |
| 14 | +} |
11 | 15 |
|
12 | | - return LayoutBuilder( |
13 | | - builder: (BuildContext context, BoxConstraints constraints) { |
14 | | - double percent = (constraints.maxHeight - kToolbarHeight); |
15 | | - double dx = 0; |
| 16 | +class _AppBarExpandableState extends State<AppBarExpandable> { |
16 | 17 |
|
17 | | - dx = 80 - percent; |
18 | | - if (constraints.maxHeight == 100) { |
19 | | - dx = 0; |
20 | | - } |
21 | | - return Stack( |
22 | | - alignment: Alignment.centerLeft, |
23 | | - children: <Widget>[ |
24 | | - Padding( |
25 | | - padding: const EdgeInsets.only(top: kToolbarHeight / 4, left: 0.0), |
26 | | - child: Transform.translate( |
27 | | - child: Text(title, |
28 | | - style: _theme.textTheme.headline1, |
29 | | - ), |
30 | | - offset: Offset( |
31 | | - dx, constraints.maxHeight - kToolbarHeight), |
32 | | - ), |
33 | | - ), |
34 | | - ], |
35 | | - ); |
36 | | - } |
37 | | - ); |
| 18 | + |
| 19 | + @override |
| 20 | + initState() { |
| 21 | + widget.scrollController.addListener(() => refresh()); |
| 22 | + super.initState(); |
38 | 23 | } |
39 | | -} |
40 | 24 |
|
| 25 | + void refresh() { |
| 26 | + setState(() { |
41 | 27 |
|
42 | | -class AppBarExpandable extends StatelessWidget { |
43 | | - const AppBarExpandable({Key key, this.leading, this.title = '', this.actions}) : super(key: key); |
| 28 | + }); |
| 29 | + } |
44 | 30 |
|
45 | | - final Widget leading; |
46 | | - final String title; |
47 | | - final List<Widget> actions; |
| 31 | + double get _horizontalTitlePadding { |
| 32 | + const kBasePadding = 15.0; |
| 33 | + const kMultiplier = 0.7; |
| 34 | + const kExpandedHeight = 120; |
| 35 | + |
| 36 | + if (widget.scrollController.hasClients) { |
| 37 | + |
| 38 | + if (widget.scrollController.offset > (kExpandedHeight - kToolbarHeight)) { |
| 39 | + return (kExpandedHeight - kToolbarHeight) * kMultiplier + |
| 40 | + kBasePadding; |
| 41 | + } |
| 42 | + |
| 43 | + return (widget.scrollController.offset) * kMultiplier + kBasePadding; |
| 44 | + } |
| 45 | + |
| 46 | + return kBasePadding; |
| 47 | + } |
48 | 48 |
|
49 | 49 | @override |
50 | 50 | Widget build(BuildContext context) { |
51 | | - var _theme = Theme.of(context); |
52 | | - |
53 | 51 | return SliverAppBar( |
54 | 52 | pinned: true, |
55 | | - snap: false, |
56 | | - floating: false, |
57 | | - expandedHeight: 100.0, |
58 | | - centerTitle: true, |
59 | | - backgroundColor: _theme.appBarTheme.backgroundColor, |
60 | | - leading: leading ?? IconButton( |
61 | | - onPressed: () { |
62 | | - Navigator.of(context).pop(); |
63 | | - }, |
64 | | - icon: Icon(Icons.chevron_left, color: _theme.iconTheme.color), |
| 53 | + expandedHeight: 120, |
| 54 | + backgroundColor: Theme.of(context).appBarTheme.backgroundColor, |
| 55 | + leading: widget.leading ?? SizedBox(), |
| 56 | + actions: widget.actions ?? [], |
| 57 | + flexibleSpace: FlexibleSpaceBar( |
| 58 | + title: Text(widget.title), |
| 59 | + titlePadding: EdgeInsets.symmetric( |
| 60 | + vertical: 16.0, horizontal: _horizontalTitlePadding, |
| 61 | + ), |
65 | 62 | ), |
66 | | - flexibleSpace: FlexibleSpaceCustom(title: title), |
67 | | - actions: actions ?? [], |
68 | 63 | ); |
69 | 64 | } |
70 | 65 | } |
0 commit comments