Balbas Code

DartでのListViewの書き方その2

公開日: 2024-05-06 19:12:09

今回は前回のListViewの実用編として
・タイトルテキスト
・内容テキスト(10~200文字)
を実装することによってセルの高さを自動的に変更

セルをタップすることで詳細画面(item_detail_view.dart)に移行
この2つの機能を実装しました。


フォルダ構成
listview_folder

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"),
),
);
}
}



実行結果
listviewlistview


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