Flutter ListView 滚动到索引滚动不足
Flutter ListView scroll to index insufficient scrolling
我有一个可展开的列表视图,但我有一个滚动问题。单独select滑动或者慢慢滑动都没有问题,但是滚动select快的时候就会滑动不足的问题
我加了一个'dartpad',这样代码就可以测试了。可能是什么问题?
代码:https://dartpad.dev/c4015095fc23456619eb20a5edcb0e8b
视频:https://vimeo.com/532603204
这是一个有趣的问题,我花了一些时间来处理这个问题,而且我在日志中看到滚动控制器似乎更新得很好。但是,出于某种原因,它不起作用,所以我在列表周围放置了滚动视图,并没有给 ListView.builder 滚动。只有这个要考虑的是列表的最后部分,因为如果你在最后部分,你不想向下滚动更多,因为你不能再向下滚动。
这可能不是最好的解决方案,但这是我设法组合在一起的,希望这对您有所帮助。
import 'dart:developer';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Scroll Bug Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
final _demoList = List.generate(100, (index) => 'List Item $index');
int _expandedIndex = -1;
final _scrollController = ScrollController();
bool _isExpanded = false;
bool _isInLastPart = false;
@override
Widget build(BuildContext context) {
_isInLastPart = (_expandedIndex > _demoList.length - 15);
final _size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
controller: _scrollController,
child: SizedBox(
height: (48 * _demoList.length).toDouble() +
((_isExpanded && _isInLastPart) ? 80 : 0).toDouble(),
width: _size.width,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => clickItem(index),
child: Container(
color: Colors.grey,
height: (_expandedIndex == index && _isExpanded) ? 120 : 40,
margin: EdgeInsets.only(bottom: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_demoList[index]),
if (_expandedIndex == index && _isExpanded)
Column(
children: <Widget>[
Text('text'),
Text('text'),
Text('text'),
Text('text'),
Text('text'),
],
),
],
),
),
);
},
itemCount: _demoList.length,
),
),
),
),
);
}
clickItem(int index) {
setState(() {
if (_expandedIndex == index)
_isExpanded = !_isExpanded;
else
_isExpanded = true;
_expandedIndex = index;
});
if (_expandedIndex < _demoList.length - 15) {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${index * 48.toDouble()}/${99 * 48.toDouble()}, scroll> ${_scrollController.position.pixels},isExpanded: $_isExpanded");
_scrollController.jumpTo(index * 48.toDouble());
} else {
if (_isExpanded) {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset},isExpanded: $_isExpanded");
_scrollController.jumpTo(83 * 48.toDouble() + 80 + 8);
} else {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 80 + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset}, isExpanded: $_isExpanded");
_scrollController.jumpTo(83 * 48.toDouble() + 8);
}
}
}
}
我有一个可展开的列表视图,但我有一个滚动问题。单独select滑动或者慢慢滑动都没有问题,但是滚动select快的时候就会滑动不足的问题
我加了一个'dartpad',这样代码就可以测试了。可能是什么问题?
代码:https://dartpad.dev/c4015095fc23456619eb20a5edcb0e8b
视频:https://vimeo.com/532603204
这是一个有趣的问题,我花了一些时间来处理这个问题,而且我在日志中看到滚动控制器似乎更新得很好。但是,出于某种原因,它不起作用,所以我在列表周围放置了滚动视图,并没有给 ListView.builder 滚动。只有这个要考虑的是列表的最后部分,因为如果你在最后部分,你不想向下滚动更多,因为你不能再向下滚动。
这可能不是最好的解决方案,但这是我设法组合在一起的,希望这对您有所帮助。
import 'dart:developer';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Scroll Bug Demo',
home: MainScreen(),
);
}
}
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
final _demoList = List.generate(100, (index) => 'List Item $index');
int _expandedIndex = -1;
final _scrollController = ScrollController();
bool _isExpanded = false;
bool _isInLastPart = false;
@override
Widget build(BuildContext context) {
_isInLastPart = (_expandedIndex > _demoList.length - 15);
final _size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
controller: _scrollController,
child: SizedBox(
height: (48 * _demoList.length).toDouble() +
((_isExpanded && _isInLastPart) ? 80 : 0).toDouble(),
width: _size.width,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => clickItem(index),
child: Container(
color: Colors.grey,
height: (_expandedIndex == index && _isExpanded) ? 120 : 40,
margin: EdgeInsets.only(bottom: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_demoList[index]),
if (_expandedIndex == index && _isExpanded)
Column(
children: <Widget>[
Text('text'),
Text('text'),
Text('text'),
Text('text'),
Text('text'),
],
),
],
),
),
);
},
itemCount: _demoList.length,
),
),
),
),
);
}
clickItem(int index) {
setState(() {
if (_expandedIndex == index)
_isExpanded = !_isExpanded;
else
_isExpanded = true;
_expandedIndex = index;
});
if (_expandedIndex < _demoList.length - 15) {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${index * 48.toDouble()}/${99 * 48.toDouble()}, scroll> ${_scrollController.position.pixels},isExpanded: $_isExpanded");
_scrollController.jumpTo(index * 48.toDouble());
} else {
if (_isExpanded) {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset},isExpanded: $_isExpanded");
_scrollController.jumpTo(83 * 48.toDouble() + 80 + 8);
} else {
// log("expanded index_: $_expandedIndex, index: $index, jump to: ${83 * 48.toDouble() + 80 + 8}/${99 * 48.toDouble()}, scroll> ${_scrollController.offset}, isExpanded: $_isExpanded");
_scrollController.jumpTo(83 * 48.toDouble() + 8);
}
}
}
}