Как сделать прокручиваемый ListView внутри одного из элементов "SliverFixedExtentList" с помощью "customScrollView" во флаттере?
Я использую "CustomScrollView"
с "SliverPersistentHeader"
а также "SliverFixedExtentList"
. Я пытаюсь не делать данные в столбце (виджет "ListTest") прокручиваемыми до заголовкаSliverPersistentHeader
добраться до вершины. Означает, что если пользователь попытается прокрутить"ListTest" data
, SliverPersistentHeader
сначала должен быть наверху, затем данные в "listTest" станут прокручиваемыми. Я знаю, это может показаться глупым, если я использую"column"
вместо того "listview"
, Я попытался использовать "Просмотр списка" на фоновом изображении (который является частью виджета "foodContent"), но это не сработало так, как я хотел. Это так неприятно, пожалуйста, помогите кому-нибудь. Любая эффективная альтернатива для достижения этого будет оценена по достоинству.
Вот изображение того, что я получаю https://i.imgur.com/CEZyiLM.gif
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Material(
type: MaterialType.transparency,
child: Stack(
children: <Widget>[
Container(
child: CustomScrollView(
slivers: <Widget>[
SliverPersistentHeader(
pinned: true,
floating: false,
delegate: SliverAppBarDelegateClass(
maxExtent: deviceSize.height * 0.37,
minExtent: deviceSize.height * 0.15,
),
),
SliverFixedExtentList(
itemExtent: deviceSize.height * 0.850,
delegate: SliverChildListDelegate(
[
FoodContent(),
],
),
),
],
),
),
// NavBar(),
],
),
);
}
}
class FoodContent extends StatefulWidget {
@override
_FoodContentState createState() => _FoodContentState();
}
class _FoodContentState extends State<FoodContent> {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
FoodContentBg(), // THIS IS THE CURVED SHAPE BACKGROUND THAT I WANT TO STICK AND COLUMN DATA
// START TOO SCROLL AS USER SCROLL SliverPersistentHeader TO THE TOP
listTest(), // THIS LIST SHOULD NOT BE SCROLL ABLE UNTILL SliverPersistentHeader TITLE GET
// TO TOP
SearchBar(),
],
);
}
}
// **This "LISTTEST" contains "Column" containing example data**
class listTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 100, bottom: 80),
child: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(15),
color: Colors.red,
width: MediaQuery.of(context).size.width / 2,
child: Text("data1",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
color: Colors.green,
padding: EdgeInsets.all(15),
width: MediaQuery.of(context).size.width / 2,
child: Text("data2",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.brown,
width: MediaQuery.of(context).size.width / 2,
child: Text("data3",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.blue,
width: MediaQuery.of(context).size.width / 2,
child: Text("data4",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
Container(
padding: EdgeInsets.all(15),
color: Colors.purple,
width: MediaQuery.of(context).size.width / 2,
child: Text("data5",
style: TextStyle(fontSize: 60, color: Colors.white)),
),
],
),
),
),
);
}
}
***This delegate might not be needed to extract solution but I paste it here anyways,***
class SliverAppBarDelegateClass extends SliverPersistentHeaderDelegate {
SliverAppBarDelegateClass({
this.maxExtent,
this.minExtent,
});
final double maxExtent;
final double minExtent;
@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent,
) {
final deviceSize = MediaQuery.of(context).size;
final double visibleMainHeight = max(maxExtent - shrinkOffset, minExtent);
final double animationVal = scrollAnimationValue(shrinkOffset);
return Container(
height: visibleMainHeight,
width: deviceSize.width,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
// ------------------------------------------------------ C U S T O M I R I Z I N G A P P B A R A N I M A T I O N
Container(
color: Colors.black.withOpacity(0.5),
),
Opacity(
opacity: animationVal,
child: HomeCoverBg(),
),
Positioned(
bottom: deviceSize.height *
0.003,
child: SizedBox(
width: deviceSize.width,
child: Row(
children: <Widget>[
Expanded(
flex: (animationVal * 20)
.toInt(), // Decrease the size on the left of titles (Row animation)
child: Container(),
),
Titles(),
Expanded(
flex: 120,
child: Container(),
)
],
),
),
),
],
),
);
}
double scrollAnimationValue(double shrinkOffset) {
return 1.0 -
max(0.0, shrinkOffset) /
maxExtent; //// simple formula: fade out or scroll text as soon as shrinkOffset > 0
}
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}