はじめに
業務でPageViewを使ったので、備忘録代わりにまとめてみます。
Flutter初心者なので、間違ってる部分があったらご指摘ください。
参考
下記を参考にさせていただきました。
https://qiita.com/yoshua/items/741038cb8c8c8bf0e873
動作イメージ
PageViewのスワイプと、ボタンタップでスクロールするようにしました。
実装
ここは特にコメントはありません。
class TestScreen extends StatefulWidget {
/// constructors
const TestScreen({
Key key,
}) : super(key: key);
@override
State<StatefulWidget> createState() => _TestScreenState();
}
initState時にPageControllerを用意します。
addListenerでスクロールの検知ができます。
あとで出てくる_MyPageView部分が、今回メインで作成したいPageViewです。
そのほか、RaisedButtonのonPressedでページ送り/戻しをしています。
todoで書いてありますが、_currentPageのmaxとminの制御が必要です
(動的に変化する場合も多いと思うので、ここでは割愛してます)。
class _TestScreenState extends State<TestScreen> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
final _myPageViewKey = GlobalKey<_MyPageViewState>();
PageController _pageController;
int _currentPage = 0;
@override
void initState() {
super.initState();
_pageController = PageController();
_pageController.addListener(() {
final nextPage = _pageController.page.round();
if (_currentPage != nextPage) {
_currentPage = nextPage;
}
});
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('test'),
),
backgroundColor: Colors.white,
body: Builder(
builder: (context) => SafeArea(
child: Column(
children: [
_MyPageView(
key: _myPageViewKey,
pageController: _pageController,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
_currentPage--; // todo: ページ数に応じた制御が必要
_pageController.animateToPage(_currentPage,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut);
},
child: const Text('前へ'),
),
RaisedButton(
onPressed: () {
_currentPage++; // todo: ページ数に応じた制御が必要
_pageController.animateToPage(_currentPage,
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut);
},
child: const Text('次へ'),
),
],
),
],
),
),
));
}
今回メインで作成したいPageViewです。
class _MyPageView extends StatefulWidget {
/// constructors
const _MyPageView({
Key key,
this.pageController,
}) : super(key: key);
final PageController pageController;
@override
State<StatefulWidget> createState() => _MyPageViewState();
}
PageView自体と、各ページを作成します。
class _MyPageViewState extends State<_MyPageView> {
var _currentViewPage = 0;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) => Column(
children: [
_buildPageView(),
],
);
Widget _buildPageView() => ConstrainedBox(
constraints: const BoxConstraints.expand(height: 100),
child: PageView(
onPageChanged: (page) {
_currentViewPage = page;
},
controller: widget.pageController,
children: List<Widget>.generate(
10, // ページ数 todo: 動的に変えるか、定数にする
_buildPageViewChild),
),
);
// ページビュー各ページ
Widget _buildPageViewChild(int pageIndex) => Row(
children: [
Expanded(
child: Container(
color: Colors.grey,
child: Center(child: Text('$pageIndex')),
),
)
],
);
}