1

I have a pageview view and it works with sliding. But how do I integrate this back button as leading: Icon(backbutton), when navigating between forms in the pageview? Thanks

screen1.dart

import 'package:app/src/features/examples/components/body.dart';

class OnboardingExampleFlowPage extends StatelessWidget {
  static String routeName = "/onboarding_example_flow";

  const OnboardingExampleFlowPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        elevation: 1,
        backgroundColor: AppColors.monochromeWhite,
        title: Text(context.l10n.buttonBack),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {},
        ),
      ),
      body: const Body(),
    );
  }
}

Body has pageview:

body.dart


class _BodyState extends State<Body> {
  int currentPage = 0;
  final PageController controller = PageController();
  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> formPages = <Widget>[
      ExampleContent01(controller: controller),
      ExampleContent02(controller: controller),
      ExampleContent03(controller: controller),
      ExampleContent04(controller: controller),
    ];
    return SafeArea(
      child: SizedBox(
        child: Column(
          children: [
            const SizedBox(height: 6),
            AppStepper(
              currentPage: currentPage,
              length: formPages.length,
              noSkip: true,
            ),
            Expanded(
              child: Padding(
                padding: EdgeInsets.symmetric(
                  horizontal: getProportionateScreenWidth(20),
                ),
                child: PageView(
                  controller: controller,
                  onPageChanged: (value) => setState(() => currentPage = value),
                  children: formPages,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

These forms: There are contents in ExampleScreens, but I did not add their code because there are AppBar and Pageview in the code I added.

here is view: enter image description here want to be able to go back inside pageview.

Thanks a lot!

2 Answers2

0

Just move the controller up, to the parent widget, so it's possible to navigate the pages with it.

Check out the live demo on DartPad.

enter image description here

The code is going to be like the following:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const OnboardingExampleFlowPage(),
      scrollBehavior: MyCustomScrollBehavior(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class OnboardingExampleFlowPage extends StatefulWidget {
  static String routeName = "/onboarding_example_flow";

  const OnboardingExampleFlowPage({Key? key}) : super(key: key);

  @override
  State<OnboardingExampleFlowPage> createState() =>
      _OnboardingExampleFlowPageState();
}

class _OnboardingExampleFlowPageState extends State<OnboardingExampleFlowPage> {
  final PageController controller = PageController();

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        elevation: 1,
        title: const Text('Back'),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            controller.previousPage(
              duration: const Duration(milliseconds: 250),
              curve: Curves.easeOut,
            );
          },
        ),
      ),
      body: Body(controller: controller),
    );
  }
}

class Body extends StatefulWidget {
  const Body({super.key, required this.controller});

  final PageController controller;

  @override
  State<Body> createState() => _BodyState();
}

class _BodyState extends State<Body> {
  int currentPage = 0;

  @override
  Widget build(BuildContext context) {
    const List<Widget> formPages = [
      Center(child: Text('Page 1')),
      Center(child: Text('Page 2')),
      Center(child: Text('Page 3')),
      Center(child: Text('Page 4')),
    ];
    return SafeArea(
      child: SizedBox(
        child: Column(
          children: [
            const SizedBox(height: 6),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 20),
                child: PageView(
                  controller: widget.controller,
                  onPageChanged: (value) => setState(() => currentPage = value),
                  children: formPages,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// Enables scrolling with mouse dragging
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}
lepsch
  • 8,927
  • 5
  • 24
  • 44
  • Hello thanks for answer I got an error like this : PageController.page cannot be accessed before a PageView is built with it. Failed assertion: line 173 pos 7: 'positions.isNotEmpty' I have checked internet and added the body this code but this is not working : @override void initState() { super.initState(); currentPage = 0; controller.addListener(() { setState(() { currentPage = controller.page!.toInt(); }); }); } thanks! –  Sep 14 '22 at 08:22
  • It looks like the controller is being accessed before the `PageView` even exists. The error should be somewhere else. Where you're trying to access the `controller`? Please update the code with the real use case – lepsch Sep 14 '22 at 08:33
  • thank you so much i fixed it, clicked useful answer for you –  Sep 14 '22 at 11:32
0

Dont have body widget in separate file

Put it in the _OnboardingExampleFlowPageState instead.

And it is the _OnboardingExampleFlowPageState that should have controller and currentIndex variables.

So on leading button click you'll do something like this:

  onPressed: () {
                        if (currentPage > 0) {
                          controller.previousPage(
                            duration: const Duration(milliseconds: 200),
                            curve: Curves.easeOut,
                          );
                          setState(() {
                            currentPage--;
                          });
                        }
                      },
70B1 H4CK3R
  • 322
  • 1
  • 10