简体   繁体   中英

How to create pageview overlapping effect?

I need to create an overlapping pageview collection, but because of draw/layout order of items the second page always shows up in front of first page. There a way to create a collection list that the first items overlapping the others?

PAGE BUILDER ->

 Widget buildList(PreloadPageController pageController, List data,
      double currentPosition) {
    return AspectRatio(
      aspectRatio: 12.0 / 15.0,
      child: PreloadPageView.builder(
        itemCount: data.length,
        controller: pageController,
        preloadPagesCount: 2,
        itemBuilder: (context, index) {
          return CardWidget(
              page: index,
              currentPage: currentPosition,
          );
        },
      ),
    );
  }


CARD WIDGET ->
Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, contraints) {
      final double padding = 20.0;

      var delta = currentPage - page;
      var start = padding * delta.abs() * 10;

      var top = padding + padding * max(-delta, 0.0);
      var bottom = padding + padding * max(-delta, 0.0);

      //print(start);
      return Transform.translate(
        offset: Offset(-start, 0),
        child: Container(
          padding: EdgeInsets.only(top: top, bottom: bottom),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(16.0),
            child: Container(
              color: _randomColor(page),
            ),
          ),
        ),
      );
    });
  }

I was expecting create a collection effect so the second page would come from behind the first one, but actually second pages always appears overlapping the first. I could use reverse in PageView.builder, but this collection needs to be a infinity list that loads more data when it reaches the end and with reverse the code will be alot trickier.

I'm achieving this:

错误的结果

But what I want is the blue card behind the red one.

So right now, to create your overlapping effect, you are offsetting the next -Page so that it overlaps the cur -Page, and as you mentioned, you discover that the next -Page visually over-laps instead of the desired under-lap .

Then, in additional to your offset, have you tried cropping off the overlapping portion of next -Page? This can simulate the effect of under-lapping .

Now, I tried replicating your sample, but I'm uncertain about your PreloadPageController (and maybe other details), so my sample might look glitchy. Additionally, I'm not wholly familiar with cropping widgets. But I bumped into this possible solution, all I did was wrap it with another ClipRect :

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      final double padding = 20.0;

      var delta = widget.currentPage - widget.myPage;
      var start = padding * delta.abs() * 10;

      var top = padding + padding * max(-delta, 0.0);
      var bottom = padding + padding * max(-delta, 0.0);

      return ClipRect(
        child: Transform.translate(
          offset: Offset(-start, 0),
          child: Container(
            padding: EdgeInsets.only(top: top, bottom: bottom),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(16.0),
              child: Container(
                color: redOrBlue(widget.myPage),
              ),
            ),
          ),
        ),
      );
    });
  }

This additional ClipRect basically clips off your offset portion. Feel free to explore and modify as needed!

在此处输入图像描述

There's an Overlay widget but it may cause more headaches, especially at scale. You can wrap your pages in a ClipRect , but only the widgets at the end of the list will need it. So in the builder function, set up a bool:

clipNeeded = (controller.page + 0.5) <= index;

Then in the new ClipRect widget:

clipper: clipNeeded ? CustomRect() : null,

Then you'll need to create that CustomRect class, extending CustomClipper<Rect>

The exact math required depends on the implementation, but in this left to right scroll example, it'll be something like

class CustomRect extends CustomClipper<Rect>{

  @override
  Rect getClip(Size size) {
    double leftLine = /* some calculation */;
    return Rect.fromLTRB(leftLine, 0.0, size.width, size.height);
  }
  @override
  bool shouldReclip(CustomRect oldClipper) {
    return true;
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM