Когда вложенная сжатая пленка CustomScrollView установлена в значение true, я не могу свернуть дочерние осколки.
Как прокрутить оба customScrollView и сделать так, чтобы дочерний customScrollView складывался до минимальной высоты.
Здесь в реальном времени demo
Моя конечная цель - сделать просмотр списка стековых карт с анимацией прокрутки
Есть ли другие решения? или есть способ решить эту проблему?
Дайте мне несколько советов мастерам:)
class AnimationTest extends StatefulWidget {
@override
_AnimationTestState createState() => _AnimationTestState();
}
class _AnimationTestState extends State<AnimationTest>
with WidgetsBindingObserver {
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print(state.toString());
}
@override
Widget build(BuildContext context) {
const double goldenRatio = 1.618;
final Size displaySize = MediaQuery.of(context).size;
final double minCardHeight = 24;
final double maxCardHeight = 80;
final List<Color> colors = Colors.primaries;
List<Color> _colors = List();
_colors.addAll(colors);
_colors.addAll(colors);
print(_colors.length);
return Scaffold(
body: Container(
color: Colors.white,
padding: EdgeInsets.only(top: 40),
alignment: AlignmentDirectional.center,
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CreditCard(),
Container(
width: displaySize.width * 0.85,
height: minCardHeight * _colors.length,
alignment: AlignmentDirectional.bottomCenter,
margin: EdgeInsets.all(0),
padding: EdgeInsets.all(0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
),
child: StackedList(
minCardHeight: minCardHeight,
maxCardHeight: maxCardHeight,
colors: _colors,
),
)
],
),
]),
)
],
),
),
);
}
}
class StackedList extends StatefulWidget {
final double minCardHeight;
final double maxCardHeight;
final List<Color> colors;
StackedList({
Key key,
this.colors,
this.maxCardHeight,
this.minCardHeight,
}) : super(key: key);
@override
_StackedListState createState() => _StackedListState();
}
class _StackedListState extends State<StackedList> {
@override
Widget build(BuildContext context) {
return CustomScrollView(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
slivers: <Widget>[
...widget.colors
.map(
(color) => StackedListChild(
minHeight: widget.minCardHeight,
maxHeight: widget.maxCardHeight,
floating: false,
pinned: true,
child: getCard(
cardId: widget.colors.indexOf(color).toString(),
color: color,
),
),
)
.toList(),
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
))
],
);
}
Widget getCard({String cardId, Color color}) {
const double cardWidth = 300;
const double cardHeight = 370;
return Hero(
tag: cardId,
child: Material(
elevation: 3,
color: Colors.white,
child: InkWell(
onTap: () => navigateToCardDetail(cardId: cardId, color: color),
child: Container(
width: cardWidth,
height: cardHeight,
color: color,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(8),
// topRight: Radius.circular(8),
// ),
// color: color,
// ),
),
),
),
);
}
navigateToCardDetail({String cardId, Color color}) {
var route = PageRouteBuilder(
pageBuilder: (context, animation, secondAnimation) =>
SecondPage(cardId: cardId, color: color),
barrierDismissible: true,
transitionDuration: const Duration(milliseconds: 300),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// var begin = Offset(0.0, 1.0);
// var end = Offset.zero;
// var curve = Curves.fastOutSlowIn;
// var tween =
// Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return FadeTransition(
//opacity: animation,
//position: animation.drive(tween),
opacity: animation,
child: child,
);
},
);
Navigator.of(context).push(route);
}
}
class StackedListChild extends StatelessWidget {
final double minHeight;
final double maxHeight;
final bool pinned;
final bool floating;
final Widget child;
SliverPersistentHeaderDelegate get _delegate => _StackedListDelegate(
minHeight: minHeight, maxHeight: maxHeight, child: child);
const StackedListChild({
Key key,
@required this.minHeight,
@required this.maxHeight,
@required this.child,
this.pinned = false,
this.floating = false,
}) : assert(child != null),
assert(minHeight != null),
assert(maxHeight != null),
assert(pinned != null),
assert(floating != null),
super(key: key);
@override
Widget build(BuildContext context) => SliverPersistentHeader(
key: key, pinned: pinned, floating: floating, delegate: _delegate);
}
class _StackedListDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
_StackedListDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
@override
bool shouldRebuild(_StackedListDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}