我希望DraggableScrollableSheet
当内部列表视图(里面的那个)到达顶部时开始最小化ItCrowdPage
,我尝试将它包裹在下面,NotificationListener
但它不起作用。
我试过的方法:-
NotificationListener<OverscrollNotification>(
onNotification: (value) {
if (value.overscroll < 0 &&
widget.scrollController.offset +
value.overscroll <=
0) {
if (widget.scrollController.offset != 0)
widget.scrollController.jumpTo(0);
} else if (widget.scrollController.offset +
value.overscroll >=
widget.scrollController.position
.maxScrollExtent) {
if (widget.scrollController.offset !=
widget.scrollController.position
.maxScrollExtent)
widget.scrollController.jumpTo(widget
.scrollController
.position
.maxScrollExtent);
}
widget.scrollController.jumpTo(
widget.scrollController.position.pixels +
value.overscroll);
return true;
},
child: ListView(
children: [
Padding(
padding:
const EdgeInsets.only(bottom: 10.0),
child: Text(
listOfCharacters[index]['name'],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
),
Container(
color: cc[index],
height: 50,
),
Container(
color: Colors.red,
height: 500,
)
],
),
);
完整代码片段:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(
const MyApp(),
);
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatelessWidget(),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Stack(children: [
DraggableScrollableSheet(
initialChildSize: 0.6,
minChildSize: 41 / MediaQuery.of(context).size.height,
maxChildSize: 0.6,
builder: (BuildContext context, ScrollController scrollController) {
return ItCrowdPage(
scrollController: scrollController,
);
},
),
]));
}
}
class ClampScroll extends ScrollBehavior {
@override
Widget buildViewportChrome(
BuildContext context, Widget child, AxisDirection axisDirection) {
return child;
}
}
class ItCrowdPage extends StatefulWidget {
final ScrollController scrollController;
const ItCrowdPage({Key key, @required this.scrollController})
: super(key: key);
@override
_ItCrowdPageState createState() => _ItCrowdPageState();
}
class _ItCrowdPageState extends State<ItCrowdPage> {
double viewPortFraction = 0.5;
PageController pageController, pageController2;
int currentPage = 0;
List<Map<String, String>> listOfCharacters = [
{'name': "Richmond"},
{'name': "Roy"},
{'name': "Moss"},
{'name': "Douglas"},
{'name': "Jen"}
];
double page = 0.0;
bool sc = false, sc2 = false;
@override
void initState() {
pageController = PageController(
initialPage: currentPage, viewportFraction: viewPortFraction);
pageController2 = PageController(initialPage: currentPage);
super.initState();
}
@override
void dispose() {
pageController.dispose();
pageController2.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
color: Colors.pink,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20))),
child: ScrollConfiguration(
behavior: ClampScroll(),
child: CustomScrollView(
controller: widget.scrollController,
slivers: [
SliverFillRemaining(
child: Column(
children: [
Container(
margin: EdgeInsets.all(10),
width: 42,
height: 6,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius:
const BorderRadius.all(Radius.circular(8))),
),
// Expanded(
// child: Container(
// color: Colors.blueAccent,
// ))
const SizedBox(
height: 9,
),
Flexible(
flex: 1,
fit: FlexFit.loose,
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification is UserScrollNotification &&
sc == false) {
setState(() {
sc = true;
sc2 = false;
});
// print("i: ll");
} else if (notification is ScrollUpdateNotification) {
if (pageController2.page != pageController.page &&
sc) {
pageController2.position
.jumpTo(pageController.position.pixels * 2);
}
setState(() {
page = pageController.page;
});
}
return true;
},
child: PageView.builder(
onPageChanged: (pos) {
setState(() {
currentPage = pos;
});
},
physics: BouncingScrollPhysics(),
pageSnapping: sc,
controller: pageController,
itemCount: listOfCharacters.length,
itemBuilder: (context, index) {
return Container(
color: Colors.blueAccent,
);
},
),
),
),
Flexible(
flex: 2,
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification.depth == 0 &&
notification is UserScrollNotification &&
sc2 == false) {
setState(() {
// i = 2;
sc = false;
sc2 = true;
});
// print("i: ll");
} else if (notification.depth == 0 &&
notification is ScrollUpdateNotification &&
sc2) {
// page = pageController2;
if (pageController2.page != pageController.page) {
pageController.position
.jumpTo(pageController2.position.pixels / 2);
}
}
return true;
},
child: PageView.builder(
pageSnapping: sc2,
controller: pageController2,
onPageChanged: (pos) {
setState(() {
currentPage = pos;
});
},
physics: BouncingScrollPhysics(),
itemCount: listOfCharacters.length,
itemBuilder: (context, index) {
return ListView(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Text(
listOfCharacters[index]['name'],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
),
Container(
color: cc[index],
height: 50,
),
Container(
color: Colors.red,
height: 500,
)
],
);
},
),
),
),
],
),
),
],
),
),
);
}
}
const List<Color> cc = [
Colors.black,
Colors.green,
Colors.purple,
Colors.yellow,
Colors.blueAccent
];