PhotoTool.dart 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
  5. import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  6. class PhotoTool extends StatefulWidget {
  7. @required final int imageCount;//最多几张
  8. @required final int lineCount;//一行几个
  9. final _AddCall addCall;
  10. final _RemoveCall removeCall;
  11. //注:最好把图片和文字这些都拿出来,方便更改,这里就不搞了
  12. const PhotoTool({required this.imageCount,required this.lineCount
  13. ,required this.addCall,required this.removeCall});
  14. @override
  15. _PhotoToolState createState() => _PhotoToolState();
  16. }
  17. class _PhotoToolState extends State<PhotoTool> {
  18. List<AssetEntity> _imageFiles = [];
  19. @override
  20. Widget build(BuildContext context) {
  21. return Container(
  22. width: double.infinity,
  23. color: Colors.white,
  24. child: Padding(
  25. padding: const EdgeInsets.all(12.0),
  26. child: Column(
  27. crossAxisAlignment: CrossAxisAlignment.start,
  28. children: [
  29. RichText(
  30. text: TextSpan(
  31. text: '说明:',
  32. style: Theme.of(context).textTheme.subtitle2,
  33. children: [
  34. TextSpan(
  35. text: '(说明:上传图片,最多${widget.imageCount}张)',
  36. style: Theme.of(context)
  37. .textTheme
  38. .bodyText2
  39. ?.copyWith(color: Colors.grey),
  40. ),
  41. ],
  42. ),
  43. ),
  44. SizedBox(height: 16.0),
  45. StaggeredGridView.countBuilder(
  46. shrinkWrap: true,
  47. crossAxisCount: widget.lineCount,
  48. itemCount: _imageFiles.length == widget.imageCount
  49. ? _imageFiles.length
  50. : _imageFiles.length + 1,
  51. physics: NeverScrollableScrollPhysics(),
  52. itemBuilder: (BuildContext context, int index) {
  53. if (_imageFiles.length < widget.imageCount && index == 0) {
  54. return InkWell(
  55. onTap: () => _onPickImage(),
  56. child: Container(
  57. padding: EdgeInsets.all(5),
  58. child: Container(
  59. decoration: BoxDecoration(
  60. borderRadius: BorderRadius.circular(5.0),
  61. color: Color(0xFFF6F7F8),
  62. ),
  63. child: Center(
  64. child: Icon(
  65. Icons.add,
  66. color: Color(0xFFB4B4B4),
  67. size: 40,
  68. ),
  69. ),
  70. ),
  71. ),
  72. );
  73. } else {
  74. return Stack(
  75. children: [
  76. Container(
  77. padding: EdgeInsets.all(5),
  78. child: InkWell(
  79. child: FutureBuilder<File?>(
  80. future: _imageFiles[_imageFiles.length < widget.imageCount ? index - 1 : index].file,
  81. builder: (context, snapshot) {
  82. return snapshot.connectionState ==
  83. ConnectionState.done
  84. ? Container(
  85. decoration: BoxDecoration(
  86. shape: BoxShape.rectangle,
  87. borderRadius:
  88. BorderRadius.circular(6.0),
  89. image: DecorationImage(
  90. image: FileImage(File(snapshot.data!.path)),
  91. fit: BoxFit.cover,
  92. ),
  93. ),
  94. )
  95. : Container(
  96. decoration: BoxDecoration(
  97. shape: BoxShape.rectangle,
  98. borderRadius:
  99. BorderRadius.circular(6.0),
  100. color: Color(0xFFF6F7F8),
  101. ),
  102. child: Center(
  103. child: CupertinoActivityIndicator(),
  104. ),
  105. );
  106. },
  107. ),
  108. ),
  109. ),
  110. InkWell(
  111. onTap: () => _deleteImage(
  112. _imageFiles.length < widget.imageCount
  113. ? index - 1
  114. : index),
  115. child: Container(
  116. decoration: BoxDecoration(
  117. borderRadius: BorderRadius.circular(99.0),
  118. color: Colors.red,
  119. ),
  120. padding: EdgeInsets.all(2.0),
  121. child: Icon(
  122. Icons.close,
  123. size: 20.0,
  124. color: Colors.white,
  125. ),
  126. ),
  127. ),
  128. ],
  129. );
  130. }
  131. },
  132. staggeredTileBuilder: (int index) =>
  133. new StaggeredTile.count(1, 1),
  134. mainAxisSpacing: 4.0,
  135. crossAxisSpacing: 4.0,
  136. ),
  137. ],
  138. ),
  139. ),
  140. );
  141. }
  142. /// 选择图片
  143. _onPickImage() async {
  144. List<AssetEntity>? assets = await AssetPicker.pickAssets(
  145. context,
  146. pickerConfig:AssetPickerConfig(maxAssets:widget.imageCount - _imageFiles.length,themeColor: Theme.of(context).primaryColor, requestType: RequestType.image,)
  147. );
  148. if (assets == null || assets.length <= 0) return;
  149. setState(() {
  150. _imageFiles.addAll(assets);
  151. if (widget.addCall != null) {
  152. widget.addCall(_imageFiles);
  153. }
  154. });
  155. }
  156. /// 删除图片
  157. _deleteImage(int index) {
  158. if (_imageFiles == null || _imageFiles.length <= index) return;
  159. setState(() {
  160. _imageFiles.removeAt(index);
  161. if (widget.removeCall != null) {
  162. widget.removeCall(index);
  163. }
  164. });
  165. }
  166. }
  167. typedef _AddCall = void Function(List<AssetEntity> mList);
  168. typedef _RemoveCall = void Function(int index);