image_list_item.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import 'package:flutter/gestures.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flyinsono/lab/color/lab_colors.dart';
  4. import 'package:flyinsono/lab/components/lab_center_loading.dart';
  5. import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
  6. /// 图片单项
  7. class ImageListItem extends StatefulWidget {
  8. const ImageListItem({
  9. super.key,
  10. required this.imagePreviewUrl,
  11. required this.imageType,
  12. required this.description,
  13. required this.isSelected,
  14. this.labelBuilder,
  15. this.onSelected,
  16. this.isSelectUrmData = false,
  17. this.isVideo = false,
  18. });
  19. final String imagePreviewUrl;
  20. final ImageType imageType;
  21. final String description;
  22. final bool isSelected;
  23. final bool isSelectUrmData;
  24. final bool isVideo;
  25. final VoidCallback? onSelected;
  26. final Widget? labelBuilder;
  27. @override
  28. State<ImageListItem> createState() => _ImageListItemState();
  29. }
  30. class _ImageListItemState extends State<ImageListItem> {
  31. bool _isHover = false;
  32. @override
  33. Widget build(BuildContext context) {
  34. Color _borderColor = Colors.transparent;
  35. if (_isHover) {
  36. _borderColor = LabColors.base600;
  37. }
  38. if (widget.isSelected) {
  39. if (widget.isSelectUrmData) {
  40. _borderColor = LabColors.base700;
  41. } else {
  42. _borderColor = LabColors.green500;
  43. }
  44. }
  45. return Container(
  46. // margin: EdgeInsets.only(bottom: 5),
  47. child: MouseRegion(
  48. cursor: SystemMouseCursors.click,
  49. onEnter: _handleMouseEnter,
  50. onExit: _handleMouseExit,
  51. child: GestureDetector(
  52. onTap: () {
  53. widget.onSelected?.call();
  54. },
  55. child: Stack(
  56. children: [
  57. Container(
  58. decoration: BoxDecoration(
  59. color: Colors.black,
  60. border: Border.all(
  61. color: _borderColor,
  62. width: 3,
  63. ),
  64. ),
  65. child: SizedBox.expand(
  66. child: Image.network(
  67. widget.imagePreviewUrl,
  68. fit: BoxFit.contain,
  69. loadingBuilder: (context, child, loadingProgress) {
  70. if (loadingProgress == null) return child; // 图片已加载,返回图片
  71. return LabCenterLoading();
  72. },
  73. errorBuilder: (BuildContext context, Object error,
  74. StackTrace? stackTrace) {
  75. return Center(
  76. child: Icon(
  77. Icons.image_outlined,
  78. size: 60,
  79. color: LabColors.base600,
  80. ),
  81. );
  82. },
  83. ),
  84. ),
  85. ),
  86. if (widget.isVideo) ...[
  87. Center(
  88. child: Icon(
  89. Icons.play_circle_outline,
  90. color: Colors.white,
  91. size: 40,
  92. ),
  93. ),
  94. ],
  95. Align(
  96. alignment: Alignment.bottomLeft,
  97. child: Container(
  98. color: Colors.black,
  99. width: double.maxFinite,
  100. margin: EdgeInsets.all(3),
  101. child: Text(
  102. widget.description,
  103. style: TextStyle(
  104. color: LabColors.text400,
  105. fontSize: 12,
  106. ),
  107. ),
  108. ),
  109. ),
  110. if (widget.labelBuilder != null)
  111. Align(
  112. alignment: Alignment.bottomRight,
  113. child: Container(
  114. margin: EdgeInsets.all(3),
  115. padding: EdgeInsets.symmetric(horizontal: 2),
  116. decoration: BoxDecoration(
  117. color: Colors.black,
  118. borderRadius: BorderRadius.circular(3),
  119. border: Border.all(
  120. color: LabColors.base800,
  121. width: 1,
  122. ),
  123. ),
  124. child: widget.labelBuilder!,
  125. ),
  126. ),
  127. ],
  128. ),
  129. ),
  130. ),
  131. );
  132. }
  133. void _handleMouseEnter(PointerEnterEvent event) {
  134. setState(() {
  135. _isHover = true;
  136. });
  137. }
  138. void _handleMouseExit(PointerExitEvent event) {
  139. setState(() {
  140. _isHover = false;
  141. });
  142. }
  143. }
  144. /// 图片列表的原型项(用于定位大小)
  145. class ImageListItemPrototypeItem extends StatelessWidget {
  146. const ImageListItemPrototypeItem({Key? key, required this.aspectRatio})
  147. : super(key: key);
  148. final double aspectRatio;
  149. @override
  150. Widget build(BuildContext context) {
  151. return Container(
  152. // margin: EdgeInsets.only(bottom: 5),
  153. child: AspectRatio(
  154. aspectRatio: aspectRatio,
  155. child: Container(),
  156. ),
  157. );
  158. }
  159. }