flutter 显示TabBarView小部件时RefreshIndicator不工作

soat7uwm  于 2023-05-30  发布在  Flutter
关注(0)|答案(1)|浏览(260)

当我执行pull to refresh操作时,RefreshIndicator小部件中的onRefresh内的代码不会执行。我想做一个pull来刷新动作,这样RefreshIndicator就会出现并触发onRefresh参数中的代码。但是,当我用另一个小部件(如Text())替换TabBarView小部件的子部件ListView.builder()时,RefreshIndicator小部件将出现。
下面是我的代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  int selectedIndex = 0;
  late TabController tabController;

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

  Widget _buildContent() {
    return Scaffold(
      body: RefreshIndicator(
        onRefresh: () async {
          print('wwwww');
        },
        child: NestedScrollView(
          headerSliverBuilder: (ctx, __) {
            return [
              SliverOverlapAbsorber(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                    ctx),
                sliver: SliverAppBar(
                  toolbarHeight: 68,
                  backgroundColor: Colors.white,
                  elevation: 0,
                  leadingWidth: 88,
                  titleSpacing: 0,
                  leading: IconButton(
                    onPressed: () {
                      Navigator.pop(context);
                    },
                    icon: const Icon(
                      Icons.arrow_back,
                      color: Colors.black,
                      size: 32,
                    ),
                  ),
                ),
              ),
              SliverToBoxAdapter(
                child: Container(
                  color: Colors.red,
                  height: 300,
                ),
              ),
              SliverToBoxAdapter(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 32),
                  child: CommonTabBar(
                    controller: tabController,
                    titles: const [
                      'Tab-1',
                      'Tab-2',
                    ],
                    icons: [
                      Icon(Icons.add),
                      Icon(Icons.map),
                    ],
                    selectedIcon: [
                      Icon(Icons.add),
                      Icon(Icons.map),
                    ],
                    selectedTabIndex: selectedIndex,
                    handleSelectedTab: _handleTabSelection,
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            controller: tabController,
            children: [
              ListView.builder(
                itemBuilder: (context, index) {
                  return Text('$index');
                },
                itemCount: 20,
              ),
              ListView.builder(
                itemBuilder: (context, index) {
                  return Text('$index');
                },
                itemCount: 20,
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _handleTabSelection() {
    setState(() {
      selectedIndex = tabController.index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _buildContent();
  }
}

class CommonTabBar extends StatelessWidget {
  final TabController controller;
  final List<String> titles;
  final List<Icon> icons;
  final List<Icon> selectedIcon;
  final int selectedTabIndex;
  final Function handleSelectedTab;

  const CommonTabBar({
    Key? key,
    required this.controller,
    required this.titles,
    required this.icons,
    required this.selectedIcon,
    required this.selectedTabIndex,
    required this.handleSelectedTab,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.bottomLeft,
      children: [
        Container(
          margin: const EdgeInsets.symmetric(vertical: 8),
          decoration: UnderlineTabIndicator(
            borderRadius: BorderRadius.circular(4),
            borderSide: const BorderSide(
              width: 4,
              color: Colors.black12,
            ),
          ),
        ),
        Container(
          margin: const EdgeInsets.symmetric(vertical: 8),
          child: TabBar(
            controller: controller,
            isScrollable: true,
            tabs: List.generate(titles.length, (idx) {
              return Container(
                alignment: Alignment.center,
                constraints: const BoxConstraints(minWidth: 132),
                child: Row(
                  children: [
                    selectedTabIndex == idx ? selectedIcon[idx] : icons[idx],
                    const SizedBox(width: 8),
                    Text(
                      titles[idx],
                      textAlign: TextAlign.center,
                    ),
                  ],
                ),
              );
            }),
            labelColor: selectedTabColor(selectedTabIndex),
            unselectedLabelColor: Colors.black26,
            labelStyle: TextStyle(fontSize: 14),
            unselectedLabelStyle: TextStyle(fontSize: 20),
            labelPadding: const EdgeInsets.all(16),
            indicatorSize: TabBarIndicatorSize.tab,
            splashBorderRadius: BorderRadius.circular(16),
            indicator: UnderlineTabIndicator(
              borderRadius: BorderRadius.circular(4),
              borderSide: BorderSide(
                width: 4,
                color: selectedTabColor(selectedTabIndex),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Color selectedTabColor(index) {
    if (index == 1) {
      return Colors.blue;
    } else if(index == 2) {
      return Colors.orange;
    }else {
      return Colors.green;
    }
  }
}

请帮帮我

lrl1mhuk

lrl1mhuk1#

要解决此问题,请使用SingleChildScrollView Package TabBarView,并将其物理设置为AlwaysScrollableScrollPhysics()。此修改允许RefreshIndicator出现,并在执行拉取刷新操作时触发onRefresh参数中的代码。
请按照下面提供的代码相应地实现。

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {

  Widget _buildContent() {
    return Scaffold(
      body: RefreshIndicator(
        onRefresh: () async {
          print('Refreshing...');
        },
        child: NestedScrollView(
          
          body: SingleChildScrollView(  SingleChildScrollView
            physics: const AlwaysScrollableScrollPhysics(),
            child: Column(
              children: [
                TabBarView(
                  controller: tabController,
                  children: [
                    ListView.builder(
                      itemBuilder: (context, index) {
                        return Text('$index');
                      },
                      itemCount: 20,
                    ),
                    ListView.builder(
                      itemBuilder: (context, index) {
                        return Text('$index');
                      },
                      itemCount: 20,
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

相关问题