Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-02-06 20:58:49 +08:00
parent 7ab2cf973f
commit cc1704a021
4 changed files with 39 additions and 21 deletions

View File

@@ -43,10 +43,10 @@ class DynamicSliverAppBarMedium extends StatefulWidget {
this.forceMaterialTransparency = false, this.forceMaterialTransparency = false,
this.clipBehavior, this.clipBehavior,
this.appBarClipper, this.appBarClipper,
this.afterCalc, this.onPerformLayout,
}); });
final ValueChanged<double>? afterCalc; final ValueChanged<double>? onPerformLayout;
final Widget? flexibleSpace; final Widget? flexibleSpace;
final Widget? leading; final Widget? leading;
final bool automaticallyImplyLeading; final bool automaticallyImplyLeading;
@@ -93,7 +93,6 @@ class DynamicSliverAppBarMedium extends StatefulWidget {
} }
class _DynamicSliverAppBarMediumState extends State<DynamicSliverAppBarMedium> { class _DynamicSliverAppBarMediumState extends State<DynamicSliverAppBarMedium> {
final GlobalKey _key = GlobalKey();
double? _height; double? _height;
double? _width; double? _width;
late double _topPadding; late double _topPadding;
@@ -112,18 +111,17 @@ class _DynamicSliverAppBarMediumState extends State<DynamicSliverAppBarMedium> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_height == null) { if (_height == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_height =
(_key.currentContext!.findRenderObject() as RenderBox).size.height;
widget.afterCalc?.call(_height!);
setState(() {});
});
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: OnlyLayoutWidget( child: OnlyLayoutWidget(
onPerformLayout: (Size size) {
if (!mounted) return;
_height = size.height;
widget.onPerformLayout?.call(_height!);
setState(() {});
},
child: UnconstrainedBox( child: UnconstrainedBox(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: SizedBox( child: SizedBox(
key: _key,
width: _width, width: _width,
child: widget.flexibleSpace, child: widget.flexibleSpace,
), ),

View File

@@ -1,17 +1,42 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart' show RenderProxyBox; import 'package:flutter/rendering.dart' show RenderProxyBox;
import 'package:flutter/scheduler.dart';
typedef LayoutCallback = void Function(Size size);
class OnlyLayoutWidget extends SingleChildRenderObjectWidget { class OnlyLayoutWidget extends SingleChildRenderObjectWidget {
const OnlyLayoutWidget({ const OnlyLayoutWidget({
super.key, super.key,
super.child, super.child,
required this.onPerformLayout,
}); });
final LayoutCallback onPerformLayout;
@override @override
RenderObject createRenderObject(BuildContext context) => Layout(); RenderObject createRenderObject(BuildContext context) =>
Layout(onPerformLayout: onPerformLayout);
@override
void updateRenderObject(BuildContext context, Layout renderObject) {
super.updateRenderObject(context, renderObject);
renderObject.onPerformLayout = onPerformLayout;
}
} }
class Layout extends RenderProxyBox { class Layout extends RenderProxyBox {
Layout({required this.onPerformLayout});
LayoutCallback onPerformLayout;
@override
void performLayout() {
super.performLayout();
SchedulerBinding.instance.addPostFrameCallback((_) {
onPerformLayout(size);
});
}
@override @override
void paint(PaintingContext context, Offset offset) {} void paint(PaintingContext context, Offset offset) {}
} }

View File

@@ -23,22 +23,17 @@ class SelfSizedHorizontalList extends StatefulWidget {
} }
class _SelfSizedHorizontalListState extends State<SelfSizedHorizontalList> { class _SelfSizedHorizontalListState extends State<SelfSizedHorizontalList> {
final _key = GlobalKey();
double? _height; double? _height;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_height == null) { if (_height == null) {
WidgetsBinding.instance.addPostFrameCallback( return OnlyLayoutWidget(
(_) { onPerformLayout: (Size size) {
_height = (_key.currentContext!.findRenderObject() as RenderBox) if (!mounted) return;
.size _height = size.height;
.height;
setState(() {}); setState(() {});
}, },
);
return OnlyLayoutWidget(
key: _key,
child: Padding( child: Padding(
padding: widget.padding ?? .zero, padding: widget.padding ?? .zero,
child: widget.itemBuilder(context, 0), child: widget.itemBuilder(context, 0),

View File

@@ -159,7 +159,7 @@ class _DynTopicPageState extends State<DynTopicPage> with DynMixin {
Loading() => const SliverAppBar(), Loading() => const SliverAppBar(),
Success(:final response) when response != null => DynamicSliverAppBarMedium( Success(:final response) when response != null => DynamicSliverAppBarMedium(
pinned: true, pinned: true,
afterCalc: (value) => onPerformLayout: (value) =>
_controller.appbarOffset = value - kToolbarHeight - padding.top, _controller.appbarOffset = value - kToolbarHeight - padding.top,
title: IgnorePointer(child: Text(response.topicItem!.name)), title: IgnorePointer(child: Text(response.topicItem!.name)),
flexibleSpace: Container( flexibleSpace: Container(