flutterimage-gallery

How to create an image gallery on flutter?


I have a Set<String> variable containing a list of image files. In a Card object, in addition to some Text elements, I want to create a gallery of images like this:

enter image description here

The number of images stored in Set<String> is variable. If possible, I want to show in a corner (top-right) the current number image and the total count of images (e.g. 1/5).

The images will be withdrawn from a webserver, and I don't know if it's more efficient to save them in cache or not. I don't want to use storage folder to save the images.

If possible, I would to withdraw all the images in a single http request, to save time.

Here the variable:

Set<String> _photosList = {
'http://myhost.com/image01.jpg',
'http://myhost.com/image02.bmp',
'http://myhost.com/image03.png',
'http://myhost.com/image04.gif',
};

Solution

  • There are certain things which I want you to explore before actually jumping into the code. These are:

    Let us now jump to the code how it works. Follow the comments to know about each work

      // this will keep track of the current page index
      int _pageIndex = 0;
      
      // this is your page controller, which controls the page transition
      final PageController _controller = new PageController();
      
      Set<String> _photosList = {
        'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRqRwpDKN_zJr1C7pPeWcwOa36BtPm4HeLPgA&usqp=CAU',
        'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSgjZ8pw5WLIGMBibVi_g4CMlSE-EOvrLv7Ag&usqp=CAU',
        'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQUuMIENOhc1DmruZ6SwLc7JtrR6ZMBRAb3jQ&usqp=CAU',
        'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcRzasDrBHWV-84vxbmlX7MTuz3QHqtT8jtTuA&usqp=CAU'
      };
    

    Now the UI of the Gallery View.

    Please note: This code supports, swipe functionality in the view. If you want to disable it just add this line inside your Pageview.builder()

    physics:new NeverScrollableScrollPhysics()
    
             Container(
                // use MediaQuery always, it will always adjust the dimensions
                // according to different screens
                height: MediaQuery.of(context).size.height * 0.3,
                width: MediaQuery.of(context).size.width * 0.4,
                // here is your stack
                child: Stack(
                  children: [
                    // PageView.builder is just the part of PageView, read through
                    // Documentation, and you will get to know
                    PageView.builder(
                      controller: _controller,
                      // here you can remove swipe gesture. UNCOMMENT IT 
                      // physics:new NeverScrollableScrollPhysics()
                      onPageChanged: (index){ 
                        // with each change updating the index of our variable too
                        setState(() => _pageIndex = index);
                      },
                      itemCount: _photosList.length,
                      // building the view of our gallery
                      itemBuilder: (BuildContext context, int position){
                        return Align(
                          alignment: Alignment.topLeft,
                          child: Container(
                            decoration: BoxDecoration(
                              image: DecorationImage(
                                fit: BoxFit.cover,
                                image: NetworkImage(_photosList.elementAt(position))
                              )
                            )
                          )
                        );
                      }
                    ),
                    
                    // this will come over the images, the icon buttons
                    Positioned(
                      left: 0.0,
                      right: 0.0,
                      top: MediaQuery.of(context).size.height * 0.12,
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          IconButton(
                            onPressed: (){
                              // checking if we are not on pos = 0
                              // then we can always go back else do nothing
                              if(_pageIndex != 0)
                                _controller.previousPage(duration: Duration(milliseconds: 200), curve: Curves.easeIn);
                            },
                            icon: Icon(Icons.arrow_back_ios, color: Colors.white, size: 28.0)
                          ),
                          IconButton(
                            onPressed: (){
                              // checking if we are not on pos = photosList.length - 1
                              // we calculate 0 to length-1
                              // then we can always go forward else do nothing
                              if(_pageIndex < _photosList.length-1)
                                _controller.nextPage(duration: Duration(milliseconds: 200), curve: Curves.easeIn);
                            },
                            icon: Icon(Icons.arrow_forward_ios, color: Colors.white, size: 28.0)
                          ),
                        ]
                      )
                    )
                  ]
                )
              )
    

    Result

    Result GIF

    Pointer: In order to show them numbering on the corner. just make use of two variables which is already there for you in the code

    Do something like this, and show it using Container in the same view:

    //_pageIndex + 1, because it starts from 0 not 1, and goes up to 4 not 5
    Text('${_pageIndex+1}/$_photosList.length')