J'ai l'exemple suivant (testé sur un iPhone X, iOS 11):
import 'package:flutter/material.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new ListView(
children: <Widget>[
new Container(
height: 40.0,
color: Colors.blue,
),
new Container(
height: 40.0,
color: Colors.red,
),
new Container(
height: 40.0,
color: Colors.green,
),
]
);
}
}
Dans ce cas, le ListView agit comme prévu. Je peux faire défiler au-delà de la fenêtre et le ListView rebondit à nouveau (comportement typique d'iOS). Mais lorsque j'ajoute un ScrollController pour suivre le décalage, le comportement du défilement change:
import 'package:flutter/material.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController _controller = new ScrollController();
@override
Widget build(BuildContext context) {
return new ListView(
controller: _controller,
children: <Widget>[
new Container(
height: 40.0,
color: Colors.blue,
),
new Container(
height: 40.0,
color: Colors.red,
),
new Container(
height: 40.0,
color: Colors.green,
),
]
);
}
}
Dans ce cas, le défilement n'est plus possible. Pourquoi est-ce que lorsque j'ajoute un ScrollController, le défilement n'est plus possible? L'ajout de physics: new BouncingScrollPhysics(),
à ListView n'aide pas non plus.
Merci pour toute aide :)
Pour que le défilement soit toujours activé sur un ListView
, vous pouvez encapsuler la phisique de défilement d'origine que vous souhaitez avec la classe AlwaysScrollableScrollPhysics
. Plus de détails ici . Si vous le souhaitez, vous pouvez spécifier un parent
ou vous fier à la valeur par défaut.
Voici votre exemple avec l'option ajoutée:
import 'package:flutter/material.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController _controller = new ScrollController();
@override
Widget build(BuildContext context) {
return new ListView(
physics: const AlwaysScrollableScrollPhysics(), // new
controller: _controller,
children: <Widget>[
new Container(
height: 40.0,
color: Colors.blue,
),
new Container(
height: 40.0,
color: Colors.red,
),
new Container(
height: 40.0,
color: Colors.green,
),
]
);
}
}
Je pense que cette solution est meilleure sans CustomScrollView. Utilisez simplement NotificationListener pour envelopper le ListView.
Widget noti = new NotificationListener(
child:listView,
onNotification: (ScrollNotification note){
print(note.metrics.pixels.toInt());
},
);
Je l'ai testé, Bounce est efficace
Ajoutez simplement AlwaysScrollableScrollPhysics
ListView(
physics: const AlwaysScrollableScrollPhysics(),
children : [...]
}
J'ai trouvé une solution pour suivre l'offset avec des listes qui ont une hauteur de contenu plus petite que la fenêtre. Utilisez un NotificationListener
avec un CustomScrollView
dans la méthode build()
comme ceci:
import 'package:flutter/material.Dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController _controller = new ScrollController();
@override
Widget build(BuildContext context) {
return new NotificationListener(
onNotification: _handleScrollPosition,
child: new CustomScrollView(
slivers: [
new SliverList(
delegate: new SliverChildListDelegate([
new Container(
height: 40.0,
color: Colors.blue,
),
new Container(
height: 40.0,
color: Colors.red,
),
new Container(
height: 40.0,
color: Colors.green,
),
])
)
]
)
);
}
bool _handleScrollPosition(ScrollNotification notification) {
print(notification.metrics.pixels);
return true;
}
}
Tant qu'il n'y aura pas de solution avec une solution ScrollController
uniquement (ou une solution "meilleure" (plus élégante)), j'accepterai cela comme la réponse.