import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:win_text_editor/shared/components/text_editor.dart'; import 'package:win_text_editor/frame/tab_manager.dart'; import 'package:win_text_editor/frame/models/tab_model.dart'; import 'package:win_text_editor/modules/content_search/widgets/content_search_view.dart'; class TabView extends StatelessWidget { final List tabs; final String? currentTabId; const TabView({super.key, required this.tabs, required this.currentTabId}); @override Widget build(BuildContext context) { final activeTab = tabs.firstWhere( (tab) => tab.id == currentTabId, orElse: () => AppTab(id: '', title: ''), // 提供默认值 ); return Column( children: [ // 选项卡标签栏 _buildTabBar(context), // 选项卡内容区 Expanded( child: activeTab.id.isNotEmpty ? _buildTabContent(activeTab) : const Center(child: Text('无活动标签页')), ), ], ); } Widget _buildTabBar(BuildContext context) { return SizedBox( height: 40, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: tabs.length, itemBuilder: (ctx, index) { final tab = tabs[index]; return _TabItem( tab: tab, isActive: tab.id == currentTabId, onClose: () => context.read().closeTab(tab.id), onTap: () => context.read().setActiveTab(tab.id), ); }, ), ); } Widget _buildTabContent(AppTab tab) { return IndexedStack( index: tabs.indexWhere((tab) => tab.id == currentTabId).clamp(0, tabs.length - 1), children: tabs.map((tab) { return findActiveView(tab); }).toList(), ); } // 查找当前活动的视图 Widget findActiveView(AppTab tab) { switch (tab.type) { case 'content_search': return ContentSearchView(tabId: tab.id); default: return TextEditor(tabId: tab.id, initialContent: tab.content); } } } class _TabItem extends StatelessWidget { final AppTab tab; final bool isActive; final VoidCallback onClose; final VoidCallback onTap; const _TabItem({ required this.tab, required this.isActive, required this.onClose, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: isActive ? Colors.blue[100] : Colors.grey[200], border: Border( bottom: BorderSide(color: isActive ? Colors.blue : Colors.transparent, width: 2), ), ), child: Row( children: [ if (tab.icon != null) Icon(tab.icon, size: 16), if (tab.icon != null) const SizedBox(width: 4), Text(tab.title), const SizedBox(width: 8), IconButton(icon: const Icon(Icons.close, size: 16), onPressed: onClose), ], ), ), ); } }