Search code examples
androidflutterflutter-layouthorizontalscrollviewflutter-pageview

Emulating horizontal list of images as seen in google play app


I would like to create a widget that behaves same way as the horizontal scrolling lists (for example for recommended apps) in google play app.

An example of what I mean:

enter image description here

I have tried to use the Page Viewer widget but it does not quite do same thing. Some noticiable facts:

1) 3 perfectly squared images are fully seen and another one is partially shown. The second one (the greenish one) is right in the center.

2) The left most image (the blue one) is perfectly aligned with the Caption "Recommended for you"

3) All 4 squared images have rounded corners.

4) It supports item snapping

This is the best I have been able to mimic this behaviour with the PageView widget:

enter image description here

  • Red is the background color of the container containing the pageview.
  • Green is the color for even items and Blue for odd items
  • Inside every item an image of 100x100 is added.

This is the code:

  return Container(
      width: double.infinity,
      color: Colors.red,
      height: 100,
      child:
          PageView(
              pageSnapping: true,
              controller:
                  PageController(initialPage: 1, viewportFraction: 0.315),
              children: List<Widget>.generate(10, (index) {
                return Container(
                  color: index%2 ==0 ? Colors.green : Colors.blue,
                  child:Image.network("http://via.placeholder.com/100x100",
                      fit: BoxFit.fitHeight)
                );
              })));

Width my code there are 2 things that won't work:

1) I can't make appear a partially seen item from the right side keeping the 3 fully visible items and the second perfectly centered as in the original image form google play, just by using viewportFraction.

2) I can't apply rounded corners to the item images because as you see the container is not squared but the image is. So when I apply ClipRRect it is not applied correctly. I have tried to add another container forcing its size to 100x100 and apply ClipRRect on the image inside this container but when it is inside a PageView it seems the width/height given have no effect. They seem controlled internally by PageView.

So, Could anybody help on this problems to get something with the same behaviour as the google play horizontal scrollable list?

Cheers!


Solution

  • class SO extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        double edge = 120.0;
        double padding = edge / 10.0;
        return Scaffold(
          appBar: AppBar(),
          body: Container(
            color: Colors.red,
            padding: const EdgeInsets.symmetric(vertical: 8),
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Row(
                children: [
                  for (int i = 0; i < 10; i++)
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                          padding: EdgeInsets.all(padding),
                          child: ClipRRect(
                            borderRadius: BorderRadius.all(Radius.circular(edge * .2)),
                            child: Container(
                              width: edge,
                              height: edge,
                              color: Colors.blue,
                              child: Image.network("http://via.placeholder.com/${edge.round()}x${edge.round()}", fit: BoxFit.fitHeight),
                            ),
                          ),
                        ),
                        Container(
                          width: edge + padding,
                          padding: EdgeInsets.only(left: padding),
                          child: Text(
                            'foo app bar baz app apk',
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.only(left: padding),
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: <Widget>[
                              Text('4.2'),
                              Icon(
                                Icons.star,
                                size: 16,
                              )
                            ],
                          ),
                        ),
                      ],
                    )
                ],
              ),
            ),
          ),
        );
      }
    }
    

    which gives

    screenshot