質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

1回答

3024閲覧

[Flutter]お気に入りボタンを押した際に、リストの全てにお気に入りマークがついてしまう。

namihana

総合スコア23

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

1グッド

0クリップ

投稿2020/02/17 14:00

リスト内のお気に入りボタンを押したところ、現状全てのリストにお気に入りマークがついてしまうので、それを個別につくようにしたいと思っております。[画像参照]

現状ハートボタンを押すと、ハートON/OFFは切り替わりますが、全てのハートマークが同時にトグルされてしまいます。
Widgetsを分けてみたりしたのですが、結果は同じでどうしても一つ一つにON/OFFを実装することができません。
Flutter自体が始めたばかりで理解がまだよくできていないのですが、どなたかわかる方はいらっしゃいますでしょうか。

![イメージ説明]

↓リストのCardのwidgetです。

class ListCards extends StatelessWidget { var name; ListCards({@required this.name}); @override Widget build(BuildContext context) { return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15.0), ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15.0), gradient: LinearGradient( colors: [ Colors.lightBlue, Colors.lightBlueAccent, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: ListTile( contentPadding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0), onTap: () { Navigator.of(context).pushNamed( SentencesScreen.routeName, arguments: { 'id': name.id.toString(), 'title': name.title.toString(), }, ); }, leading: Text( name.id + '.', style: TextStyle( color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold, ), ), title: Container( child: Text( name.title, style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), trailing: Material( color: Colors.transparent, child: Consumer<Course>( builder: (context, color, _) => IconButton( icon: Icon(color.isFavorite ? Icons.favorite : Icons.favorite_border), iconSize: 40, autofocus: true, highlightColor: Colors.pinkAccent, hoverColor: Colors.pink, onPressed: () { color.favoriteToggle(); }, ), ), ), ), ), ); } }

↓ここでListViewをビルドしています。

class CourseList extends StatelessWidget { var name; CourseList({@required this.name}); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(8), itemCount: name.length, itemBuilder: (context, index) { return ListCards(name: name[index]); } ); } }

↓各コースのmodelとお気に入りのの動作を調整しています。

class Course with ChangeNotifier { final String id; final String title; final Color color; bool isFavorite; Course({ @required this.id, @required this.title, this.color = Colors.blue, this.isFavorite = false, }); void favoriteToggle() { isFavorite = !isFavorite; notifyListeners(); } }
popobot👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ListCards内でConsumer<Course>を実行していますが、ChangeNotifierProviderが適切な位置にないため、お気に入りボタンの状態が共用されてしまっているんだと思います。

掲載されたコードには、ChangeNotifierProviderがないので、どのようにCourseを渡しているかわかりませんが、以下のようにCourseListからListCardsを呼び出す際に、ChangeNotifierProviderで状態を渡せばうまくいくと思います

class CourseList extends StatelessWidget { var name; CourseList({@required this.name}); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(8), itemCount: name.length, itemBuilder: (context, index) { return ChangeNotifierProvider<Course>.value( value: name[index], child: ListCards(name: name[index]), ); }); } }

一応、動作確認したコード全部も貼っておきます

import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter Demo'), ), body: Container( child: CourseList(name: Courses().list), ), ); } } class ListCards extends StatelessWidget { var name; ListCards({@required this.name}); @override Widget build(BuildContext context) { return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15.0), ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(15.0), gradient: LinearGradient( colors: [ Colors.lightBlue, Colors.lightBlueAccent, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: ListTile( contentPadding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0), onTap: () { Navigator.of(context).pushNamed( 'SentencesScreen.routeName', // XXX arguments: { 'id': name.id.toString(), 'title': name.title.toString(), }, ); }, leading: Text( name.id + '.', style: TextStyle( color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold, ), ), title: Container( child: Text( name.title, style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white, ), ), ), trailing: Material( color: Colors.transparent, child: Consumer<Course>( builder: (context, color, _) => IconButton( icon: Icon( color.isFavorite ? Icons.favorite : Icons.favorite_border), iconSize: 40, autofocus: true, highlightColor: Colors.pinkAccent, hoverColor: Colors.pink, onPressed: () { color.favoriteToggle(); }, ), ), ), ), ), ); } } class CourseList extends StatelessWidget { var name; CourseList({@required this.name}); @override Widget build(BuildContext context) { return ListView.builder( padding: const EdgeInsets.all(8), itemCount: name.length, itemBuilder: (context, index) { return ChangeNotifierProvider<Course>.value( value: name[index], child: ListCards(name: name[index]), ); }); } } class Courses { final List<Course> list = [ Course(id: 'b1', title: '自己紹介をしよう'), Course(id: 'b2', title: '宿にチェックインしよう'), Course(id: 'b3', title: '空港で英会話'), Course(id: 'b3', title: 'カフェで注文'), ]; } class Course with ChangeNotifier { final String id; final String title; final Color color; bool isFavorite; Course({ @required this.id, @required this.title, this.color = Colors.blue, this.isFavorite = false, }); void favoriteToggle() { isFavorite = !isFavorite; notifyListeners(); } }

おまけ:似たようなことをやろうとしている記事を見つけたので参考に貼っておきます。

投稿2020/02/17 20:46

popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

namihana

2020/02/18 11:54

ご回答大変ありがとうございました!ChangeNotifierProviderでvalueを渡すというところがすっかり抜けておりました。無事動作させることができました。数日悩んでいたのでとても助かりました。 ありがとうございます。m(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問