feat(app): 完善播放协议搜索与空状态
This commit is contained in:
1 parent
671e0ce143
commit
ef29fc5f15
85 files changed
+2976
-768
No files matched your search
@@ -20,6 +20,11 @@ import 'discover_binding.dart';
|
||||
import 'discover_logic.dart';
|
||||
import 'widgets/search_result_card.dart';
|
||||
|
||||
const double _clearHit = 20;
|
||||
const double _clearIconSize = 16;
|
||||
const double _clearEndGap = 10;
|
||||
const double _loadingInset = 2;
|
||||
|
||||
class SearchPage extends StatefulWidget {
|
||||
const SearchPage({super.key});
|
||||
|
||||
@@ -119,11 +124,10 @@ class _SearchPageState extends State<SearchPage> {
|
||||
}
|
||||
|
||||
Widget _field(AppLocalizations l10n) {
|
||||
final hasText = _logic.search.text.isNotEmpty;
|
||||
return Container(
|
||||
key: const Key('search-field'),
|
||||
height: AppDimens.searchHeight,
|
||||
padding: const EdgeInsets.symmetric(horizontal: AppDimens.spaceMd),
|
||||
padding: const EdgeInsets.only(left: AppDimens.spaceMd),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.contentSurface,
|
||||
borderRadius: BorderRadius.circular(AppDimens.searchRadius),
|
||||
@@ -143,7 +147,9 @@ class _SearchPageState extends State<SearchPage> {
|
||||
focusNode: _logic.searchFocus,
|
||||
autofocus: true,
|
||||
onChanged: (_) => _logic.onSearchChanged(),
|
||||
onTapOutside: (_) => _logic.searchFocus.unfocus(),
|
||||
textInputAction: TextInputAction.search,
|
||||
textAlignVertical: TextAlignVertical.center,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: 14,
|
||||
@@ -163,35 +169,64 @@ class _SearchPageState extends State<SearchPage> {
|
||||
scrollPadding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
if (_logic.searchLoading)
|
||||
const SizedBox.square(
|
||||
dimension: 16,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
)
|
||||
else if (hasText)
|
||||
IconButton(
|
||||
key: const Key('search-clear'),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints.tightFor(width: 24, height: 24),
|
||||
onPressed: () {
|
||||
_logic.search.clear();
|
||||
_logic.onSearchChanged();
|
||||
_logic.searchFocus.requestFocus();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.close_rounded,
|
||||
color: AppColors.textSecondary,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
_fieldTrailing(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 有内容时把清除按钮放在输入框内部右侧,并留出一点边距。
|
||||
/// 刷新时不拿转圈替换叉号,避免宽度变化把按钮抖开。
|
||||
Widget _fieldTrailing() {
|
||||
final hasText = _logic.search.text.isNotEmpty;
|
||||
if (!hasText && !_logic.searchLoading) {
|
||||
return const SizedBox(width: AppDimens.spaceMd);
|
||||
}
|
||||
return SizedBox(
|
||||
width: _clearHit + _clearEndGap,
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: _clearEndGap),
|
||||
child: hasText ? _clearButton() : _loadingMark(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _clearButton() {
|
||||
return GestureDetector(
|
||||
key: const Key('search-clear'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
_logic.search.clear();
|
||||
_logic.onSearchChanged();
|
||||
_logic.searchFocus.requestFocus();
|
||||
},
|
||||
child: const SizedBox.square(
|
||||
dimension: _clearHit,
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
color: AppColors.textSecondary,
|
||||
size: _clearIconSize,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _loadingMark() {
|
||||
return const SizedBox.square(
|
||||
dimension: _clearHit,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(_loadingInset),
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _body(AppLocalizations l10n) {
|
||||
if (!_logic.hasSearchQuery) {
|
||||
return _stateScroll(
|
||||
|
||||
Reference in new issue
Block a user