Farmers in yards world, beautiful application experience, from the programmer for the processing of detail, and self requirements state, agriculture in the yard a member of the young people is busy, every day, every week, can leave some footprints, is the creation of content, there is a persistent, is I don’t know why, if you lost, might as well to Chou Chou code track of farmers.
If you are interested, you can follow the public account Biglead to get the latest learning materials.
- The Series of articles on Flutter from Entry to Mastery is here
- Of course, it is also necessary to have the source code here
- Github a bit slow might as well take a look at the source code cloud it
- A series of learning tutorials is available here
Let’s take a look at the results of this article
Let’s just look at the code
The first is the start function
main() {
runApp(MaterialApp(
// Do not display the debug tag
debugShowCheckedModeBanner: false.// Display the home page
home: DemoSelectImageWidgetPage(),
));
}
Copy the code
Then there’s the home page, and the core code is the SelectPhotoWidget
/// code list
class DemoSelectImageWidgetPage extends StatefulWidget {
@override
_DemoSelectImageWidgetPageState createState(a) =>
_DemoSelectImageWidgetPageState();
}
class _DemoSelectImageWidgetPageState extends State<DemoSelectImageWidgetPage> {
@override
Widget build(BuildContext context) {
//
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(title: Text("Picture Selection component")),
body: Center(
child: Container(
padding: EdgeInsets.all(12),
// Image select component
child: SelectPhotoWidget(
header: Text(
"Please select a photo",
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18),),// Red alert text under the heading
tips: "Please note that a maximum of 5 images are selected.".// Select the image callback
imageSelectAction: (List<String> list) {
print(${list.toString()});
},
// Select maximum image data
maxSelect: 6.// Preset imageimageList: [], ), ), ), ); }}Copy the code
The core functionality is encapsulated in the SelectPhotoWidget component, which you can copy and use directly
///
class SelectPhotoWidget extends StatefulWidget {
/// a callback after each click to select an image
final Function(List<String>) imageSelectAction;
/// customize the title
final Widget header;
/// "//
final String tips;
/// predisplay the images used
final List<String> imageList;
// The maximum number of images can be selected
final int maxSelect;
/// display network images when true
final ImageType imageType;
const SelectPhotoWidget(
{Key key,
this.header,
this.tips,
this.imageList,
this.imageType = ImageType.asset,
this.imageSelectAction,
this.maxSelect = 5})
: super(key: key);
@override
State<StatefulWidget> createState(a) {
return_SelectPhotoWidgetState(); }}Copy the code
class _SelectPhotoWidgetState extends State<SelectPhotoWidget>
with WidgetsBindingObserver {
/// Whether the image is being selected
bool _isSelect = false;
@override
void initState(a) {
super.initState();
if(widget.imageList ! =null) {
// Determine the maximum selected image data
if (widget.imageList.length <= widget.maxSelect) {
_imageList = widget.imageList;
} else {
// Capture the image
_imageList = widget.imageList.sublist(0, widget.maxSelect); }}// Bind the view listener
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.inactive:
// Applications in this state should assume that they may pause at any time.
break;
case AppLifecycleState.resumed:
// Switch from background to foreground, the interface is visible
break;
case AppLifecycleState.paused:
// The interface is not visible, the background
break;
case AppLifecycleState.detached:
// called when APP ends
break; }}@override
void dispose(a) {
// Unbind view listeners
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
// Rounded rectangle clipping
return ClipRRect(
/ / the rounded
borderRadius: BorderRadius.all(Radius.circular(12)),
child: Container(
color: Color(0xffFFFFFF),
// The width is filled
width: double.infinity,
// create a unified inner margin
padding: EdgeInsets.all(10),
// Vertical linear alignment
child: Column(
// Horizontal direction
crossAxisAlignment: CrossAxisAlignment.start,
/ / the parcel
mainAxisSize: MainAxisSize.min,
children: [
/ / title
buildHeaderWidget(),
// Second line tip
buildTipsWidget(),
// Display the image
buildGridView(),
SizedBox(
height: 10,),),),); } buildHeaderWidget() {returnwidget.header ! =null ? widget.header : Container();
}
buildTipsWidget() {
if (widget.tips == null || widget.tips.length == 0) {
return Container();
}
return Container(
padding: EdgeInsets.only(top: 10, bottom: 16),
// Rounded rectangle clipping
child: ClipRRect(
/ / the rounded
borderRadius: BorderRadius.all(Radius.circular(12)),
child: Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 6, bottom: 6),
color: Color(0xffFFF1F1),
child: Text(
"${widget.tips}",
style: TextStyle(
color: Color(0xffBD2F2F),
fontSize: 14(), ((), ((), ((); } List<String> _imageList = []; buildGridView() {return Container(
child: GridView.builder(
padding: EdgeInsets.only(top: 8, bottom: 8),
/ / the parcel
shrinkWrap: true.// Do not slide
physics: NeverScrollableScrollPhysics(),
// The number of images
itemCount: getSelectCount(),
/ / SliverGridDelegateWithFixedCrossAxisCount build a transverse fixed number of widgets
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// Number of elements on the horizontal axis
crossAxisCount: 4.// Spindle spacing
mainAxisSpacing: 1.0.// From axis spacing
crossAxisSpacing: 1.0.// Ratio of sub-component width to height to length
childAspectRatio: 1.0),
itemBuilder: (BuildContext context, int index) {
//Widget Function(BuildContext context, int index)
if (index == _imageList.length) {
if (_isSelect) {
return Center(child: Text("..."));
}
return Container(
margin: EdgeInsets.only(top: 10),
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
onSelectImageFunction();
},
),
color: Color(0xFFF1F1F2)); }// Display the current image
String imageUrl = _imageList[index];
return Container(
// Cascading layout
child: Stack(
children: [
// Shift a little to the left
Positioned.fill(
top: 10,
right: 10,
child: GestureDetector(
onTap: () {
// View the larger image
},
child: Container(
padding: EdgeInsets.all(1),
child: buildImageWidget(imageUrl),
color: Colors.grey[200],
),
),
),
Positioned(
top: 0,
right: 0,
child: GestureDetector(
onTap: () {
onDeleteImageFunction(index);
},
child: ClipOval(
child: Container(
padding: EdgeInsets.all(2),
color: Colors.red,
child: Icon(
Icons.close,
color: Colors.white,
size: 14(() (() (() (() [() (() [() (() [() },),); }Widget buildImageWidget(String image) {
if (widget.imageType == ImageType.net) {
return Image.network(
image,
fit: BoxFit.fitWidth,
);
} else if (widget.imageType == ImageType.asset) {
return Image.asset(
image,
fit: BoxFit.fitWidth,
);
}
return Image.file(
File(image),
fit: BoxFit.fitWidth,
);
}
/// Select the maximum image data limit
getSelectCount() {
if (_imageList.length >= widget.maxSelect) {
return widget.maxSelect;
}
return _imageList.length + 1;
}
// Delete photos
void onDeleteImageFunction(int index) {
_imageList.removeAt(index);
setState(() {});
widget.imageSelectAction(_imageList);
}
void onSelectImageFunction(a) async {
_isSelect = true;
setState(() {});
String localImageUrl = "assets/images/sp03.png";
await Future.delayed(Duration(milliseconds: 1000));
_isSelect = false;
if (localImageUrl.length > 0) { _imageList.add(localImageUrl); setState(() {}); widget.imageSelectAction(_imageList); }}}Copy the code