Tabview 滚动行为

Tabview scroll behavior

我有一个 Tabview 和一个 azlist scrollable bar 的列表。在 azlist bar 中滚动时,TabView 很容易移动,试图滑到另一个 Tab。我希望 TabView 在滚动 azlist scrollable bar 期间保持不变。有没有办法阻止 TabView 的这种行为?我试过声明一个 CustomScrollPhysic 但它并没有按照我想要的方式工作。

下面是附加的 gif 和代码。

在 pubspec 中导入这个

alphabet_list_view: ^0.1.2

home.dart

import 'package:alphabet_list_view/alphabet_list_view.dart';
import 'package:flutter/material.dart';


class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          bottom: const TabBar(
            isScrollable: true,
            tabs: [
              Tab(text: 'TabOne'),
              Tab(text: 'TabTwo'),
            ],
          ),
        ),
        body: SafeArea(
          child: TabBarView(
            physics: CustomScrollPhysics(),
            children: [
              TabOne(),
              TabTwo(),
            ],
          ),
        ),
      ),
    );
  }
}

tabone.dart

class TabOne extends StatelessWidget {
  TabOne({Key? key}) : super(key: key);

  final List<AlphabetListViewItemGroup> animals = [
    for (var animalLetter in animalsMap.entries)
      AlphabetListViewItemGroup(
        tag: animalLetter.key,
        children: animalLetter.value.map((animal) => Text(animal)).toList(),
      ),
  ];

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: AlphabetListView(
        items: animals,
      ),
    );
  }
}

tabtwo.dart


class TabTwo extends StatelessWidget {
  TabTwo({Key? key}) : super(key: key);

  final List<AlphabetListViewItemGroup> animals = [
    for (var animalLetter in animalsMap.entries)
      AlphabetListViewItemGroup(
        tag: animalLetter.key,
        children: animalLetter.value.map((animal) => Text(animal)).toList(),
      ),
  ];

  @override
  Widget build(BuildContext context) {
    return AlphabetListView(
      items: animals,
    );
  }
}

custom_scroll_physics.dart


class CustomScrollPhysics extends ScrollPhysics {
  const CustomScrollPhysics({ScrollPhysics? parent}) : super(parent: parent);

  @override
  ScrollPhysics applyTo(ScrollPhysics? ancestor) =>
      CustomScrollPhysics(parent: buildParent(ancestor));

  @override
  Simulation? createBallisticSimulation(
      ScrollMetrics position, double velocity) {
    final tolerance = this.tolerance;
    if ((velocity.abs() < tolerance.velocity) ||
        (velocity > 0.0 && position.pixels >= position.maxScrollExtent) ||
        (velocity < 0.0 && position.pixels <= position.minScrollExtent)) {
      return null;
    }
    return ClampingScrollSimulation(
      position: position.pixels,
      velocity: velocity,
      friction: 0.5,
      tolerance: Tolerance.defaultTolerance,
    );
  }
}

动物的硬编码地图


const Map<String, List<String>> animalsMap = {
  'A': [
    'Admiral, indian red',
  ],
  'B': [
    'Baboon, gelada',
    'Baboon, olive',
  ],
  'F': [
    'Fairy penguin',
    'Falcon, peregrine',
    'Frog (unidentified)',
  ],
  'G': [
    'Galah',
    'Galapagos albatross',
  ],
  'H': [
    'Hare, arctic',
    'Hartebeest, coke\'s',
  ],
  'I': [
    'Ibis, glossy',
    'Insect, stick',
  ],
  'J': [
    'Jacana, african',
    'Jackal, black-backed',
  ],
  'K': [
    'Kaffir cat',
    'Kafue flats lechwe',
    'Koala',
  ],
  'M': [
    'Macaque, pig-tailed',
    'Musk ox',
    'Mynah, indian',
  ],
  'N': [
    'Native cat',
    'Nighthawk, common',
  ],
  'P': [
    'Painted stork',
    'Porcupine, prehensile-tailed',
  ],
  'Q': [
    'Quoll, spotted-tailed',
  ],
  'T': [
    'Tailless tenrec',
    'Tapir, brazilian',
    'Tarantula, salmon pink bird eater',
  ],
  'U': [
    'Uinta ground squirrel',
  ],
  'V': [
    'Vicuna',
    'Vine snake (unidentified)',
  ],
  'W': [
    'Wagtail, african pied',
    'White-fronted capuchin',
    'Woylie',
  ],
  'Y': [
    'Yak',
  ],
  'Z': [
    'Zebra, plains',
    'Zorilla',
    'Zorro, common',
  ],
};

我有一个非常相似的页面:两个包含字母列表和滚动的选项卡运行良好。

我的小部件上没有 CustomScrollPhysics,但使用了 TabController。

class _PeopleListScreenState extends State<PeopleListScreen> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  var tab = _Tab.user;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: 2);
    _tabController.addListener(() {
      if (_tabController.indexIsChanging || _tabController.index != _tabController.previousIndex) {
        var index = _tabController.index;
        // Tab Changed tapping on new tab
        setState(() => tab = _Tab.values[index]);
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        children: [
          TabBar(
            controller: tabController,
            tabs: [Tab(), Tab()],
          ),
          Expanded(
            child: TabBarView(
              tabController: _tabController,
              children: [AlphabetList(), AlphabetList()],
            ),
          ),
        ],
      ),
    );
  }
}