How can I obtain this UI result?

I was trying to recreate a design concept from this guy(https://dribbble.com/shots/3812962-iPhone-X-Todo-Concept) but I'm getting some troubles with the ListView alignment or so I think. What I'm trying to do is moving the List to the right without cutting the edges of the cards when I swipe.

I already tried with margin and padding but none of this applied to the container produces the results I want to obtain.Edges are cutted off when I swipe.

I leave here the Container with the ListView inside it.

Screenshoots of the actual app: https://imgur.com/a/hJ96sEv

           Container(
              height: 350.0,
              child: ListView.builder(
                physics: NeverScrollableScrollPhysics(),
                itemCount: 3,
                controller: scrollController,
                scrollDirection: Axis.horizontal,
                itemBuilder: (context, position) {
                  return GestureDetector(
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Card(
                          child: Container(
                            width: 250.0,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              mainAxisAlignment:
                                  MainAxisAlignment.spaceBetween,
                              children: <Widget>[
                                Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: <Widget>[
                                      Icon(
                                        cardsList[position].icon,
                                        color: appColors[position],
                                      ),
                                      Icon(
                                        Icons.more_vert,
                                        color: Colors.grey,
                                      )
                                    ],
                                  ),
                                ),
                                Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: <Widget>[
                                      Padding(
                                        padding: const EdgeInsets.symmetric(
                                            horizontal: 8.0, vertical: 4.0),
                                        child: Text(
                                          "${cardsList[position].tasksRemaining} Tasks",
                                          style:
                                              TextStyle(color: Colors.grey),
                                        ),
                                      ),
                                      Padding(
                                          padding:
                                              const EdgeInsets.symmetric(
                                                  horizontal: 8.0,
                                                  vertical: 4.0),
                                          child: Text(
                                            "${cardsList[position].cardTitle}",
                                            style:
                                                TextStyle(fontSize: 28.0),
                                          )),
                                      Padding(
                                        padding: const EdgeInsets.all(8.0),
                                        child: LinearProgressIndicator(
                                          value: cardsList[position]
                                              .taskCompletion,
                                        ),
                                      )
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ),
                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(10.0)),
                        ),
                      ),
                      onHorizontalDragEnd: (details) {
                        animationController = AnimationController(
                            vsync: this,
                            duration: Duration(milliseconds: 450));
                        curvedAnimation = CurvedAnimation(
                            parent: animationController,
                            curve: Curves.fastOutSlowIn);
                        animationController.addListener(() {
                          setState(() {
                            currentColor =
                                colorTween.evaluate(curvedAnimation);
                          });
                        });

                        if (details.velocity.pixelsPerSecond.dx > 0) {
                          if (cardIndex > 0) {
                            cardIndex--;
                            colorTween = ColorTween(
                                begin: currentColor,
                                end: appColors[cardIndex]);
                          }
                        } else {
                          if (cardIndex < 2) {
                            cardIndex++;
                            colorTween = ColorTween(
                                begin: currentColor,
                                end: appColors[cardIndex]);
                          }
                        }
                        setState(() {
                          scrollController.animateTo((cardIndex) * 256.0,
                              duration: Duration(milliseconds: 450),
                              curve: Curves.fastOutSlowIn);
                        });

                        colorTween.animate(curvedAnimation);

                        animationController.forward();
                      });
                },
              ),
            ),

What I'm trying to do is moving the List to the right without cutting the edges of the cards when I swipe.

1 answer

  • answered 2019-06-25 03:58 Mariano Zorrilla

    To achieve that goal you need a PageView instead of a ListView, that way you can swipe and "snap" the views when you reach and specific position:

    PageView.builder(
      itemCount: tasks.length,
      controller: PageController(initialPage: 0, viewportFraction: 0.8),
      itemBuilder: (context, index) {
         return Padding(
             padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
             child: Container(
                decoration: BoxDecoration(
                   boxShadow: [
                      BoxShadow(
                         color: Color(0x40000000),
                         blurRadius: 10,
                         offset: Offset(0, 12),
                      ),
                   ],
                ),
                child: Card(
                  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10),
                  ),
                  color: Colors.white,
                  child: Padding(
                     padding: const EdgeInsets.all(15),
                     child: Column(
                        children: <Widget>[
                           IntrinsicHeight(
                              child: Row(
                                 crossAxisAlignment: CrossAxisAlignment.start,
                                 children: <Widget>[
                                    Icon(tasks[index].icon),
                                    Expanded(
                                        child: Container(
                                           child: Align(
                                              alignment: Alignment.topRight,
                                              child: Icon(Icons.menu),
                                                ),
                                              ),
                                            ),
                                          ],
                                        ),
                                    ),
                                    Expanded(
                                      child: Container(
                                        width: double.infinity,
                                        child: Column(
                                          crossAxisAlignment: CrossAxisAlignment.start,
                                          mainAxisAlignment: MainAxisAlignment.end,
                                          children: <Widget>[
                                            Text(
                                              "${tasks[index].tasks} tasks",
                                              style: TextStyle(
                                                 color: Color(0xD0000000),
                                                 fontSize: 15,
                                                ),
                                            ),
                                            SizedBox(height: 10),
                                            Text(
                                              "${tasks[index].title}",
                                              style: TextStyle(
                                                color: Color(0xD0000000),
                                                fontSize: 24,
                                              ),
                                            ),
                                            SizedBox(height: 10),
                                            LinearProgressIndicator(
                                              value: tasks[index].percentage,
                                              backgroundColor: Color(0x300000FF),
                                            )
                                          ],
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      );
                    },
                  )
    

    The result of this implementation is something like this:

    PageView

    If you want to change the offset of the cards, you need to modify the value viewportFraction: 0.8 to anything you'd like. 1.0 is the value without offset.

    You can find my full implementation over this Gist Github