mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/app.git
synced 2025-07-01 00:11:57 +08:00
feat: 42kit Nav
feat: Animation Optimization
This commit is contained in:
203
lib/ui/nav/nav_ui.dart
Normal file
203
lib/ui/nav/nav_ui.dart
Normal file
@ -0,0 +1,203 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter/gestures.dart' show TapGestureRecognizer;
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:flutter_tilt/flutter_tilt.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:starcitizen_doctor/ui/nav/nav_state.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'package:starcitizen_doctor/widgets/widgets.dart';
|
||||
|
||||
class NavUI extends HookConsumerWidget {
|
||||
const NavUI({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: buildBody(context, ref),
|
||||
),
|
||||
SizedBox(height: 6),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(children: [
|
||||
TextSpan(text: "*对应链接指向的服务由第三方提供,我们不对其做任何担保,请用户自行判断使用风险 | "),
|
||||
TextSpan(text: "网站导航数据由"),
|
||||
TextSpan(
|
||||
text: " 42kit ",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
launchUrlString("https://42kit.citizenwiki.cn/nav");
|
||||
},
|
||||
),
|
||||
TextSpan(text: "提供"),
|
||||
]),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white.withValues(alpha: .6),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBody(BuildContext context, WidgetRef ref) {
|
||||
final data = ref.watch(navProvider);
|
||||
if (data.errorInfo.isNotEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
data.errorInfo,
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.items == null) {
|
||||
return const Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(height: 12),
|
||||
Text("正在获取数据..."),
|
||||
],
|
||||
));
|
||||
}
|
||||
return MasonryGridView.count(
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 12,
|
||||
crossAxisSpacing: 12,
|
||||
itemCount: data.items!.length,
|
||||
padding: EdgeInsets.only(left: 12, right: 12, bottom: 12),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
const itemHeight = 160.0;
|
||||
|
||||
final item = data.items![index];
|
||||
final itemName = item.name;
|
||||
final itemImage = item.image.url;
|
||||
return GridItemAnimator(
|
||||
index: index,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlString(item.link);
|
||||
},
|
||||
child: Tilt(
|
||||
shadowConfig: const ShadowConfig(maxIntensity: .3),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: SizedBox(
|
||||
height: itemHeight,
|
||||
width: double.infinity,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: CacheNetImage(
|
||||
height: itemHeight,
|
||||
width: double.infinity,
|
||||
url: itemImage,
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: .55),
|
||||
),
|
||||
),
|
||||
ClipRect(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
|
||||
blendMode: BlendMode.srcOver,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: itemHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(),
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: CacheNetImage(
|
||||
url: itemImage,
|
||||
height: 48,
|
||||
width: 48,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Flexible(
|
||||
child: Text(
|
||||
itemName,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
item.abstract_,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: .75)),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
for (var value in item.tags)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.withValues(alpha: .6),
|
||||
borderRadius: BorderRadius.circular(12)),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 3),
|
||||
margin: EdgeInsets.only(right: 6),
|
||||
child: Text(
|
||||
value.name,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user