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

Flutter中使用OpenContainer向SearchPage传递选中数据的问题

解决OpenContainer中SubCategoriesContainerBar向SearchPage传递选中数据的两种方案

方案一:组件回调+外部变量传递

无需额外状态管理库,通过组件间回调和父组件变量传递实现数据共享:

  1. 在父组件中声明变量存储选中的分类:
String? selectedCategory;
  1. 给SubCategoriesContainerBar添加选中回调,触发时传递选中数据并打开容器:
class SubCategoriesContainerBar extends StatelessWidget {
  final List<String> categories;
  final VoidCallback openContainer;
  final ValueChanged<String> onCategorySelected;

  const SubCategoriesContainerBar({
    super.key,
    required this.categories,
    required this.openContainer,
    required this.onCategorySelected,
  });

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: categories.length,
      itemBuilder: (context, index) {
        return GestureDetector(
          onTap: () {
            onCategorySelected(categories[index]);
            openContainer();
          },
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12),
            child: Text(categories[index]),
          ),
        );
      },
    );
  }
}
  1. 父组件中更新OpenContainer,在closedBuilder中接收选中数据,openBuilder中传递给SearchPage:
OpenContainer<String>(
  closedShape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
  openShape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
  openBuilder: (_, closeContainer) => SearchPage(
    closeContainer: closeContainer,
    selectedCategory: selectedCategory,
  ),
  onClosed: (res) {
    print('test');
  },
  tappable: false,
  closedBuilder: (_, openContainer) => SubCategoriesContainerBar(
    categories: categories!,
    openContainer: openContainer,
    onCategorySelected: (category) => selectedCategory = category,
  ),
)
  1. SearchPage接收并使用选中数据:
class SearchPage extends StatelessWidget {
  final VoidCallback closeContainer;
  final String? selectedCategory;

  const SearchPage({
    super.key,
    required this.closeContainer,
    this.selectedCategory,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Search'),
        actions: [
          IconButton(
            icon: const Icon(Icons.close),
            onPressed: closeContainer,
          ),
        ],
      ),
      body: Center(
        child: Text('Selected Category: ${selectedCategory ?? 'No selection'}'),
      ),
    );
  }
}

方案二:使用Provider状态管理

如果需要跨多个组件共享选中状态,或者项目已使用Provider,可采用这种方式:

  1. 创建Provider类管理选中状态:
import 'package:flutter/foundation.dart';

class SelectedCategoryProvider extends ChangeNotifier {
  String? _selectedCategory;

  String? get selectedCategory => _selectedCategory;

  void updateSelectedCategory(String category) {
    _selectedCategory = category;
    notifyListeners();
  }
}
  1. 在应用根节点注册Provider:
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => SelectedCategoryProvider(),
      child: const MyApp(),
    ),
  );
}
  1. 修改SubCategoriesContainerBar,选中时更新Provider:
class SubCategoriesContainerBar extends StatelessWidget {
  final List<String> categories;
  final VoidCallback openContainer;

  const SubCategoriesContainerBar({
    super.key,
    required this.categories,
    required this.openContainer,
  });

  @override
  Widget build(BuildContext context) {
    final categoryProvider = Provider.of<SelectedCategoryProvider>(context, listen: false);
    
    return ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: categories.length,
      itemBuilder: (context, index) {
        return GestureDetector(
          onTap: () {
            categoryProvider.updateSelectedCategory(categories[index]);
            openContainer();
          },
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12),
            child: Text(categories[index]),
          ),
        );
      },
    );
  }
}
  1. SearchPage中监听Provider获取最新选中数据:
class SearchPage extends StatelessWidget {
  final VoidCallback closeContainer;

  const SearchPage({
    super.key,
    required this.closeContainer,
  });

  @override
  Widget build(BuildContext context) {
    final selectedCategory = Provider.of<SelectedCategoryProvider>(context).selectedCategory;
    
    return Scaffold(
      appBar: AppBar(
        title: const Text('Search'),
        actions: [
          IconButton(
            icon: const Icon(Icons.close),
            onPressed: closeContainer,
          ),
        ],
      ),
      body: Center(
        child: Text('Selected Category: ${selectedCategory ?? 'No selection'}'),
      ),
    );
  }
}
  1. 父组件的OpenContainer保持原有代码即可,无需额外变量:
OpenContainer<String>(
  closedShape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
  openShape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
  openBuilder: (_, closeContainer) => SearchPage(closeContainer),
  onClosed: (res) {
    print('test');
  },
  tappable: false,
  closedBuilder: (_, openContainer) => SubCategoriesContainerBar(
    categories: categories!,
    openContainer: openContainer,
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:17:04