fix:按照shadcn_ui对着demo_shadcn对齐

This commit is contained in:
jingyun
2026-06-05 15:04:39 +08:00
parent 9727b906c6
commit c5288f397d
29 changed files with 1425 additions and 642 deletions
+18 -115
View File
@@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../routing/app_router.dart';
import '../theme/app_theme.dart';
import '../theme/yanting_text.dart';
import '../theme/yanting_shad_theme.dart';
class ReportNotebooklmApp extends ConsumerWidget {
const ReportNotebooklmApp({super.key});
@@ -10,125 +14,24 @@ class ReportNotebooklmApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(routerProvider);
return MaterialApp.router(
final dmSansStyle = GoogleFonts.dmSans().copyWith(
fontFamilyFallback: YantingText.fontFallback,
);
return ShadApp.router(
title: '研听',
debugShowCheckedModeBanner: false,
theme: buildAppTheme(),
scrollBehavior: const WhitespaceStretchScrollBehavior(),
theme: buildYantingShadTheme(),
darkTheme: buildYantingDarkShadTheme(),
routerConfig: router,
);
}
}
class WhitespaceStretchScrollBehavior extends MaterialScrollBehavior {
const WhitespaceStretchScrollBehavior();
@override
Widget buildOverscrollIndicator(
BuildContext context,
Widget child,
ScrollableDetails details,
) {
return _WhitespaceStretchIndicator(child: child);
}
}
class _WhitespaceStretchIndicator extends StatefulWidget {
const _WhitespaceStretchIndicator({required this.child});
final Widget child;
@override
State<_WhitespaceStretchIndicator> createState() =>
_WhitespaceStretchIndicatorState();
}
class _WhitespaceStretchIndicatorState
extends State<_WhitespaceStretchIndicator>
with SingleTickerProviderStateMixin {
static const double _maxStretch = 64;
static const double _dragResistance = 0.38;
late final AnimationController _offsetController =
AnimationController.unbounded(vsync: this)..addListener(_onTick);
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: ClipRect(
child: Transform.translate(
offset: Offset(0, _offsetController.value),
child: widget.child,
),
),
);
}
@override
void dispose() {
_offsetController.dispose();
super.dispose();
}
bool _handleScrollNotification(ScrollNotification notification) {
if (notification.metrics.axis != Axis.vertical) {
return false;
}
if (notification is OverscrollNotification) {
final overscroll = notification.overscroll;
final atTop =
notification.metrics.pixels <= notification.metrics.minScrollExtent;
final atBottom =
notification.metrics.pixels >= notification.metrics.maxScrollExtent;
if (atTop && overscroll < 0) {
_setOffset(
(_offsetController.value - overscroll * _dragResistance).clamp(
0,
_maxStretch,
),
scrollBehavior: const ShadScrollBehavior(),
materialThemeBuilder: (context, theme) => buildAppTheme(),
builder: (context, child) {
return DefaultTextStyle.merge(
style: TextStyle(fontFamilyFallback: dmSansStyle.fontFamilyFallback),
child: child ?? const SizedBox.shrink(),
);
} else if (atBottom && overscroll > 0) {
_setOffset(
(_offsetController.value - overscroll * _dragResistance).clamp(
-_maxStretch,
0,
),
);
}
}
if (notification is ScrollUpdateNotification &&
notification.dragDetails == null) {
_releaseOffset();
}
if (notification is ScrollEndNotification) {
_releaseOffset();
}
return false;
}
void _setOffset(num next) {
if (next == _offsetController.value) {
return;
}
_offsetController.stop();
_offsetController.value = next.toDouble();
}
void _releaseOffset() {
if (_offsetController.value == 0) {
return;
}
_offsetController.animateTo(
0,
duration: const Duration(milliseconds: 260),
curve: Curves.easeOutCubic,
},
);
}
void _onTick() {
if (mounted) {
setState(() {});
}
}
}