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