'how to invoke parent component AppBar back in Flutter

I am a newbie in Flutter, today I encount a problem. I want to back to my app's list main page when user using right gustures in screen. Now I could recognize the right gestures. But next I did not know how to triggger parent componnet AppBar's back event. This is my chiild component code:

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/style.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:Cruise/src/component/part_snippet.dart';
import 'package:Cruise/src/common/helpers.dart';
import 'package:Cruise/src/models/Item.dart';
import 'package:Cruise/src/page/profile.dart';
import 'package:Cruise/src/common/Repo.dart';
import 'package:url_launcher/url_launcher.dart';

final partsProvider = FutureProvider.family((ref, int id) async {
  return await Repo.fetchItem(id);
});

class StoryInformation extends HookWidget {
  const StoryInformation({
    Key key,
    @required this.item,
  }) : super(key: key);

  final Item item;

  void launchUrl(url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  @override
  Widget build(BuildContext context) {
    final parts = item.parts.map((i) => useProvider(partsProvider(i))).toList();

    Offset _initialSwipeOffset;
    Offset _finalSwipeOffset;

    void _onHorizontalDragStart(DragStartDetails details) {
      _initialSwipeOffset = details.globalPosition;
    }

    void _onHorizontalDragUpdate(DragUpdateDetails details) {
      _finalSwipeOffset = details.globalPosition;
    }

    void _onHorizontalDragEnd(DragEndDetails details) {
      if (_initialSwipeOffset != null) {
        final offsetDifference = _initialSwipeOffset.dx - _finalSwipeOffset.dx;
        final direction = offsetDifference > 0 ? print('left') : print('right');
        if (offsetDifference > 0) {
           // detect the right gesture, then back to main list page
        }
      }
    }

    return Container(
        color: Theme.of(context).scaffoldBackgroundColor,
        child: GestureDetector(
          onHorizontalDragStart: _onHorizontalDragStart,
          onHorizontalDragUpdate: _onHorizontalDragUpdate,
          onHorizontalDragEnd: _onHorizontalDragEnd,
          child: Padding(),
        ),
    )
 }

}

and this is the parent component:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:Cruise/src/component/comment_list.dart';
import 'package:Cruise/src/component/story_information.dart';
import 'package:Cruise/src/models/Item.dart';
import 'package:Cruise/src/common/Repo.dart';

class StoryPage extends HookWidget {
  const StoryPage({
    Key key,
    @required this.item,
  }) : super(key: key);

  final Item item;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cruise'),
        actions: [
          if (item.parent != null)
            IconButton(
              icon: Icon(Feather.corner_left_up),
              onPressed: () async {
                Item parent = await Repo.fetchItem(item.parent);
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => StoryPage(item: parent)),
                );
              },
            ),
        ],
      ),
      body: CustomScrollView(
        slivers: [
          SliverToBoxAdapter(child: StoryInformation(item: item)),
          CommentList(item: item)
        ],
      ),
    );
  }
}

I want to do is that when recognizing the user's right gestures, then back to the main list page, how to trigger the back action in child's play _onHorizontalDragEnd function?



Solution 1:[1]

You can pass the function of the app bar back button to the StoryInformation class as a callback function and use it from there normally

void appBarBack() async {
            Item parent = await Repo.fetchItem(item.parent);
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => StoryPage(item: parent)),
            );
          },

and when calling StoryInformation

StoryInformation(item: item, backFunction: appBarBack);

and from StoryInformation class

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/style.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:Cruise/src/component/part_snippet.dart';
import 'package:Cruise/src/common/helpers.dart';
import 'package:Cruise/src/models/Item.dart';
import 'package:Cruise/src/page/profile.dart';
import 'package:Cruise/src/common/Repo.dart';
import 'package:url_launcher/url_launcher.dart';

final partsProvider = FutureProvider.family((ref, int id) async {
  return await Repo.fetchItem(id);
});

class StoryInformation extends HookWidget {
  const StoryInformation({
    Key key,
    @required this.item,
    this.backFunction,
  }) : super(key: key);

  final Item item;
  final Function backFunction;

  void launchUrl(url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  @override
  Widget build(BuildContext context) {
    final parts = item.parts.map((i) => useProvider(partsProvider(i))).toList();

    Offset _initialSwipeOffset;
    Offset _finalSwipeOffset;

    void _onHorizontalDragStart(DragStartDetails details) {
      _initialSwipeOffset = details.globalPosition;
    }

    void _onHorizontalDragUpdate(DragUpdateDetails details) {
      _finalSwipeOffset = details.globalPosition;
    }

    void _onHorizontalDragEnd(DragEndDetails details) {
      if (_initialSwipeOffset != null) {
        final offsetDifference = _initialSwipeOffset.dx - _finalSwipeOffset.dx;
        final direction = offsetDifference > 0 ? print('left') : print('right');
        if (offsetDifference > 0) {
           // detect the right gesture, then back to main list page
        }
      }
    }

    return Container(
        color: Theme.of(context).scaffoldBackgroundColor,
        child: GestureDetector(
          onHorizontalDragStart: _onHorizontalDragStart,
          onHorizontalDragUpdate: _onHorizontalDragUpdate,
          onHorizontalDragEnd: (details) => backFunction(),
          child: Padding(),
        ),
    )
 }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 omar hatem