You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现点击按钮在首页添加Explore页面选中的Card组件求助

Flutter 实现收藏/书签功能

问题概述

需要实现:在Explore页面点击Card右侧的添加按钮,将该Card内容同步到Home页面展示。

解决方案

通过父组件维护状态+回调传递数据的方式实现,无需复杂状态管理库,适合入门场景:


1. 定义统一数据模型

创建Item类封装Card的所有数据,方便跨页面传递:

class Item {
  final String title;
  final String subtitle;
  final String avatarUrl;

  Item({required this.title, required this.subtitle, required this.avatarUrl});
}

2. 改造Home页面,负责收藏数据管理

将原pushAdd替换为展示收藏列表的FavoritePage,同时在Home中维护收藏列表,并提供添加收藏的方法:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'explore.dart';
import 'fav.dart';
import 'login.dart';

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

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

class _HomeState extends State<Home> {
  late String uid;
  int _selectedIndex = 0;
  final List<Item> _favoriteItems = [];

  // 添加收藏,自动去重
  void _addFavorite(Item item) {
    setState(() {
      if (!_favoriteItems.any((e) => e.title == item.title)) {
        _favoriteItems.add(item);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
        actions: [
          IconButton(
            icon: const Icon(Icons.logout),
            onPressed: () async {
              await FirebaseAuth.instance.signOut();
              Navigator.pushAndRemoveUntil(
                context,
                MaterialPageRoute(builder: (context) => const LoginScreen()),
                (route) => false,
              );
            },
          )
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: 'Home'),
          BottomNavigationBarItem(icon: Icon(Icons.book_outlined), label: 'Explore'),
          BottomNavigationBarItem(icon: Icon(Icons.person_outlined), label: 'Profile'),
        ],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
      ),
      body: IndexedStack(
        index: _selectedIndex,
        children: [
          FavoritePage(favoriteItems: _favoriteItems),
          ExploreScreen(onAddFavorite: _addFavorite),
          const RandWords(),
        ],
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    uid = FirebaseAuth.instance.currentUser!.uid;
  }

  void _onItemTapped(int index) => setState(() => _selectedIndex = index);
}

// 展示收藏内容的页面
class FavoritePage extends StatelessWidget {
  final List<Item> favoriteItems;

  const FavoritePage({Key? key, required this.favoriteItems}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: favoriteItems.isEmpty
          ? const Center(child: Text('暂无收藏内容'))
          : ListView.builder(
              itemCount: favoriteItems.length,
              itemBuilder: (context, index) {
                final item = favoriteItems[index];
                return Card(
                  child: ListTile(
                    title: Text(item.title),
                    subtitle: Text(item.subtitle),
                    leading: CircleAvatar(backgroundImage: NetworkImage(item.avatarUrl)),
                  ),
                );
              },
            ),
    );
  }
}

3. 修改Explore页面,绑定收藏逻辑

让ExploreScreen接收添加收藏的回调,点击按钮时传递对应Item数据:

import 'package:flutter/material.dart';
import 'home.dart';

class ExploreScreen extends StatelessWidget {
  final Function(Item) onAddFavorite;

  const ExploreScreen({Key? key, required this.onAddFavorite}) : super(key: key);

  @override
  Widget build(BuildContext context) => ListViewHome(onAddFavorite: onAddFavorite);
}

class ListViewHome extends StatelessWidget {
  final Function(Item) onAddFavorite;
  final List<Item> items = [
    Item(
      title: "List 1",
      subtitle: "Here is list 1 subtitle",
      avatarUrl: "https://images.unsplash.com/photo-1547721064-da6cfb341d50",
    ),
    Item(
      title: "List 2",
      subtitle: "Here is list 2 subtitle",
      avatarUrl: "https://images.unsplash.com/photo-1547721064-da6cfb341d50",
    ),
    Item(
      title: "List 3",
      subtitle: "Here is list 3 subtitle",
      avatarUrl: "https://images.unsplash.com/photo-1547721064-da6cfb341d50",
    ),
    Item(
      title: "List 4",
      subtitle: "Here is list 4 subtitle",
      avatarUrl: "https://images.unsplash.com/photo-1547721064-da6cfb341d50",
    ),
  ];

  ListViewHome({Key? key, required this.onAddFavorite}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        final item = items[index];
        return Card(
          child: ListTile(
            title: Text(item.title),
            subtitle: Text(item.subtitle),
            leading: CircleAvatar(backgroundImage: NetworkImage(item.avatarUrl)),
            trailing: IconButton(
              onPressed: () {
                onAddFavorite(item);
                // 添加收藏提示
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('已添加「${item.title}」到收藏')),
                );
              },
              icon: const Icon(Icons.add),
            ),
          ),
        );
      },
    );
  }
}

效果演示

操作演示

内容的提问来源于stack exchange,提问作者Ankit Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:27:27