Flutter:禁用的小部件会禁用Tabview拖动检测

时间:2018-11-12 00:15:41

标签: flutter drag tabview

我有两个选项卡,左边的选项卡有一个磁贴列表,右边的选项卡什么也没有。用户可以从右向左或从左向右拖动屏幕,以从一个选项卡转到另一个选项卡。 左侧标签页列出了仅允许启用“方向:DismissDirection.startToEnd”(从左至右)的可禁用图块列表,因此,理论上用户仍然可以拖动(从右至左)转到右侧选项卡。 但是,我相信Dismissible小部件仍然会接收从右到左的拖动信息,这将禁用TabView拖动来更改选项卡。

从本质上讲,我如何允许仅TabView而不是Dismissible项检测到从右向左拖动?

如果可以给出带有代码片段的明确解决方案/示例,我将非常感谢您的帮助!

以下是您main.dart文件的粘贴内容:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/semantics.dart';

void main() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin {
  TabController _tabController;
  @override
  void initState() {
    _tabController = TabController(vsync: this, length: 2, initialIndex: 1);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          color: Colors.black,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Expanded(
                child: TabBarView(
                  controller: _tabController,
                  children: <Widget>[
                    TabWithSomething(),
                    TabWithNothing(),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class TabWithNothing extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: Text("Swipe from left-to-right!"),
      ),
    );
  }
}

class TabWithSomethingItem implements Comparable<TabWithSomethingItem> {
  TabWithSomethingItem({this.index, this.name, this.subject, this.body});

  TabWithSomethingItem.from(TabWithSomethingItem item)
      : index = item.index,
        name = item.name,
        subject = item.subject,
        body = item.body;

  final int index;
  final String name;
  final String subject;
  final String body;

  @override
  int compareTo(TabWithSomethingItem other) => index.compareTo(other.index);
}

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

  static const String routeName = '/material/leave-behind';

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

class TabWithSomethingState extends State<TabWithSomething> {
  List<TabWithSomethingItem> TabWithSomethingItems;

  void initListItems() {
    TabWithSomethingItems =
        List<TabWithSomethingItem>.generate(10, (int index) {
      return TabWithSomethingItem(
          index: index,
          name: 'Item $index',
          subject: 'Swipe from left-to-right to delete',
          body: "Swipe from right-to-left to go back to old tab");
    });
  }

  @override
  void initState() {
    super.initState();
    initListItems();
  }

  void _handleDelete(TabWithSomethingItem item) {
    setState(() {
      TabWithSomethingItems.remove(item);
    });
  }

  @override
  Widget build(BuildContext context) {
    Widget body;
    body = ListView(
        children:
            TabWithSomethingItems.map<Widget>((TabWithSomethingItem item) {
      return _TabWithSomethingListItem(
        item: item,
        onDelete: _handleDelete,
        dismissDirection: DismissDirection.startToEnd,
      );
    }).toList());

    return body;
  }
}

class _TabWithSomethingListItem extends StatelessWidget {
  const _TabWithSomethingListItem({
    Key key,
    @required this.item,
    @required this.onDelete,
    @required this.dismissDirection,
  }) : super(key: key);

  final TabWithSomethingItem item;
  final DismissDirection dismissDirection;
  final void Function(TabWithSomethingItem) onDelete;

  void _handleDelete() {
    onDelete(item);
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    return Semantics(
      customSemanticsActions: <CustomSemanticsAction, VoidCallback>{
        const CustomSemanticsAction(label: 'Delete'): _handleDelete,
      },
      child: Dismissible(
        key: ObjectKey(item),
        direction: dismissDirection,
        onDismissed: (DismissDirection direction) => _handleDelete(),
        background: Container(
            color: theme.primaryColor,
            child: const ListTile(
                leading: Icon(Icons.delete, color: Colors.white, size: 36.0))),
        child: Container(
          decoration: BoxDecoration(
              color: theme.canvasColor,
              border: Border(bottom: BorderSide(color: theme.dividerColor))),
          child: ListTile(
              title: Text(item.name),
              subtitle: Text('${item.subject}\n${item.body}'),
              isThreeLine: true),
        ),
      ),
    );
  }
}

更新: 我想我们可以更改“ dismissible.dart”文件来更改“ TabControlller”,但我不确定该怎么做。

在“ dismissible.dart”文件中:

...
  void _handleDragUpdate(DragUpdateDetails details) {
    if (!_isActive || _moveController.isAnimating)
      return;

    final double delta = details.primaryDelta;

    if (delta < 0) print(delta);  // thinking of doing something here
...

0 个答案:

没有答案