DartでのListViewの書き方その2
公開日: 2024-05-06 19:12:09
今回は前回のListViewの実用編として
・タイトルテキスト
・内容テキスト(10~200文字)
を実装することによってセルの高さを自動的に変更
セルをタップすることで詳細画面(item_detail_view.dart)に移行
この2つの機能を実装しました。
フォルダ構成
main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'view/item_list_view.dart';
import 'viewmodel/item_list_view_model.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => ItemListViewModel(),
child: MaterialApp(
title: 'MVVM ListView Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ItemListView(),
),
);
}
}
item.dart(model)
class Item {
final String title;
final String? message;
Item(this.title, [this.message]);
}
item_list_view_model.dart(viewModel)
import 'dart:math';
import 'package:flutter/material.dart';
import '../model/item.dart';
class ItemListViewModel extends ChangeNotifier {
final Random _random = Random();
// ランダムな文字列を生成
String _generateRandomString(int length) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
return String.fromCharCodes(
Iterable.generate(
length,
(_) => chars.codeUnitAt(_random.nextInt(chars.length)),
),
);
}
// アイテムを生成
Item _generateItem(int index) {
return Item(
"Title $index",
_generateRandomString(_random.nextInt(191) + 10),
);
}
// アイテムのリスト
late final List<Item> _items;
ItemListViewModel() {
_items = List<Item>.generate(50, (i) => _generateItem(i));
}
List<Item> get items => _items;
}
item_list_view.dart(view セルをタップした時に遷移するコードを追加)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../viewmodel/item_list_view_model.dart';
import 'item_detail_view.dart';
class ItemListView extends StatelessWidget {
const ItemListView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scrollable ListView'),
),
body: Column(
children: [
Expanded(
child: Consumer<ItemListViewModel>(
builder: (context, viewModel, child) {
return ListView.builder(
itemCount: viewModel.items.length,
itemBuilder: (context, index) {
final item = viewModel.items[index];
return Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey),
),
),
child: ListTile(
title: Text(item.title),
subtitle: Text(item.message ?? ""), // 2行目のテキスト
tileColor: Colors.blue[50], // 背景色
contentPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
onTap: () {
// タップ時の処理: 詳細画面にナビゲート
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailView(item: item),
),
);
},
),
);
},
);
},
),
),
],
),
);
}
}
item_detail_view.dart(詳細画面 新規追加)
import 'package:flutter/material.dart';
import '../model/item.dart';
class DetailView extends StatelessWidget {
final Item item;
const DetailView({super.key, required this.item});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(item.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(item.message ?? "No message available"),
),
);
}
}
実行結果

とても上手くいきました。
今回は画面遷移を少し使いましたが、画面遷移に関してももう少し深く掘り下げていきます。