前回のAppleMusicクローンアプリの続きです。
前回はmain.dartにレイアウトをただ並べて行きました。
その結果、一つのクラスでいろいろなクラスがごちゃまぜになりました。
今回はこのまま次の行の横スクロールを実装していくと
メンテナンスが大変になることを想定してレイアウトの分離を行います。
前回はヘッダーとListViewを作成しましたので「ヘッダー」部分と「ListView」部分を分けたいと思います。
- custom_sliver_appbar.dart (ヘッダー)
- custom_sliver_list.dart (ListView)
の命名でクラスを作成します。
スポンサーリンク
ヘッダー部分のソースコード
custom_sliver_appbar.dart
import 'package:flutter/material.dart';
class CustomAppBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverAppBar(
pinned: false,
backgroundColor: Colors.white,
expandedHeight: 40.0,
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.only(left: 20),
centerTitle: false,
title: Text(
'見つける',
style: TextStyle(color: Colors.black),
),
),
);
}
}
ListView部分のソースコード
custom_sliver_list.dart
import 'package:flutter/material.dart';
class ContentSliverList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
if (index == 0) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
height: 250,
child: ListView(
// This next line does the trick.
scrollDirection: Axis.horizontal,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: MediaQuery.of(context).size.width - 40.0,
color: Colors.red,
),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: MediaQuery.of(context).size.width - 40.0,
color: Colors.blue,
),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: MediaQuery.of(context).size.width - 40.0,
color: Colors.green,
),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: MediaQuery.of(context).size.width - 40.0,
color: Colors.yellow,
),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: MediaQuery.of(context).size.width - 40.0,
color: Colors.orange,
),
),
],
),
),
);
} else {
return Card(
child: ListTile(
title: Text("list item:$index"),
leading: Icon(Icons.photo),
),
);
}
},
childCount: 20,
),
);
}
}
main.dartの部分
main.dart
import 'package:apple_music_clone/widgets/content_sliver_list.dart';
import 'package:apple_music_clone/widgets/custom_sliver_appbar.dart';
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 Demo',
theme: ThemeData(),
home: HomePage(title: '見つける'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isVisibleHeader;
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(_scrollListener);
_isVisibleHeader = true;
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _scrollListener() {
print(_scrollController.offset);
if (_scrollController.offset > 100) {
setState(() {
_isVisibleHeader = true;
});
} else {
setState(() {
_isVisibleHeader = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: _isVisibleHeader ? 1.0 : 0.0,
backgroundColor: Colors.white,
title: Visibility(
visible: _isVisibleHeader,
child: Text(
'見つける',
style: TextStyle(color: Colors.black),
)),
),
body: CustomScrollView(
shrinkWrap: false,
controller: _scrollController,
slivers: <Widget>[
CustomAppBar(),
ContentSliverList()
],
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
ソースコードをビルドするとコンテンツ部分のセクション1が横スクロールできます。
ビルド時の挙動
次回からはcustom_sliver_list.dart
にどんどんレイアウトを乗せていく予定になります。
セクションの概念を導入する予定なのでDartでenum を使ってセクション分けしていきます。