PhotoTool.dart 6.7 KB

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