731 lines
25 KiB
Dart
731 lines
25 KiB
Dart
/*
|
||
* 文件: search_page.dart
|
||
* 名称: 搜索页面
|
||
* 作用: iOS 26 风格的菜谱搜索页面,支持搜索历史、热门搜索、实时搜索
|
||
* 更新: 2026-04-10 完全重写,优化UI和交互体验
|
||
*/
|
||
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart' show Colors;
|
||
import 'package:get/get.dart';
|
||
import '../../controllers/search_controller.dart';
|
||
import '../../config/design_tokens.dart';
|
||
import '../../models/recipe/recipe_model.dart';
|
||
import '../../widgets/recipe_image.dart';
|
||
|
||
class SearchPage extends StatefulWidget {
|
||
const SearchPage({super.key});
|
||
|
||
@override
|
||
State<SearchPage> createState() => _SearchPageState();
|
||
}
|
||
|
||
class _SearchPageState extends State<SearchPage> {
|
||
late final SearchController _searchController;
|
||
final TextEditingController _textEditingController = TextEditingController();
|
||
final FocusNode _focusNode = FocusNode();
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_searchController = Get.find<SearchController>();
|
||
_focusNode.requestFocus();
|
||
_checkInitialKeyword();
|
||
}
|
||
|
||
void _checkInitialKeyword() {
|
||
final args = Get.arguments;
|
||
if (args is Map<String, dynamic> && args.containsKey('keyword')) {
|
||
final keyword = args['keyword'] as String;
|
||
if (keyword.isNotEmpty) {
|
||
_textEditingController.text = keyword;
|
||
_searchController.search(keyword);
|
||
_focusNode.unfocus();
|
||
}
|
||
} else if (args is String && args.isNotEmpty) {
|
||
_textEditingController.text = args;
|
||
_searchController.search(args);
|
||
_focusNode.unfocus();
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_textEditingController.dispose();
|
||
_focusNode.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final isDark = CupertinoTheme.brightnessOf(context) == Brightness.dark;
|
||
|
||
return CupertinoPageScaffold(
|
||
backgroundColor: isDark
|
||
? DarkDesignTokens.background
|
||
: DesignTokens.background,
|
||
navigationBar: CupertinoNavigationBar(
|
||
middle: _buildSearchBar(isDark),
|
||
backgroundColor: isDark
|
||
? DarkDesignTokens.background.withValues(alpha: 0.9)
|
||
: DesignTokens.background.withValues(alpha: 0.9),
|
||
border: null,
|
||
leading: CupertinoButton(
|
||
padding: EdgeInsets.zero,
|
||
child: Icon(
|
||
CupertinoIcons.back,
|
||
color: isDark ? DarkDesignTokens.text1 : DesignTokens.text1,
|
||
),
|
||
onPressed: () => Get.back(),
|
||
),
|
||
),
|
||
child: SafeArea(child: Obx(() => _buildContent(isDark))),
|
||
);
|
||
}
|
||
|
||
Widget _buildSearchBar(bool isDark) {
|
||
return Container(
|
||
height: 36,
|
||
decoration: BoxDecoration(
|
||
color: (isDark ? DarkDesignTokens.text3 : DesignTokens.text3)
|
||
.withValues(alpha: 0.1),
|
||
borderRadius: BorderRadius.circular(10),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
const SizedBox(width: 8),
|
||
Icon(
|
||
CupertinoIcons.search,
|
||
size: 18,
|
||
color: isDark ? DarkDesignTokens.text2 : DesignTokens.text2,
|
||
),
|
||
const SizedBox(width: 6),
|
||
Expanded(
|
||
child: CupertinoTextField(
|
||
controller: _textEditingController,
|
||
focusNode: _focusNode,
|
||
placeholder: '搜索菜谱、食材...',
|
||
placeholderStyle: TextStyle(
|
||
fontSize: 15,
|
||
color: isDark ? DarkDesignTokens.text2 : DesignTokens.text2,
|
||
),
|
||
style: TextStyle(
|
||
fontSize: 15,
|
||
color: isDark ? DarkDesignTokens.text1 : DesignTokens.text1,
|
||
),
|
||
decoration: const BoxDecoration(border: null),
|
||
onSubmitted: (value) {
|
||
if (value.trim().isNotEmpty) {
|
||
_searchController.search(value);
|
||
_focusNode.unfocus();
|
||
}
|
||
},
|
||
onChanged: (value) {
|
||
if (value.isEmpty) {
|
||
_searchController.clearResults();
|
||
}
|
||
},
|
||
),
|
||
),
|
||
if (_textEditingController.text.isNotEmpty)
|
||
CupertinoButton(
|
||
minimumSize: Size.zero,
|
||
padding: const EdgeInsets.all(4),
|
||
onPressed: () {
|
||
_textEditingController.clear();
|
||
_searchController.clearResults();
|
||
_focusNode.requestFocus();
|
||
},
|
||
child: Icon(
|
||
CupertinoIcons.xmark_circle_fill,
|
||
size: 20,
|
||
color: isDark ? DarkDesignTokens.text3 : DesignTokens.text3,
|
||
),
|
||
)
|
||
else
|
||
const SizedBox(width: 8),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildContent(bool isDark) {
|
||
if (_searchController.searchQuery.value.isEmpty) {
|
||
return _buildInitialView(isDark);
|
||
} else if (_searchController.isLoading.value) {
|
||
return _buildLoadingView(isDark);
|
||
} else if (_searchController.searchResults.isEmpty) {
|
||
return _buildEmptyView(isDark);
|
||
} else {
|
||
return _buildResultsView(isDark);
|
||
}
|
||
}
|
||
|
||
Widget _buildInitialView(bool isDark) {
|
||
return SingleChildScrollView(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: DesignTokens.space4,
|
||
vertical: DesignTokens.space4,
|
||
),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 搜索历史
|
||
Obx(() {
|
||
if (_searchController.searchHistory.isEmpty) {
|
||
return const SizedBox.shrink();
|
||
}
|
||
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||
children: [
|
||
Text(
|
||
'🕐 搜索历史',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontLg,
|
||
fontWeight: FontWeight.w600,
|
||
color: isDark
|
||
? DarkDesignTokens.text1
|
||
: DesignTokens.text1,
|
||
),
|
||
),
|
||
CupertinoButton(
|
||
minimumSize: Size.zero,
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 8,
|
||
vertical: 4,
|
||
),
|
||
onPressed: () => _searchController.clearSearchHistory(),
|
||
child: Text(
|
||
'清空',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontSm,
|
||
color: isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: DesignTokens.space3),
|
||
Wrap(
|
||
spacing: DesignTokens.space2,
|
||
runSpacing: DesignTokens.space2,
|
||
children: _searchController.searchHistory.map((history) {
|
||
return GestureDetector(
|
||
onTap: () {
|
||
_textEditingController.text = history;
|
||
_searchController.search(history);
|
||
},
|
||
onLongPress: () =>
|
||
_showRemoveHistoryDialog(history, isDark),
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 14,
|
||
vertical: 8,
|
||
),
|
||
decoration: BoxDecoration(
|
||
color:
|
||
(isDark
|
||
? DarkDesignTokens.text3
|
||
: DesignTokens.text3)
|
||
.withValues(alpha: 0.08),
|
||
borderRadius: BorderRadius.circular(20),
|
||
),
|
||
child: Text(
|
||
history,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontSm,
|
||
color: isDark
|
||
? DarkDesignTokens.text1
|
||
: DesignTokens.text1,
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}).toList(),
|
||
),
|
||
const SizedBox(height: DesignTokens.space5),
|
||
],
|
||
);
|
||
}),
|
||
|
||
// 热门搜索
|
||
Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
'🔥 热门搜索',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontLg,
|
||
fontWeight: FontWeight.w600,
|
||
color: isDark ? DarkDesignTokens.text1 : DesignTokens.text1,
|
||
),
|
||
),
|
||
const SizedBox(height: DesignTokens.space3),
|
||
Wrap(
|
||
spacing: DesignTokens.space2,
|
||
runSpacing: DesignTokens.space2,
|
||
children: _searchController.hotSearches.map((keyword) {
|
||
return GestureDetector(
|
||
onTap: () {
|
||
_textEditingController.text = keyword;
|
||
_searchController.search(keyword);
|
||
},
|
||
child: Container(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 14,
|
||
vertical: 8,
|
||
),
|
||
decoration: BoxDecoration(
|
||
gradient: LinearGradient(
|
||
colors: [
|
||
(isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary)
|
||
.withValues(alpha: 0.12),
|
||
(isDark
|
||
? DarkDesignTokens.secondary
|
||
: DesignTokens.secondary)
|
||
.withValues(alpha: 0.08),
|
||
],
|
||
),
|
||
borderRadius: BorderRadius.circular(20),
|
||
border: Border.all(
|
||
color:
|
||
(isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary)
|
||
.withValues(alpha: 0.2),
|
||
width: 0.5,
|
||
),
|
||
),
|
||
child: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Text(
|
||
keyword,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontSm,
|
||
color: isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary,
|
||
fontWeight: FontWeight.w500,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}).toList(),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showRemoveHistoryDialog(String history, bool isDark) {
|
||
showCupertinoDialog(
|
||
context: context,
|
||
builder: (context) => CupertinoAlertDialog(
|
||
title: const Text('删除记录'),
|
||
content: Text('确定要删除"$history"吗?'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
isDefaultAction: true,
|
||
child: const Text('取消'),
|
||
onPressed: () => Navigator.pop(context),
|
||
),
|
||
CupertinoDialogAction(
|
||
isDestructiveAction: true,
|
||
child: const Text('删除'),
|
||
onPressed: () {
|
||
_searchController.removeFromHistory(history);
|
||
Navigator.pop(context);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildLoadingView(bool isDark) {
|
||
return Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
const CupertinoActivityIndicator(radius: 16),
|
||
const SizedBox(height: DesignTokens.space3),
|
||
Text(
|
||
'正在搜索"${_searchController.searchQuery.value}"...',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontMd,
|
||
color: isDark ? DarkDesignTokens.text2 : DesignTokens.text2,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildEmptyView(bool isDark) {
|
||
return SingleChildScrollView(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: DesignTokens.space4,
|
||
vertical: DesignTokens.space6,
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Container(
|
||
width: 80,
|
||
height: 80,
|
||
decoration: BoxDecoration(
|
||
color: (isDark ? DarkDesignTokens.text3 : DesignTokens.text3)
|
||
.withValues(alpha: 0.08),
|
||
shape: BoxShape.circle,
|
||
),
|
||
child: Icon(
|
||
CupertinoIcons.search,
|
||
size: 40,
|
||
color: isDark ? DarkDesignTokens.text3 : DesignTokens.text3,
|
||
),
|
||
),
|
||
const SizedBox(height: DesignTokens.space4),
|
||
Text(
|
||
'未找到"${_searchController.searchQuery.value}"相关菜谱',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontLg,
|
||
fontWeight: FontWeight.w500,
|
||
color: isDark ? DarkDesignTokens.text1 : DesignTokens.text1,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: DesignTokens.space2),
|
||
Text(
|
||
'试试其他关键词,如"红烧肉"、"糖醋排骨"',
|
||
textAlign: TextAlign.center,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontSm,
|
||
color: isDark ? DarkDesignTokens.text2 : DesignTokens.text2,
|
||
),
|
||
),
|
||
const SizedBox(height: DesignTokens.space5),
|
||
SizedBox(
|
||
width: 200,
|
||
height: 44,
|
||
child: CupertinoButton.filled(
|
||
borderRadius: BorderRadius.circular(22),
|
||
onPressed: () {
|
||
_textEditingController.clear();
|
||
_searchController.clearResults();
|
||
_focusNode.requestFocus();
|
||
},
|
||
child: const Text(
|
||
'重新搜索',
|
||
style: TextStyle(fontWeight: FontWeight.w500),
|
||
),
|
||
),
|
||
),
|
||
Obx(() {
|
||
if (!_searchController.hasSimilarResults.value ||
|
||
_searchController.similarResults.isEmpty) {
|
||
return const SizedBox();
|
||
}
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const SizedBox(height: DesignTokens.space6),
|
||
Row(
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.lightbulb,
|
||
size: 18,
|
||
color: isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary,
|
||
),
|
||
const SizedBox(width: 6),
|
||
Text(
|
||
'相似推荐',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontMd,
|
||
fontWeight: FontWeight.w600,
|
||
color: isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: DesignTokens.space3),
|
||
..._searchController.similarResults.map(
|
||
(recipe) => _buildSimilarItem(recipe, isDark),
|
||
),
|
||
],
|
||
);
|
||
}),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildSimilarItem(RecipeModel recipe, bool isDark) {
|
||
return GestureDetector(
|
||
onTap: () {
|
||
Get.toNamed('/recipe-detail', arguments: '${recipe.id}');
|
||
},
|
||
child: Container(
|
||
margin: const EdgeInsets.only(bottom: DesignTokens.space2),
|
||
padding: const EdgeInsets.all(DesignTokens.space3),
|
||
decoration: BoxDecoration(
|
||
color: isDark ? DarkDesignTokens.card : DesignTokens.card,
|
||
borderRadius: DesignTokens.borderRadiusMd,
|
||
border: Border.all(
|
||
color: (isDark ? DarkDesignTokens.text3 : DesignTokens.text3)
|
||
.withValues(alpha: 0.1),
|
||
),
|
||
),
|
||
child: Row(
|
||
children: [
|
||
ClipRRect(
|
||
borderRadius: DesignTokens.borderRadiusSm,
|
||
child: RecipeImage(
|
||
recipeId: recipe.id,
|
||
coverUrl: recipe.cover,
|
||
width: 48,
|
||
height: 48,
|
||
fit: BoxFit.cover,
|
||
mode: RecipeImageMode.thumbnail,
|
||
),
|
||
),
|
||
const SizedBox(width: DesignTokens.space3),
|
||
Expanded(
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
recipe.title,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontMd,
|
||
fontWeight: FontWeight.w500,
|
||
color: isDark
|
||
? DarkDesignTokens.text1
|
||
: DesignTokens.text1,
|
||
),
|
||
maxLines: 1,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
if (recipe.intro != null && recipe.intro!.isNotEmpty)
|
||
Text(
|
||
recipe.intro!,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontXs,
|
||
color: isDark
|
||
? DarkDesignTokens.text3
|
||
: DesignTokens.text3,
|
||
),
|
||
maxLines: 1,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
Icon(
|
||
CupertinoIcons.chevron_forward,
|
||
size: 16,
|
||
color: isDark ? DarkDesignTokens.text3 : DesignTokens.text3,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildResultsView(bool isDark) {
|
||
return Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 结果统计栏
|
||
Container(
|
||
width: double.infinity,
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: DesignTokens.space4,
|
||
vertical: DesignTokens.space2,
|
||
),
|
||
decoration: BoxDecoration(
|
||
border: Border(
|
||
bottom: BorderSide(
|
||
color: (isDark ? DarkDesignTokens.text3 : DesignTokens.text3)
|
||
.withValues(alpha: 0.1),
|
||
),
|
||
),
|
||
),
|
||
child: Text(
|
||
'找到 ${_searchController.searchResults.length} 个结果 · "${_searchController.searchQuery.value}"',
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontXs,
|
||
color: isDark ? DarkDesignTokens.text2 : DesignTokens.text2,
|
||
),
|
||
),
|
||
),
|
||
|
||
// 结果列表
|
||
Expanded(
|
||
child: ListView.separated(
|
||
padding: const EdgeInsets.all(DesignTokens.space4),
|
||
itemCount: _searchController.searchResults.length,
|
||
separatorBuilder: (_, _) =>
|
||
const SizedBox(height: DesignTokens.space3),
|
||
itemBuilder: (context, index) {
|
||
final recipe = _searchController.searchResults[index];
|
||
return _buildRecipeItem(recipe, isDark);
|
||
},
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget _buildRecipeItem(dynamic recipe, bool isDark) {
|
||
final title = recipe.title ?? '未知菜谱';
|
||
final intro = recipe.intro ?? '';
|
||
final category = recipe.categoryName;
|
||
final cover = recipe.cover;
|
||
final recipeId = recipe.id;
|
||
|
||
return GestureDetector(
|
||
behavior: HitTestBehavior.opaque,
|
||
onTap: () {
|
||
try {
|
||
debugPrint('Tapped recipe: $title (ID: $recipeId)');
|
||
|
||
if (recipeId == null || recipeId <= 0) {
|
||
Get.snackbar('提示', '菜谱 ID 无效', snackPosition: SnackPosition.BOTTOM);
|
||
return;
|
||
}
|
||
|
||
Get.toNamed('/recipe-detail', arguments: '$recipeId');
|
||
} catch (e, stackTrace) {
|
||
debugPrint('Open recipe detail error: $e');
|
||
debugPrint('Stack trace: $stackTrace');
|
||
Get.snackbar(
|
||
'错误',
|
||
'无法打开菜谱详情: $e',
|
||
snackPosition: SnackPosition.BOTTOM,
|
||
);
|
||
}
|
||
},
|
||
child: Container(
|
||
padding: const EdgeInsets.all(DesignTokens.space3),
|
||
decoration: BoxDecoration(
|
||
color: isDark ? DarkDesignTokens.card : DesignTokens.card,
|
||
borderRadius: BorderRadius.circular(DesignTokens.radiusMd),
|
||
boxShadow: [
|
||
BoxShadow(
|
||
color: Colors.black.withValues(alpha: 0.03),
|
||
blurRadius: 10,
|
||
offset: const Offset(0, 2),
|
||
),
|
||
],
|
||
),
|
||
child: Row(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 封面图
|
||
ClipRRect(
|
||
borderRadius: BorderRadius.circular(DesignTokens.radiusSm),
|
||
child: RecipeImage(
|
||
recipeId: recipeId ?? 0,
|
||
coverUrl: cover,
|
||
width: 90,
|
||
height: 90,
|
||
fit: BoxFit.cover,
|
||
mode: RecipeImageMode.thumbnail,
|
||
),
|
||
),
|
||
const SizedBox(width: DesignTokens.space3),
|
||
|
||
// 信息区
|
||
Expanded(
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Text(
|
||
title,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontMd,
|
||
fontWeight: FontWeight.w600,
|
||
color: isDark
|
||
? DarkDesignTokens.text1
|
||
: DesignTokens.text1,
|
||
),
|
||
maxLines: 2,
|
||
overflow: TextOverflow.ellipsis,
|
||
),
|
||
if (category != null && category!.isNotEmpty) ...[
|
||
const SizedBox(height: 4),
|
||
Container(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 6,
|
||
vertical: 2,
|
||
),
|
||
decoration: BoxDecoration(
|
||
color:
|
||
(isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary)
|
||
.withValues(alpha: 0.1),
|
||
borderRadius: BorderRadius.circular(4),
|
||
),
|
||
child: Text(
|
||
'📂 $category',
|
||
style: TextStyle(
|
||
fontSize: 11,
|
||
color: isDark
|
||
? DarkDesignTokens.primary
|
||
: DesignTokens.primary,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
if (intro.isNotEmpty) ...[
|
||
const SizedBox(height: 6),
|
||
Text(
|
||
intro,
|
||
maxLines: 2,
|
||
overflow: TextOverflow.ellipsis,
|
||
style: TextStyle(
|
||
fontSize: DesignTokens.fontSm,
|
||
color: isDark
|
||
? DarkDesignTokens.text2
|
||
: DesignTokens.text2,
|
||
height: 1.3,
|
||
),
|
||
),
|
||
],
|
||
],
|
||
),
|
||
),
|
||
|
||
// 箭头
|
||
Padding(
|
||
padding: const EdgeInsets.only(left: 8, top: 4),
|
||
child: Icon(
|
||
CupertinoIcons.chevron_right,
|
||
size: 16,
|
||
color: isDark ? DarkDesignTokens.text3 : DesignTokens.text3,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|