You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.2 KiB
114 lines
3.2 KiB
2 months ago
|
import 'package:flutter/material.dart';
|
||
2 months ago
|
import 'package:provider/provider.dart';
|
||
2 months ago
|
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';
|
||
2 months ago
|
|
||
|
class TabView extends StatelessWidget {
|
||
|
final List<AppTab> 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<TabManager>().closeTab(tab.id),
|
||
|
onTap: () => context.read<TabManager>().setActiveTab(tab.id),
|
||
|
);
|
||
|
},
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Widget _buildTabContent(AppTab tab) {
|
||
2 months ago
|
return IndexedStack(
|
||
|
index: tabs.indexWhere((tab) => tab.id == currentTabId).clamp(0, tabs.length - 1),
|
||
|
children:
|
||
|
tabs.map((tab) {
|
||
2 months ago
|
return findActiveView(tab);
|
||
2 months ago
|
}).toList(),
|
||
|
);
|
||
2 months ago
|
}
|
||
2 months ago
|
|
||
|
// 查找当前活动的视图
|
||
|
Widget findActiveView(AppTab tab) {
|
||
|
switch (tab.type) {
|
||
|
case 'content_search':
|
||
|
return ContentSearchView(tabId: tab.id);
|
||
|
default:
|
||
|
return TextEditor(tabId: tab.id, initialContent: tab.content);
|
||
|
}
|
||
|
}
|
||
2 months ago
|
}
|
||
|
|
||
|
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),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|