grid_item.dart 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:image_puzzle/collection/detail_dialog.dart';
  4. import 'package:image_puzzle/config/device.dart';
  5. import 'package:image_puzzle/models/items.dart';
  6. import 'package:image_puzzle/skin/skin.dart';
  7. import 'package:provider/provider.dart';
  8. class GridItem extends StatefulWidget {
  9. final ListItem item;
  10. final bool lock;
  11. final int index;
  12. const GridItem({super.key, required this.item, required this.lock, required this.index});
  13. @override
  14. State<StatefulWidget> createState() {
  15. return _GridItemState();
  16. }
  17. }
  18. class _GridItemState extends State<GridItem> {
  19. @override
  20. void initState() {
  21. super.initState();
  22. }
  23. @override
  24. void dispose() {
  25. super.dispose();
  26. }
  27. @override
  28. Widget build(BuildContext context) {
  29. return Stack(
  30. children: [
  31. Hero(
  32. tag: widget.item.id,
  33. child: Material(
  34. color: Colors.transparent,
  35. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
  36. elevation: 1,
  37. clipBehavior: Clip.hardEdge,
  38. child: Listener(
  39. child: GestureDetector(
  40. onTapUp: (details) {
  41. if (widget.lock) {
  42. ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这个合集还未解锁!')));
  43. } else {
  44. // 跳转到大图页面 (以全屏 Dialog 形式)
  45. Navigator.push(
  46. context,
  47. PageRouteBuilder(
  48. opaque: false, // 允许背景半透明
  49. pageBuilder: (context, animation, secondaryAnimation) => FadeTransition(
  50. opacity: animation,
  51. child: ImageDetailDialog(item: widget.item),
  52. ),
  53. ),
  54. );
  55. }
  56. },
  57. child: LayoutBuilder(
  58. builder: (context, constraints) {
  59. if (widget.lock) {
  60. return _buildLockedPlaceholder(constraints.biggest);
  61. } else {
  62. return _buildImage(constraints.biggest);
  63. }
  64. },
  65. ),
  66. ),
  67. ),
  68. ),
  69. ),
  70. Positioned(
  71. bottom: 0,
  72. right: 0,
  73. child: DecoratedBox(
  74. decoration: BoxDecoration(
  75. color: SkinHelper.color5,
  76. borderRadius: const BorderRadius.only(bottomRight: Radius.circular(4), topLeft: Radius.circular(10)),
  77. ),
  78. child: Padding(
  79. padding: const EdgeInsets.all(6),
  80. child: Text(
  81. badgeStr,
  82. style: TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
  83. ),
  84. ),
  85. ),
  86. ),
  87. ],
  88. );
  89. }
  90. String get badgeStr => '${widget.index * 25 + 1}-${(widget.index + 1) * 25}';
  91. Widget _buildImage(Size size) {
  92. final device = context.read<Device>();
  93. int cacheWidth = (size.width * device.devicePixelRatio).toInt();
  94. int cacheHeight = (size.height * device.devicePixelRatio).toInt();
  95. if (widget.item is AssetItem) {
  96. AssetItem assetItem = widget.item as AssetItem;
  97. return Image.asset(assetItem.thumb, cacheWidth: cacheWidth, cacheHeight: cacheHeight);
  98. } else {
  99. return network(widget.item, size.width, size.height, cacheWidth, cacheHeight);
  100. }
  101. }
  102. Widget network(ListItem item, double width, double height, int cacheWidth, int cacheHeight) {
  103. return CachedNetworkImage(
  104. imageUrl: item.thumb,
  105. fit: BoxFit.fill,
  106. width: width,
  107. height: height,
  108. memCacheWidth: cacheWidth,
  109. memCacheHeight: cacheHeight,
  110. // placeholder: (context, url) => JigsawPiece.placeHolder(scale: 0.6),
  111. );
  112. }
  113. Widget _buildLockedPlaceholder(Size size) {
  114. return Container(
  115. width: size.width,
  116. height: size.height,
  117. decoration: BoxDecoration(color: SkinHelper.slotBorderColor, borderRadius: BorderRadius.circular(8)),
  118. child: const Center(
  119. child: Icon(
  120. Icons.lock,
  121. size: 60, // 锁图标大小
  122. color: Colors.white, // 锁图标颜色
  123. ),
  124. ),
  125. );
  126. }
  127. }