Flutter Quick Actions change selected Bottom Navigation Bar item

2.3k views Asked by At

I'm trying to implement home screen quick actions / app shortcuts in my Flutter app. What I'm trying to achieve is when the user launches my app via a quick action, the app changes the selected tab inside the bottom navigation bar. Any help is appreciated.

main.dart:

runApp(
    MaterialApp(
      theme: Themes.appLightTheme,
      darkTheme: Themes.appDarkTheme,
      home: QuickActionsController(
        child: HomeFrame(currentIndex: 0),
      ),

My QuickActionsController class:

import 'package:binfinder/screens/HomeFrame.dart';
import 'package:flutter/material.dart';
import 'package:quick_actions/quick_actions.dart';

class QuickActionsController extends StatefulWidget {
  final HomeFrame child;

  QuickActionsController({Key key, this.child}) : super(key: key);

  @override
  _QuickActionsControllerState createState() => _QuickActionsControllerState();
}

class _QuickActionsControllerState extends State<QuickActionsController> {
  final QuickActions quickActions = QuickActions();
  int _currentIndex = 0;

  @override
  void initState() {
    super.initState();
    _handleQuickActions();
    _setupQuickActions();
  }

  void _setupQuickActions() {
    quickActions.setShortcutItems(<ShortcutItem>[
      ShortcutItem(
        type: 'action_map',
        localizedTitle: 'Map',
      ),
    ]);
  }

  void _handleQuickActions() {
    quickActions.initialize((shortcutType) {
      if (shortcutType == 'action_map') {
        setState(() {
          _currentIndex = 1;
        });
      } else {
        setState(() {
          _currentIndex = 0;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    widget.child.currentIndex = _currentIndex;
    return widget.child;
  }
}

1

There are 1 answers

1
chunhunghan On BEST ANSWER

In the demo below, direct click app will enter First Page and In Quick Action choose Main view will enter Second Page

_handleQuickActions need to use

Navigator.pushReplacement(
        context,
        MaterialPageRoute(
            builder: (context) => BottomNavigationBarController(
                  initialIndex: 1,
                )));

and use initial index to control page index

class BottomNavigationBarController extends StatefulWidget {
  final int initialIndex;

  BottomNavigationBarController({
    this.initialIndex,
    Key key,
  }) : super(key: key);

  @override
  _BottomNavigationBarControllerState createState() =>
      _BottomNavigationBarControllerState();
}

full code

import 'package:flutter/material.dart';
import 'package:quick_actions/quick_actions.dart';
import 'dart:io';

class QuickActionsManager extends StatefulWidget {
  final Widget child;
  QuickActionsManager({Key key, this.child}) : super(key: key);

  _QuickActionsManagerState createState() => _QuickActionsManagerState();
}

class _QuickActionsManagerState extends State<QuickActionsManager> {
  final QuickActions quickActions = QuickActions();

  @override
  void initState() {
    super.initState();
    _setupQuickActions();
    _handleQuickActions();
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }

  void _setupQuickActions() {
    quickActions.setShortcutItems(<ShortcutItem>[
      ShortcutItem(
          type: 'action_main',
          localizedTitle: 'Main view',
          icon: Platform.isAndroid ? 'quick_box' : 'QuickBox'),
      ShortcutItem(
          type: 'action_help',
          localizedTitle: 'Help',
          icon: Platform.isAndroid ? 'quick_heart' : 'QuickHeart')
    ]);
  }

  void _handleQuickActions() {
    quickActions.initialize((shortcutType) {
      if (shortcutType == 'action_main') {
        Navigator.pushReplacement(
            context,
            MaterialPageRoute(
                builder: (context) => BottomNavigationBarController(
                      initialIndex: 1,
                    )));
      } else if (shortcutType == 'action_help') {
        print('Show the help dialog!');
      }
    });
  }
}

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'QuickActions Demo',
        home: QuickActionsManager(child: BottomNavigationBarController(initialIndex: 0,)));
  }
}

class Home extends StatelessWidget {
  const Home({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: Center(child: Text('Home')));
  }
}

class Login extends StatelessWidget {
  const Login({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: Center(child: Text('Login')));
  }
}

class BottomNavigationBarController extends StatefulWidget {
  final int initialIndex;

  BottomNavigationBarController({
    this.initialIndex,
    Key key,
  }) : super(key: key);

  @override
  _BottomNavigationBarControllerState createState() =>
      _BottomNavigationBarControllerState();
}

class _BottomNavigationBarControllerState
    extends State<BottomNavigationBarController> {
  final List<Widget> pages = [
    FirstPage(
      key: PageStorageKey('Page1'),
    ),
    SecondPage(
      key: PageStorageKey('Page2'),
    ),
  ];

  final PageStorageBucket bucket = PageStorageBucket();

  int _selectedIndex = 0;

  Widget _bottomNavigationBar(int selectedIndex) => BottomNavigationBar(
        onTap: (int index) => setState(() => _selectedIndex = index),
        currentIndex: selectedIndex,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
              icon: Icon(Icons.add), title: Text('First Page')),
          BottomNavigationBarItem(
              icon: Icon(Icons.list), title: Text('Second Page')),
        ],
      );

  @override
  void initState() {
    _selectedIndex = widget.initialIndex;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: _bottomNavigationBar(_selectedIndex),
      body: PageStorage(
        child: pages[_selectedIndex],
        bucket: bucket,
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("First Screen"),
      ),
      body: ListView.builder(itemBuilder: (context, index) {
        return ListTile(
          title: Text('Lorem Ipsum'),
          subtitle: Text('$index'),
        );
      }),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: ListView.builder(itemBuilder: (context, index) {
        return ListTile(
          title: Text('Lorem Ipsum'),
          subtitle: Text('$index'),
        );
      }),
    );
  }
}

demo, emulator is a little slow when enter Second Page

enter image description here