Zeke Willams
Zeke Willams

Reputation: 180

Pass scroll gestures through container in Flutter

I have a smaller element on a screen that I'm using a PageView to build, since I need that snap-to effect for each item in the list. But this means the edges will be flush, with no visual indication that the PageView element is scrollable. I tried putting the PageView in a stack with a container on top (like an overlay) that had a linear gradient to "shadow" the sides to make the element look rounded, but this blocks the scrolling gesture from reaching the PageView.

My question is this: is there a widget that I'm not finding that allows scroll gestures to pass through it, while visually appearing on top of other elements? I know I can draw smaller-than-the-PageView elements on top of it, but I'm just wondering if someone else has done something like this successfully.

EDIT: here is a simplified version of the working code. I can't swipe to the next page view.

    return Scaffold(
      body: Center(
        child: Container(
          padding: const EdgeInsets.all(35.0),
          child: Stack(
            children: [
              PageView(
                children: [
                  Container(color: Colors.blue[200]),
                  Container(color: Colors.red[200]),
                  Container(color: Colors.deepPurple[200])
                ]
              ),
              Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.centerLeft,
                    end: Alignment.centerRight,
                    colors: [ Color.fromARGB(50, 0, 0, 0), Color.fromARGB(0, 0, 0, 0), Color.fromARGB(0, 0, 0, 0), Color.fromARGB(50, 0, 0, 0) ],
                    stops: [ 0.05, 0.25, 0.75, 0.95 ]
                  )
                )
              )
            ]
          )
        ),
      ),
    );

Upvotes: 0

Views: 1751

Answers (2)

Zeke Willams
Zeke Willams

Reputation: 180

It seems Containers block scroll input, so I decided to go another route with something like Pedro R.'s suggestion. I created a page indicator at the bottom of the PageView that indicates which page the user is currently on and how many pages total there are. Here is the CodePen I made to showcase the effect.

EDIT AND BEST ANSWER: So I found exactly what I was looking for a little while later. It's a class called IgnorePointer, and it works like the below code example. This will allow you to swipe on the PageView. Try removing the IgnorePointer and your swiping becomes blocked.

Stack(
  children: <Widget>[
    PageView(
      children: <Widget>[
        Container(color: Colors.deepPurple[300]),
        Container(color: Colors.blue[300]
      ]
    ),
    IgnorePointer(
      child: Container(
        color: Color.fromARGB(100, 100, 100, 100)
      )
    )
  ]
)

And the code to go with the code pen

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: MyWidget(),
    ),
  );
}

class MyWidget extends StatelessWidget {
  MyWidget({Key key}): super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          padding: const EdgeInsets.all(35.0),
          child: PageIndicator()
        ),
      ),
    );
  }
}

class PageIndicator extends StatefulWidget {
  PageIndicator({Key key}): super(key: key);
  
  @override
  _PageIndicatorState createState() => _PageIndicatorState();
}

class _PageIndicatorState extends State<PageIndicator> {
  int _pageNum;
  PageController _controller;
  
  @override
  void initState() {
    super.initState();
    _pageNum = 0;
    _controller = PageController(initialPage: 0);
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        PageView(
          controller: _controller,
          onPageChanged: (page) {
            setState(() {
              _pageNum = page;
            });
          },
          children: [
            Container(color: Colors.blue[200]),
            Container(color: Colors.red[200]),
            Container(color: Colors.deepPurple[200])
          ]
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: Container(
            width: 200,
            height: 80,
            child: Center(
              child: Text("${_pageNum + 1} / 3", style: TextStyle(fontSize: 25.0))
            )
          )
        )
      ]
    );
  }// end build
}

Upvotes: 4

Pedro R.
Pedro R.

Reputation: 673

You could use a PageIndicatorWidget. Something like this: var pageController = PageController();

          Stack(
            children: [
              PageView(
                controller: pageController,
                children: [
                  Container(color: Colors.blue[200]),
                  Container(color: Colors.red[200]),
                  Container(color: Colors.deepPurple[200])
                ]
              ),
          PageIndicator(
              layout: PageIndicatorLayout.WARM,
              size: 10.0,
              controller: pageController,
              space: 5.0,
              count: 3,
              color: Colors.green,
              activeColor: Colors.gray,
            ),
              
            ]
          )

Upvotes: 0

Related Questions