如何检测颤动上的滑动标签栏?

时间:2019-04-03 00:49:42

标签: dart flutter tabbar

在滑动然后在控制台上打印内容时,我需要检测标签栏,我该怎么做?这是我的代码

bottomNavigationBar: new Material(
             color: Colors.blueAccent,
             child: new TabBar(
               onTap: (int index){ setState(() {
                 _onTap(index);
               });},

               indicatorColor: Colors.white,
               controller: controller,
               tabs: <Widget>[
                 new Tab(icon: new Icon(Icons.shopping_basket)),
                 new Tab(icon: new Icon(Icons.store)),
                 new Tab(icon: new Icon(Icons.local_offer)),
                 new Tab(icon: new Icon(Icons.assignment)),
                 new Tab(icon: new Icon(Icons.settings)),

               ],
             )
           ),

9 个答案:

答案 0 :(得分:6)

这里是一个完整的例子。使用TabController并使用addListener添加回调。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      home: MyTabbedPage(),
    );
  }
}

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

class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
  var _context;

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

  TabController _tabController;

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

    _tabController.addListener(_handleTabSelection);
  }

  void _handleTabSelection() {
    if (_tabController.indexIsChanging) {
      switch (_tabController.index) {
        case 0:
          Scaffold.of(_context).showSnackBar(SnackBar(
            content: Text('Page 1 tapped.'),
            duration: Duration(milliseconds: 500),
          ));
          break;
        case 1:
          Scaffold.of(_context).showSnackBar(SnackBar(
            content: Text('Page 2 tapped.'),
            duration: Duration(milliseconds: 500),
          ));
          break;
      }
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller: _tabController,
          tabs: myTabs,
        ),
      ),
      body: Builder(
        builder: (context) {
          _context = context;
          return TabBarView(
            controller: _tabController,
            children: myTabs.map((Tab tab) {
              final String label = tab.text.toLowerCase();
              return Center(
                child: Text(
                  'This is the $label tab',
                  style: const TextStyle(fontSize: 36),
                ),
              );
            }).toList(),
          );
        },
      ),
    );
  }
}

答案 1 :(得分:1)

enter image description here

在BottomNavigationBar中扭曲选项卡。它将为您提供onTap()选项,您可以在其中检查将单击哪个选项卡。

使用此代码,当您点击Tab时,您还将重定向到特定页面

import 'package:flutter/material.dart';
    
    
    class BottomBarList extends StatefulWidget {
      @override
      _BottomBarListState createState() => _BottomBarListState();
    }
    
    class _BottomBarListState extends State<BottomBarList> {
      int bottomSelectedIndex = 0;
      int _selectedIndex = 0;
    
    
      List<Widget> _widgetOptions = <Widget>[
        AllMovieList(),
        MovieDescription(),
    
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          //  appBar: AppBar(),
          bottomNavigationBar: bottomBar(),
          body:_widgetOptions.elementAt(_selectedIndex),
        );
      }
    
      bottomBar() {
        return BottomNavigationBar(
    
          type: BottomNavigationBarType.shifting,
          unselectedItemColor: Colors.grey,
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.tv),
              title: Text('Home'),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.star),
              title: Text('Business'),
            ),
          ],
          currentIndex: _selectedIndex,
          selectedItemColor: Colors.black,
          backgroundColor: Colors.orange,
          onTap: _onItemTapped,
        );
      }
    
    
      void _onItemTapped(int index) {
        setState(() {
          _selectedIndex = index;
        });
      }
    }

答案 2 :(得分:0)

您需要将侦听器添加到标签控制器-也许在tsconfig中。

initState

答案 3 :(得分:0)

您可以通过添加以下内容来禁用TabBarView上的滑动效果:

physics: NeverScrollableScrollPhysics(),

并声明一个TabController并将其分配给您的TabBarTabBarView

TabController _tabController;

答案 4 :(得分:0)

我们可以使用NotificationListener小部件来监听标签滚动通知

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: NotificationListener(
          onNotification: (scrollNotification) {
            if (scrollNotification is ScrollUpdateNotification) {
              _onStartScroll(scrollNotification.metrics);
            }
          },
          child: _buildTabBarAndTabBarViews(),
    );
  }

  _onStartScroll(ScrollMetrics metrics) {
    print('hello world');
  }
}

答案 5 :(得分:0)

onTap()功能不提供滑动功能,因为使用了TabController

class TabBarDemo extends StatefulWidget {
  @override
  _TabBarDemoState createState() => _TabBarDemoState();
}

class _TabBarDemoState extends State<TabBarDemo>
    with SingleTickerProviderStateMixin {
  TabController _controller;
  int _selectedIndex = 0;

  List<Widget> list = [
    Tab(icon: Icon(Icons.card_travel)),
    Tab(icon: Icon(Icons.add_shopping_cart)),
  ];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    // Create TabController for getting the index of current tab
    _controller = TabController(length: list.length, vsync: this);

    _controller.addListener(() {
      setState(() {
        _selectedIndex = _controller.index;
      });
      print("Selected Index: " + _controller.index.toString());
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            onTap: (index) {
              // Should not used it as it only called when tab options are clicked,
              // not when user swapped
            },
            controller: _controller,
            tabs: list,
          ),
          title: Text('Tabs Demo'),
        ),
        body: TabBarView(
          controller: _controller,
          children: [
            Center(
                child: Text(
                  _selectedIndex.toString(),
                  style: TextStyle(fontSize: 40),
                )),
            Center(
                child: Text(
                  _selectedIndex.toString(),
                  style: TextStyle(fontSize: 40),
                )),
          ],
        ),
      ),
    );
  }
}

Github: https://github.com/jitsm555/Flutter-Problems/tree/master/tab_bar_tricks

输出:

enter image description here

答案 6 :(得分:0)

我遇到了类似的问题,以下是我为实现相同目的所做的事情:-

import 'package:flutter/material.dart';

import '../widgets/basic_dialog.dart';
import 'sign_in_form.dart';
import 'sign_up_form.dart';

class LoginDialog extends StatefulWidget {
  @override
  _LoginDialogState createState() => _LoginDialogState();
}

class _LoginDialogState extends State<LoginDialog>
    with SingleTickerProviderStateMixin {
  int activeTab = 0;
  TabController controller;

  @override
  void initState() {
    super.initState();
    controller = TabController(vsync: this, length: 2);
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener(
      onNotification: (ScrollNotification notification) {
        setState(() {
          if (notification.metrics.pixels <= 100) {
            controller.index = 0;
          } else {
            controller.index = 1;
          }
        });

        return true;
      },
      child: BasicDialog(
        child: Container(
          height: controller.index == 0
              ? MediaQuery.of(context).size.height / 2.7
              : MediaQuery.of(context).size.height / 1.8,
          padding: const EdgeInsets.all(8.0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              TabBar(
                controller: controller,
                tabs: <Widget>[
                  Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: Text('Sign In'),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: Text('Sign up'),
                  ),
                ],
              ),
              Expanded(
                child: TabBarView(
                  controller: controller,
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: SingleChildScrollView(
                        child: SignInForm(),
                      ),
                    ),

                    // If a container is not displayed during the tab switch to tab0, renderflex error is thrown because of the height change.
                    controller.index == 0
                        ? Container()
                        : Padding(
                            padding: const EdgeInsets.all(8.0),
                            child: SingleChildScrollView(
                              child: SignUpForm(),
                            ),
                          ),
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

答案 7 :(得分:0)

您可以使用 NotificationListener 的唯一滚动通知(ScrollEndNotification)。它涵盖了点击和滑动操作。

class HandlingTabChanges extends State<JsonTestDetailFrame> with SingleTickerProviderStateMixin {
  late final TabController _tabController;
  final int _tabLength = 2;

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

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _tabLength,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Some title"),
          bottom: TabBar(
            controller: _tabController,
            tabs: [
              Icon(Icons.settings),
              Icon(Icons.list_alt),
            ],
          ),
        ),
        body: NotificationListener(
          onNotification: (scrollNotification) {
            if (scrollNotification is ScrollEndNotification) _onTabChanged();
            return false;
          },
          child: TabBarView(
            controller: _tabController,
            children: [
              SomeWidget1(),
              SomeWidget2(),
            ],
          ),
        ),
      ),
    );
  }

  void _onTabChanged() {
    switch (_tabController.index) {
      case 0:
        // handle 0 position
        break;
      case 1:
        // handle 1 position
        break;
    }
  }
}

答案 8 :(得分:0)

您可以创建包装小部件

class _DefaultTabControllerListener extends StatefulWidget {
  const _DefaultTabControllerListener(
      {Key? key, this.onTabSelected, required this.child})
      : super(key: key);

  final void Function(int index)? onTabSelected;
  final Widget child;

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

class _DefaultTabControllerListenerState
    extends State<_DefaultTabControllerListener> {
  late final void Function()? _listener;
  TabController? _tabController;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      final tabController = DefaultTabController.of(context)!;
      _listener = () {
        final onTabSelected = widget.onTabSelected;
        if (onTabSelected != null) {
          onTabSelected(tabController.index);
        }
      };
      tabController.addListener(_listener!);
    });
  }
  
  @override
  void didChangeDependencies() {
    _tabController = DefaultTabController.of(context);
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    if (_listener != null && _tabController != null) {
      _tabController!.removeListener(_listener!);
    }
    super.dispose();
  }

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

}

并用这个小部件包裹 TabBar

DefaultTabController(
        child: _DefaultTabControllerListener(
                  onTabSelected: (index) {
                    // Handler
                  },
                  child: TabBar(.....