Trailing icon property of ListTile removed when I tapped on bottomnavigationbar 'favorite'

Viewed 46

I have a GIF to describe below. And how to when I tapped on trailing icon at the music_page.dart, then the music_favorite_page.dart will build value that.

This main.dart

import 'package:abc/pages/music_page.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _currentIndex = 0;
  final List<Widget> _children = [MusicPage(), MusicFavoritePage()];

  void _onTappedBar(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // appBar: AppBar(
      //   title: Text("App"),
      // ),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: _onTappedBar,
        currentIndex: _currentIndex,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.library_music),
            title: Text("Music"),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            title: Text("Favorite"),
          ),
        ],
      ),
    );
  }
}

This music_page.dart

import 'package:flutter/material.dart';

class MusicPage extends StatefulWidget {
  MusicPage({Key key}) : super(key: key);

  @override
  _MusicPageState createState() => _MusicPageState();
}

class _MusicPageState extends State<MusicPage>
    with AutomaticKeepAliveClientMixin {
  final _karaokeList = Karaoke.getAll();
  final _savedKaraoke = <Karaoke>{};

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("Music"),
      ),
      body: _buildListViewKaraokeList(),
    );
  }

  Widget _buildListViewKaraokeList() {
    return ListView.builder(
      itemCount: _karaokeList.length,
      itemBuilder: (context, index) =>
          _buildListTileKaraokeList(_karaokeList[index]),
    );
  }

  Widget _buildListTileKaraokeList(Karaoke karaoke) {
    final _isTapped = _savedKaraoke.contains(karaoke);

    return ListTile(
      leading: Text(karaoke.maBaiHat),
      title: Text(karaoke.tenBaiHat),
      subtitle: Text(karaoke.tenCaSi),
      trailing: Icon(
        _isTapped ? Icons.favorite : Icons.favorite_border,
        color: _isTapped ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (_isTapped) {
            _savedKaraoke.remove(karaoke);
          } else {
            _savedKaraoke.add(karaoke);
          }
        });
      },
    );
  }

  @override
  bool get wantKeepAlive => true;
}

This music_favorite_page.dart


class MusicFavoritePage extends StatefulWidget {
  MusicFavoritePage({Key key}) : super(key: key);

  @override
  _MusicFavoritePageState createState() => _MusicFavoritePageState();
}

class _MusicFavoritePageState extends State<MusicFavoritePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Music Favorite"),
      ),
      body: Center(
        child: Text("Music Favorite Page"),
      ),
    );
  }
}

GIF:

1

2 Answers

You can copy paste run full code below
You can use PageView, you can see working demo below
code snippet

void _onTappedBar(int index) {
    print("onItemSelected");
    setState(() => _currentIndex = index);
    _pageController.jumpToPage(index);
  }
...  
body: SizedBox.expand(
        child: PageView(
          controller: _pageController,
          children: _children,
          onPageChanged: (int index) {
            print("onPageChanged");
            setState(() {
              _currentIndex = index;
            });
          },
        ),

working demo

enter image description here

full code

import 'package:flutter/material.dart';

class Karaoke {
  String maBaiHat;
  String tenBaiHat;
  String tenCaSi;

  Karaoke({this.maBaiHat, this.tenBaiHat, this.tenCaSi});
}

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _currentIndex = 0;
  PageController _pageController = PageController();
  final List<Widget> _children = [MusicPage(), MusicFavoritePage()];

  void _onTappedBar(int index) {
    print("onItemSelected");
    setState(() => _currentIndex = index);
    _pageController.jumpToPage(index);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox.expand(
        child: PageView(
          controller: _pageController,
          children: _children,
          onPageChanged: (int index) {
            print("onPageChanged");
            setState(() {
              _currentIndex = index;
            });
          },
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        selectedItemColor: Colors.amber[800],
        unselectedItemColor: Colors.blue,
        onTap: _onTappedBar,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.library_music),
            title: Text("Music"),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            title: Text("Favorite"),
          ),
        ],
      ),
    );
  }
}

class MusicPage extends StatefulWidget {
  MusicPage({Key key}) : super(key: key);

  @override
  _MusicPageState createState() => _MusicPageState();
}

class _MusicPageState extends State<MusicPage>
    with AutomaticKeepAliveClientMixin {
  final _karaokeList = [
    Karaoke(maBaiHat: "a", tenBaiHat: "a1", tenCaSi: "a2"),
    Karaoke(maBaiHat: "b", tenBaiHat: "b1", tenCaSi: "b2"),
    Karaoke(maBaiHat: "c", tenBaiHat: "c1", tenCaSi: "c2")
  ]; //Karaoke.getAll();
  final _savedKaraoke = <Karaoke>{};

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      appBar: AppBar(
        title: Text("Music"),
      ),
      body: _buildListViewKaraokeList(),
    );
  }

  Widget _buildListViewKaraokeList() {
    return ListView.builder(
      itemCount: _karaokeList.length,
      itemBuilder: (context, index) =>
          _buildListTileKaraokeList(_karaokeList[index]),
    );
  }

  Widget _buildListTileKaraokeList(Karaoke karaoke) {
    final _isTapped = _savedKaraoke.contains(karaoke);

    return ListTile(
      leading: Text(karaoke.maBaiHat),
      title: Text(karaoke.tenBaiHat),
      subtitle: Text(karaoke.tenCaSi),
      trailing: Icon(
        _isTapped ? Icons.favorite : Icons.favorite_border,
        color: _isTapped ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (_isTapped) {
            _savedKaraoke.remove(karaoke);
          } else {
            _savedKaraoke.add(karaoke);
          }
        });
      },
    );
  }

  @override
  bool get wantKeepAlive => true;
}

class MusicFavoritePage extends StatefulWidget {
  MusicFavoritePage({Key key}) : super(key: key);

  @override
  _MusicFavoritePageState createState() => _MusicFavoritePageState();
}

class _MusicFavoritePageState extends State<MusicFavoritePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Music Favorite"),
      ),
      body: Center(
        child: Text("Music Favorite Page"),
      ),
    );
  }
}

Right now, whenever you visit the MusicPage, _savedKaraoke list is setting a null array like {} in here:

    final _savedKaraoke = <Karaoke>{};

For a very simple solution, you can use app state provider to get or set the _savedKaraoke list.

Related