Flutter: с вкладки передать некоторую строку на определенную вкладку и отобразить эту конкретную вкладку на панели вкладок

#flutter #dart

#трепетание #дротик

Вопрос:

Я работаю над проектом flutter, где у меня есть 3 вкладки на панели вкладок. На вкладке 1 и вкладке 2 есть списки, показывающие некоторые данные с помощью ListView. При нажатии на элемент списка я хочу передать некоторую строку на вкладку 3 и показать вкладку 3.

Ниже приведен код моей домашней страницы:

 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(),
            ],
          ),
        ),
      ),
    );
  }
}
  

Итак, при запуске приложения первым экраном будет вкладка 1, на которой отображается список имен. Код приведен ниже

 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
                             
                          },
                        );
                      },
                    ),
                  )
                ],
              ),
            );
          }
        },
      ),
    );
  }
}

  

При нажатии на элемент списка на вкладке 1, как мне передать строку на вкладку 3 и одновременно перейти на вкладку 3?

Комментарии:

1. Пожалуйста, поделитесь кодом, в котором вы пытались решить эту проблему.

2. Существует много способов передачи значения от одного к другому, вы можете использовать конструктор, аргументы или статические переменные. пожалуйста, предоставьте более подробную информацию или код, чтобы мы могли выяснить вашу точную проблему.

3. Для тех, кто читает / использует этот код — обратите внимание, что объект TabController «controller» никогда не используется. Использование смешивается с DefaultTabController — так что следите за своим шагом 🙂

Ответ №1:

Вы можете скопировать вставить запустить полный код ниже
, который вы можете использовать https://pub.dev/packages/provider
Шаг 1: вы можете сохранить параметр в YourModel
Шаг 2: в Tab3 , вы можете получить доступ с помощью (context.watch<YourModel>().parameter)
фрагмент кода

 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);
              },
            );
  

рабочая демонстрация

введите описание изображения здесь

полный код

 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);
                          },
                        );
                      },
                    ),
                  )
                ],
              ),
            );
          }
        },
      ),
    );
  }
}
  

Ответ №2:

Это то, что сработало для меня.

Настройте TabController как таковой:

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

А затем переключаться между вкладками

   // 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);
  });