empty_widget.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import 'package:flutter/rendering.dart';
  2. import 'package:flutter/widgets.dart';
  3. // 空视图
  4. class EmptyWidget extends StatefulWidget {
  5. // 子组件
  6. final Widget child;
  7. EmptyWidget({Key? key, this.child}) : super(key: key);
  8. @override
  9. EmptyWidgetState createState() {
  10. return EmptyWidgetState();
  11. }
  12. }
  13. class EmptyWidgetState extends State<EmptyWidget> {
  14. // 列表配置通知器
  15. ValueNotifier<SliverConfig> _notifier;
  16. @override
  17. void initState() {
  18. _notifier = ValueNotifier(null);
  19. super.initState();
  20. }
  21. @override
  22. void dispose() {
  23. _notifier.dispose();
  24. super.dispose();
  25. }
  26. @override
  27. Widget build(BuildContext context) {
  28. return _SliverEmpty(
  29. child: widget.child,
  30. notifier: _notifier,
  31. );
  32. }
  33. }
  34. // 空视图Sliver组件
  35. class _SliverEmpty extends SingleChildRenderObjectWidget {
  36. final ValueNotifier<SliverConfig> notifier;
  37. const _SliverEmpty({
  38. Key? key,
  39. required Widget child,
  40. required this.notifier,
  41. }) : super(key: key, child: child);
  42. @override
  43. RenderObject createRenderObject(BuildContext context) {
  44. return _RenderSliverEmpty(
  45. notifier: this.notifier,
  46. );
  47. }
  48. }
  49. class _RenderSliverEmpty extends RenderSliverSingleBoxAdapter {
  50. final ValueNotifier<SliverConfig> notifier;
  51. _RenderSliverEmpty({
  52. RenderBox child,
  53. required this.notifier,
  54. }) {
  55. this.child = child;
  56. }
  57. @override
  58. void performLayout() {
  59. // 判断Sliver配置是否改变
  60. SliverConfig sliverConfig = SliverConfig(
  61. remainingPaintExtent: constraints.remainingPaintExtent,
  62. crossAxisExtent: constraints.crossAxisExtent,
  63. axis: constraints.axis,
  64. );
  65. if (notifier.value != sliverConfig) {
  66. notifier.value = sliverConfig;
  67. child.layout(
  68. constraints.asBoxConstraints(
  69. maxExtent: constraints.remainingPaintExtent,
  70. ),
  71. parentUsesSize: true,
  72. );
  73. geometry = SliverGeometry(
  74. paintExtent: constraints.remainingPaintExtent,
  75. maxPaintExtent: constraints.remainingPaintExtent,
  76. layoutExtent: constraints.remainingPaintExtent,
  77. );
  78. } else {
  79. double remainingPaintExtent = notifier.value.remainingPaintExtent;
  80. double childExtent = remainingPaintExtent;
  81. final double paintedChildSize =
  82. calculatePaintOffset(constraints, from: 0.0, to: childExtent);
  83. final double cacheExtent =
  84. calculateCacheOffset(constraints, from: 0.0, to: childExtent);
  85. child.layout(
  86. constraints.asBoxConstraints(
  87. maxExtent: remainingPaintExtent,
  88. ),
  89. parentUsesSize: true,
  90. );
  91. geometry = SliverGeometry(
  92. scrollExtent: childExtent,
  93. paintExtent: paintedChildSize,
  94. cacheExtent: cacheExtent,
  95. maxPaintExtent: remainingPaintExtent,
  96. layoutExtent: paintedChildSize,
  97. hitTestExtent: paintedChildSize,
  98. hasVisualOverflow: childExtent > constraints.remainingPaintExtent ||
  99. constraints.scrollOffset > 0.0,
  100. );
  101. setChildParentData(child, constraints, geometry);
  102. }
  103. }
  104. }
  105. // 列表属性
  106. class SliverConfig {
  107. final double remainingPaintExtent;
  108. final double crossAxisExtent;
  109. final Axis axis;
  110. SliverConfig({this.remainingPaintExtent, this.crossAxisExtent, this.axis});
  111. @override
  112. bool operator ==(Object other) =>
  113. identical(this, other) ||
  114. other is SliverConfig &&
  115. runtimeType == other.runtimeType &&
  116. crossAxisExtent == other.crossAxisExtent &&
  117. axis == other.axis;
  118. @override
  119. int get hashCode => crossAxisExtent.hashCode ^ axis.hashCode;
  120. }