Jyinx
Jyinx

Reputation: 11

Flutter: From a tab pass some string to a specific tab and show that specific tab in tabbar

I am working on a flutter project where I have 3 tabs in tabbar. In tab 1 and tab 2, there are lists showing some data using ListView. When clicked on a list item, I want to pass some string to tab 3 and show tab 3.

Below is my home page code:

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  TabController controller;
  @override
  void initState() {
    super.initState();
    controller = new TabController(vsync: this, length: 3);
  }
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {},
      child: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            title: Text("InstaPost"),
            backgroundColor: Colors.black45,
            bottom: TabBar(
              tabs: [
                Tab(
                  text: "Tab 1",
                ),
                Tab(text: "Tab 2"),
                Tab(text: "Tab 3"),
                // Tab(text: "My Posts")
              ],
            ),
          ),
          body: TabBarView(
            children: <Widget>[
              Tab1(),
              Tab2(),
              Tab3(),
            ],
          ),
        ),
      ),
    );
  }
}

So, when the app is launched the first screen will be tab 1 which shows a list of names. The code is below

class _HashtagPageState extends State<HashtagPage> {

  Future<dynamic> getLists() async {
     // get list
  }
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {},
      child: FutureBuilder(
        future: getLists(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Container(
              child: SpinKitDoubleBounce(color: Colors.green, size: 100),
            );
          } else {
            // log(snapshot.data.toString());
            var data = snapshot.data;
            return Container(
              child: Column(
                children: <Widget>[
                  Expanded(
                    child: ListView.separated(
                      itemCount: data.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(data[index]),
                          onTap: () {
                              
                              // code to pass a string value to tab 3 and navigate to tab 3
                             
                          },
                        );
                      },
                    ),
                  )
                ],
              ),
            );
          }
        },
      ),
    );
  }
}

When clicked on a list item in tab 1, how should I pass a string to tab 3 and navigate to tab 3 at the same time ?

Upvotes: 1

Views: 2005

Answers (2)

Oded Ben Dov
Oded Ben Dov

Reputation: 10397

This is what worked for me.

Set up the TabController as such:

child: Scaffold(
  appBar: AppBar(
      bottom: TabBar(
        controller: _tabController, 
        tabs: ...,
      ),
    ),
  body: TabBarView(
    controller: _tabController,
    children: ...

And then to switch between tabs

  // Set desired state to cause changes in target tab
  setState(() {
    appState.targetValue = newValue;
  });

  // Important for the timing/sequence of the actions
  WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
    _tabController.animateTo(newTabIndex);
  });

Upvotes: 0

chunhunghan
chunhunghan

Reputation: 54377

You can copy paste run full code below
You can use https://pub.dev/packages/provider
Step 1: You can save parameter in YourModel
Step 2: In Tab3 , you can access with (context.watch<YourModel>().parameter)
code snippet

class YourModel extends ChangeNotifier {
  String _parameter = "";
  String get parameter => _parameter;

  void passParameter(String parameter) {
    _parameter = parameter;
    print(_parameter);
    notifyListeners();
  }
}
...
ChangeNotifierProvider(
  create: (context) => YourModel(),
  child: MyApp(),
),  
...
class Tab3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text("${(context.watch<YourModel>().parameter)}"));
  }
}
...
return ListTile(
              title: Text(data[index]),
              onTap: () {
                Provider.of<YourModel>(context, listen: false)
                    .passParameter(data[index]);
                widget.controller.animateTo(2);
              },
            );

working demo

enter image description here

full code

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'dart:collection';
import 'package:provider/provider.dart';

class YourModel extends ChangeNotifier {
  String _parameter = "";
  String get parameter => _parameter;

  void passParameter(String parameter) {
    _parameter = parameter;
    print(_parameter);
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => YourModel(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  TabController controller;
  @override
  void initState() {
    super.initState();
    controller = TabController(vsync: this, length: 3);
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {},
      child: Scaffold(
        appBar: AppBar(
          title: Text("InstaPost"),
          backgroundColor: Colors.black45,
          bottom: TabBar(
            controller: controller,
            tabs: [
              Tab(
                text: "Tab 1",
              ),
              Tab(text: "Tab 2"),
              Tab(text: "Tab 3"),
              // Tab(text: "My Posts")
            ],
          ),
        ),
        body: TabBarView(
          controller: controller,
          children: <Widget>[
            HashtagPage(controller),
            Tab2(),
            Tab3(),
          ],
        ),
      ),
    );
  }
}

class Tab2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text("Tab2");
  }
}

class Tab3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text("${(context.watch<YourModel>().parameter)}"));
  }
}

class HashtagPage extends StatefulWidget {
  TabController controller;

  HashtagPage(this.controller);
  @override
  _HashtagPageState createState() => _HashtagPageState();
}

class _HashtagPageState extends State<HashtagPage> {
  Future<List<String>> _future;

  Future<List<String>> getLists() async {
    await Future.delayed(Duration(seconds: 1), () {});

    return Future.value(["a", "b", "c", "d", "e", "f", "g"]);
  }

  @override
  void initState() {
    _future = getLists();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {},
      child: FutureBuilder(
        future: _future,
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Container(
              child: SpinKitDoubleBounce(color: Colors.green, size: 100),
            );
          } else {
            // log(snapshot.data.toString());
            var data = snapshot.data;
            return Container(
              child: Column(
                children: <Widget>[
                  Expanded(
                    child: ListView.separated(
                      separatorBuilder: (BuildContext context, int index) =>
                          Divider(),
                      itemCount: data.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(data[index]),
                          onTap: () {
                            Provider.of<YourModel>(context, listen: false)
                                .passParameter(data[index]);
                            widget.controller.animateTo(2);
                          },
                        );
                      },
                    ),
                  )
                ],
              ),
            );
          }
        },
      ),
    );
  }
}

Upvotes: 1

Related Questions