Flutter web tabbarview scrollcontroller 不响应键盘滚动

如何解决Flutter web tabbarview scrollcontroller 不响应键盘滚动

  • 我创建了两个标签
  • 在每个选项卡中,我都有用 Scrollbar 包裹的 SingleChildScrollView。
  • 我不能在两个选项卡中都使用主滚动控制器,因为这会引发异常:“ScrollController 附加到多个滚动视图。”
  • 对于标签一,我使用主滚动控制器,对于标签二,我创建了滚动控制器并附加了它。
  • 对于带有主滚动控制器的 Tab ONE,我可以通过键盘和拖动滚动条进行滚动。
  • 但是对于带有非主滚动控制器的 Tab TWO,我只能通过拖动滚动条来滚动。此选项卡不响应键盘向上/向下翻页键。

请在下面检查我的代码。指导我如何实现 Tab 2 的键盘滚动。

import 'package:Flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TabExample(),);
  }
}

class TabExample extends StatefulWidget {
  const TabExample({Key key}) : super(key: key);

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

class _TabExampleState extends State<TabExample> {
  ScrollController _scrollController;

  @override
  void initState() {
    _scrollController = ScrollController();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: [
              Tab(icon: Text('Tab ONE')),Tab(icon: Text('Tab TWO')),],),title: Text('Tabs Demo'),body: TabBarView(
          children: [
            _buildWidgetA(),_buildWidgetB(),);
  }

  Widget _buildWidgetA() {
    List<Widget> children = [];
    for (int i = 0; i < 20; i++) {
      children.add(
        Padding(
          padding: EdgeInsets.symmetric(vertical: 16),child: Container(
            height: 100,width: double.infinity,color: Colors.black,);
    }
    return Scrollbar(
      isAlwaysShown: true,showTrackOnHover: true,child: SingleChildScrollView(
        child: Column(
          children: children,);
  }

  Widget _buildWidgetB() {
    List<Widget> children = [];
    for (int i = 0; i < 20; i++) {
      children.add(
        Padding(
          padding: EdgeInsets.symmetric(vertical: 16),color: Colors.green,);
    }
    return Scrollbar(
      controller: _scrollController,isAlwaysShown: true,child: SingleChildScrollView(
        controller: _scrollController,child: Column(
          children: children,);
  }
}

解决方法

您无需创建显式 ScrollController 即可实现此目的。

一个技巧是在 SingleChildScrollView 更改其索引时更改哪个 PrimaryScrollController 将使用 Tab

因此,当我们侦听该选项卡已更改为索引 0 时,我们将设置第一个 SingleChildScrolViewprimary。当它更改为 1 时,我们会将另一个设置为 primary

首先像这样创建一个新的状态变量,

int currentIndex = 0; // This will be the index of tab at a point in time

要监听更改事件,您需要将 Listener 添加到 TabController

DefaultTabController(
  length: 2,child: Builder(  // <---- Use a Builder Widget to get the context this this DefaultTabController
    builder: (ctx) {

      // Here we need to use ctx instead of context otherwise it will give null
      final TabController tabController = DefaultTabController.of(ctx);

      tabController.addListener(() {
        if (!tabController.indexIsChanging) {

          // When the tab has changed we are changing our currentIndex to the new index
          setState(() => currentIndex = tabController.index);
        }
      });

      return Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: [
              Tab(icon: Text('Tab ONE')),Tab(icon: Text('Tab TWO')),],),title: Text('Tabs Demo'),body: TabBarView(
          children: [
            _buildWidgetA(),_buildWidgetB(),);
    },);

最后,根据 currentIndexprimary: true 设置为每个 SingleChildScrollView

对于_buildWidgetA

Scrollbar(
  isAlwaysShown: true,showTrackOnHover: true,child: SingleChildScrollView(
    primary: currentIndex == 0,// <--- This will be primary if currentIndex = 0
    child: Column(
      children: children,);

对于_buildWidgetB

Scrollbar(
  isAlwaysShown: true,child: SingleChildScrollView(
    primary: currentIndex == 1,// <--- This will be primary if currentIndex = 1
    child: Column(
      children: children,);

现在,您应该可以使用键盘控制这两个选项卡了。

完整代码here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?