Как получить индекс текущей вкладки во Flutter

В Flutter реализовать макет вкладок легко и просто. Это простой пример из официального документация:

import 'package:flutter/material.dart';

void main() {
  runApp(new TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            bottom: new TabBar(
              tabs: [
                new Tab(icon: new Icon(Icons.directions_car)),
                new Tab(icon: new Icon(Icons.directions_transit)),
                new Tab(icon: new Icon(Icons.directions_bike)),
              ],
            ),
            title: new Text('Tabs Demo'),
          ),
          body: new TabBarView(
            children: [
              new Icon(Icons.directions_car),
              new Icon(Icons.directions_transit),
              new Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

Но вот в чем дело: я хочу получить индекс активной вкладки, чтобы применить некоторую логику к определенным вкладкам. Я ищу документацию, но не могу понять. Ребята, вы можете помочь и спасибо?

Ответ на вашу проблему здесь введите описание ссылки здесь

ALNAJJAR 05.12.2020 22:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
32
1
39 380
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

Вся суть DefaultTabController в том, что он сам по себе управляет вкладками.

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

class MyTabbedPage extends StatefulWidget {
  const MyTabbedPage({Key key}) : super(key: key);
  @override
  _MyTabbedPageState createState() => new _MyTabbedPageState();
}

class _MyTabbedPageState extends State<MyTabbedPage>
    with SingleTickerProviderStateMixin {
  final List<Tab> myTabs = <Tab>[
    new Tab(text: 'LEFT'),
    new Tab(text: 'RIGHT'),
  ];

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = new TabController(vsync: this, length: myTabs.length);
  }

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

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        bottom: new TabBar(
          controller: _tabController,
          tabs: myTabs,
        ),
      ),
      body: new TabBarView(
        controller: _tabController,
        children: myTabs.map((Tab tab) {
          return new Center(child: new Text(tab.text));
        }).toList(),
      ),
    );
  }
}

В этом примере как получить индекс ?? Я попытался добавить список, но после создания определенного представления вкладки слушатель печатал индекс, который я хочу получить, прежде чем создавать макет конкретной вкладки. Любая идея?

sarvesh chavan 20.04.2019 07:28

только с состоянием?

shinriyo 11.06.2020 02:18

Привет, @sarveshchavan, ты нашел какое-нибудь решение?

Sachin 18.06.2020 14:12

Чтобы получить индекс вкладок, просто выполните _tabController.index

repleeka 28.05.2021 10:11

В этом случае использование StatefulWidget и State - не лучшая идея.

Вы можете получить текущий индекс по DefaultTabController.of(context).index;.

Следуйте коду:

...
appBar: AppBar(
  bottom: TabBar(
    tabs: [
      Tab(~), Tab(~)
    ]
  ),
  actions: [
    // At here you have to get `context` from Builder.
    // If you are not sure about this, check InheritedWidget document.
    Builder(builder: (context){
      final index = DefaultTabController.of(context).index;   
      // use index at here... 
    })
  ]
)

У меня сработало обертывание всего Scaffold внутри Builder.

Rami Alloush 14.06.2019 18:23

Спасибо, это все, что я искал. ???

punjabi4life 15.08.2019 10:31

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

surtyaar 26.07.2020 17:50

Благодаря примеру Реми Русселе вы можете это сделать, вот такой код:

_tabController.index

Это вернет текущий индекс позиции вашего TabBarView

Вы можете получить доступ к текущему индексу, когда вкладка выбрана событием onTap для TabBar.

TabBar(
    onTap: (index) {
      //your currently selected index
    },

    tabs: [
      Tab1(),
      Tab2(),
    ]);

Это не работает должным образом, если пользователь меняет вкладки, проводя пальцем по экрану. Только если они действительно нажимают на панель вкладок.

dakamojo 26.08.2019 22:59

Просто примените слушателя к TabController.

// within your initState() method
_tabController.addListener(_setActiveTabIndex);

void _setActiveTabIndex() {
  _activeTabIndex = _tabController.index;
}

Этот код предоставит вам указатель активной вкладки, а также сохранит указатель вкладки для будущего использования, а когда вы вернетесь на страницу вкладки, будет отображаться предыдущая активная страница.

import 'package:flutter/material.dart';

    void main() {
      runApp(new TabBarDemo());
    }

    class TabBarDemo extends StatelessWidget {


      TabScope _tabScope = TabScope.getInstance();

      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: new DefaultTabController(
            length: 3,
            index: _tabScope.tabIndex, // 
            child: new Scaffold(
              appBar: new AppBar(
                bottom: new TabBar(
                  onTap: (index) => _tabScope.setTabIndex(index),  //current tab index
                  tabs: [
                    new Tab(icon: new Icon(Icons.directions_car)),
                    new Tab(icon: new Icon(Icons.directions_transit)),
                    new Tab(icon: new Icon(Icons.directions_bike)),
                  ],
                ),
                title: new Text('Tabs Demo'),
              ),
              body: new TabBarView(
                children: [
                  new Icon(Icons.directions_car),
                  new Icon(Icons.directions_transit),
                  new Icon(Icons.directions_bike),
                ],
              ),
            ),
          ),
        );
      }
    }

    class TabScope{ // singleton class
      static TabScope _tabScope;
      int tabIndex = 0;

      static TabScope getInstance(){
        if (_tabScope == null) _tabScope = TabScope();

        return _tabScope;
      }
      void setTabIndex(int index){
        tabIndex = index;
      }
    }

Вы можете добавить слушателя для прослушивания изменений на вкладках, как показано ниже.

tabController = TabController(vsync: this, length: 4)
   ..addListener(() {
setState(() {
  switch(tabController.index) {
    case 0:
      // some code here
    case 1:
     // some code here
  }
  });
});

Не забудьте перезапустить приложение после этого, вместо того, чтобы использовать горячую перезагрузку. Поскольку горячая перезагрузка не обязательно снова запускает initState для вашего экрана.

George 13.11.2020 15:11

Используя DefaultTabController, вы можете легко получить текущий индекс независимо от того, меняет ли пользователь вкладки с помощью смахивание или кран на панели вкладок.

Важно: вы должны обернуть свой Scaffold внутри Builder, и тогда вы сможете получить индекс вкладки с помощью DefaultTabController.of(context).index внутри Scaffold.

Пример:

DefaultTabController(
    length: 3,
    child: Builder(builder: (BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Home'),
          bottom: TabBar(
              isScrollable: true,
              tabs: [Text('0'), Text('1'), Text('2')]),
        ),
        body: _buildBody(),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            print(
                'Current Index: ${DefaultTabController.of(context).index}');
          },
        ),
      );
    }),
  ),

Новое рабочее решение

Я предлагаю вам использовать TabController для дополнительных настроек. Чтобы получить индекс активной вкладки, вы должны использовать _tabController.addListener и _tabController.indexIsChanging.

Используйте этот полный фрагмент кода:


class CustomTabs extends StatefulWidget {
  final Function onItemPressed;

  CustomTabs({
    Key key,
    this.onItemPressed,
  }) : super(key: key);

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

class _CustomTabsState extends State<CustomTabs>
    with SingleTickerProviderStateMixin {

  final List<Tab> myTabs = <Tab>[
    Tab(text: 'LEFT'),
    Tab(text: 'RIGHT'),
  ];

  TabController _tabController;
  int _activeIndex = 0;
  
  @override
  void initState() {
    super.initState();
    _tabController = TabController(
      vsync: this,
      length: myTabs.length,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    _tabController.addListener(() {
      if (_tabController.indexIsChanging) {
        setState(() {
          _activeIndex = _tabController.index;
        });
      }
    });
    return Container(
      color: Colors.white,
      child: TabBar(
        controller: _tabController,
        isScrollable: true,
        indicatorPadding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
        indicator: BoxDecoration(
            borderRadius: BorderRadius.circular(10.0), color: Colors.green),
        tabs: myTabs
            .map<Widget>((myTab) => Tab(
                  child: Container(
                    width: width / 3 -
                        10, // - 10 is used to make compensate horizontal padding
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10.0),
                      color:
                          _activeIndex == myTabs.indexOf(myTab)
                              ? Colors.transparent
                              : Color(0xffA4BDD4),
                    ),
                    margin:
                        EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
                    child: Align(
                      alignment: Alignment.center,
                      child: Text(
                        myTab.text,
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ))
            .toList(),
        onTap: widget.onItemPressed,
      ),
    );
  }
}

Другие вопросы по теме