Last active
March 21, 2023 03:15
-
-
Save ykrods/3abbe700ba93e42d84d83409faf624c1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Flutter で PullToRefresh + InfiniteScroll 実装例 | |
* | |
* # ポイント | |
* - Mixin で InfinateScroll の実装を分割している | |
* | |
* # 課題 | |
* - ListView に対して ScrollController が一つしか指定できないので他にスクロール関連でやりたいことがある場合は | |
* このままの形では使えない | |
*/ | |
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
abstract class LoadMoreInterface { | |
Future<void> loadMore(); | |
} | |
mixin LoadMoreMixin<T extends StatefulWidget> on State<T> implements LoadMoreInterface { | |
Future<void>? loading; | |
late ScrollController _scrollController; | |
void initState() { | |
super.initState(); | |
_scrollController = ScrollController()..addListener(_scrollListener); | |
} | |
void dispose() { | |
super.dispose(); | |
_scrollController.removeListener(_scrollListener); | |
} | |
void _scrollListener() { | |
if (loading == null && _scrollController.position.extentAfter < 100) { | |
loading = loadMore().then((_) { | |
loading = null; | |
}).catchError((e) { | |
loading = null; | |
}); | |
} | |
} | |
} | |
class ListPage extends StatefulWidget { | |
const ListPage({ super.key }); | |
@override | |
State<ListPage> createState() => _ListPageState(); | |
} | |
class _ListPageState extends State<ListPage> with LoadMoreMixin { | |
int itemCount = 20; | |
loadMore() async { | |
print("load start"); | |
await Future.delayed(Duration(seconds: 1)); | |
setState(() { | |
itemCount += 20; | |
print("itemCount: ${itemCount}"); | |
}); | |
} | |
@override | |
void initState() { | |
super.initState(); | |
_refresh(); | |
} | |
void _refresh() { | |
print("refresh"); | |
itemCount = 20; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: RefreshIndicator( | |
color: Colors.white, | |
backgroundColor: Colors.blue, | |
onRefresh: () async => setState(_refresh), | |
child: ListView.builder( | |
// これを忘れると動かないので注意 | |
controller: _scrollController, | |
itemCount: itemCount, | |
itemBuilder: (context, index) => ListTile(title: Text(index.toString())) | |
) | |
) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment