我目前正在处理我的Ffltter应用程序中的一个页面,并面临着实现特定逻辑的挑战.当应用程序启动时,我希望页面一开始会显示"appbardown"窗口小部件(较大的那个),并保持该状态,直到用户决定向上滑动或滚动其中一个选项卡中的"一"列表.

目前,当我try 向上滑动时,小工具会切换到"appbarup"小工具,但转换既不流畅也不高效.此外,当我try 滚动"一"的列表时,我希望在允许滚动列表之前,"appbardown"窗口小部件能够平稳地过渡到"appbarup"窗口小部件.

相反,当我向下滑动时,小工具应该从"appbarup"变为"appbardown".同样,当我向下滚动"1"列表时,应用程序栏也应该相应地移动.

如果您对实现此功能有任何见解或更好的解决方案,我将非常感谢您的帮助.

import 'package:flutter/material.dart';

import 'widgets/quick_links.dart';

class TempScreen extends StatefulWidget {
  const TempScreen({super.key});

  @override
  State<TempScreen> createState() => _TempScreenState();
}

class _TempScreenState extends State<TempScreen> {
  final controller = PageController(initialPage: 1);
  bool isSecondOrder = false;

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      body: GestureDetector(
        onVerticalDragEnd: (details) {
          if (details.primaryVelocity! > 0) {
            // Swiped downwards
            setState(() {
              isSecondOrder = false;
            });
          } else if (details.primaryVelocity! < 0) {
            //Swiped Upwards
            setState(() {
              isSecondOrder = true;
            });
          }
        },
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            AnimatedSwitcher(
              switchInCurve: Curves.easeInOut, // Use your preferred curve
              switchOutCurve: Curves.easeInOut, // Use your preferred curve
              transitionBuilder: (child, animation) {
                return Container(
                  color: Theme.of(context).primaryColor,
                  child: FadeTransition(
                    opacity: animation,
                    child: child,
                  ),
                );
              },
              duration: const Duration(milliseconds: 1),
              child: isSecondOrder
                  ? AppBarUpt(size: size)
                  : AppBarDownt(size: size),
            ),
            Padding(
              padding: EdgeInsets.only(
                  left: size.width * 0.05, top: size.height * 0.035),
              child: const Text(
                'Quick Links',
                style: TextStyle(
                  fontSize: 20.0,
                  color: Colors.black,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Padding(
                padding: EdgeInsets.only(
                  left: size.width * 0.05,
                ),
                child: const Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('A'),
                    Text('B'),
                    Text('C'),
                    Text('D'),
                    Text('E'),
                  ],
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: EdgeInsets.only(
                  top: 20,
                  left: size.width * 0.04,
                  right: size.width * 0.04,
                ),
                child: DefaultTabController(
                  length: 3, // Number of tabs
                  child: Column(
                    children: [
                      Padding(
                        padding: EdgeInsets.only(
                          // top: 20,
                          left: size.width * 0.04,
                          right: size.width * 0.04,
                        ),
                        child: const TabBar(
                          indicatorWeight:
                              4.0, // Adjust indicator weight as needed
                          indicatorColor: Colors.black,
                          // labelPadding: EdgeInsets.symmetric(horizontal: 16.0),
                          labelStyle: TextStyle(
                            fontSize: 18.0,
                            fontWeight: FontWeight.w700,
                          ),
                          tabs: [
                            Tab(text: '1'),
                            Tab(text: '2'),
                            Tab(text: '3'),
                          ],
                          unselectedLabelColor:
                              Color.fromARGB(255, 186, 186, 186),
                        ),
                      ),
                      const Expanded(
                        child: TabBarView(
                          children: [
                            // Your Surah page content
                            One(),
                            Two(),
                            Three(),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const SingleChildScrollView(
      padding: EdgeInsets.only(
        top: 10,
      ),
      child: Column(
        children: [
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
          Text(
            'one',
            style: TextStyle(
              fontSize: 50,
            ),
          ),
        ],
      ),
    );
  }
}
class Two extends StatelessWidget {
  const Two({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Two'),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Three'),
    );
  }
}

class AppBarDownt extends StatelessWidget {
  const AppBarDownt({
    super.key,
    required this.size,
  });

  final Size size;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: size.height * 0.29,
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: const BorderRadius.only(
          bottomLeft: Radius.circular(20),
          bottomRight: Radius.circular(20),
        ),
      ),
    );
  }
}

class AppBarUpt extends StatelessWidget {
  const AppBarUpt({
    super.key,
    required this.size,
  });

  final Size size;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: size.height * 0.15,
      decoration: BoxDecoration(
        color: Theme.of(context).primaryColor,
        borderRadius: const BorderRadius.only(
          bottomLeft: Radius.circular(20),
          bottomRight: Radius.circular(20),
        ),
      ),
    );
  }
}

推荐答案

结果

enter image description here

解释

由于您正在处理的是AppBar,因此您可能正在寻找NestedScrollView/SliverAppBar.

要检测您当前是否正在滚动,您可以使用NotificationListener.

代码

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isScrolling = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        body: Scaffold(
          body: NestedScrollView(
            headerSliverBuilder: (context, _) => [
              isScrolling
                  ? SliverAppBar(
                      pinned: true,
                      flexibleSpace: Container(
                        color: Colors.green,
                        child: FlexibleSpaceBar(
                          title: Text(
                            'YES scrolling',
                            style: TextStyle(color: Colors.black),
                          ),
                        ),
                      ),
                    )
                  : SliverAppBar(
                      pinned: true,
                      flexibleSpace: Container(
                        color: Colors.red,
                        child: FlexibleSpaceBar(
                          title: Text(
                            'NOT scrolling',
                            style: TextStyle(color: Colors.black),
                          ),
                        ),
                      ),
                    ),
            ],
            body: NotificationListener<ScrollNotification>(
              onNotification: (scrollNotification) {
                // check if the user is scrolling
                if (scrollNotification is ScrollStartNotification) {
                  setState(() {
                    isScrolling = true;
                  });
                } else if (scrollNotification is ScrollEndNotification) {
                  setState(() {
                    isScrolling = false;
                  });
                }
                return true;
              },
              child: ListView.builder(
                itemCount: 100,
                itemBuilder: (context, index) => ListTile(
                  title: Text('Item $index'),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}


如果你想要动画,你可以使用AnimtedSwitcher.例如:

 flexibleSpace: AnimatedSwitcher(
                duration: Duration(seconds: 1),
                child: isScrolling
                    ? Container(
                        key: ValueKey('AppBar1'),
                        color: Colors.green,
                        child: FlexibleSpaceBar(
                          title: Text('YES scrolling',
                              style: TextStyle(color: Colors.black)),
                        ),
                      )
                    : Container(
                        key: ValueKey('AppBar2'),
                        color: Colors.red,
                        child: FlexibleSpaceBar(
                          title: Text('NOT scrolling',
                              style: TextStyle(color: Colors.black)),
                        ),
                      ),
              ),

Flutter相关问答推荐

如何将图像从顶部和底部半向外设置为飘动

当键盘在抖动中打开时,如何才能看到包装在SingleChildScrollView中的列中的最后一个小工具?

无法在我的Flutter 应用程序中使用GoRouter测试导航

在VSCode中运行应用程序而不进行调试时,控制台仍显示为调试模式

Flutter 数独网格

在创建显示此错误的Flutter 深度链接时

Flutter中的编译时间常量方法

Riverpod Provider.family 和 HookConsumerWidget 不刷新 UI

2023 年如何使用 youtube_explode_dart 包下载 URL?

我无法找到修复此错误的位置,指出无法使用静态访问来访问实例成员

Flutter 使用扩展的 TextField 定位小部件

Flutter如何从深入嵌套的小部件中打开抽屉?

Flutter居中的SizedBox无法居中

Freezed+BLoc 如何从 BLoc Listener 查看当前状态和特定状态的变量

MediaQuery 在不同手机上不一致

为什么将 bloc 提供程序放在单独的文件/类中会引发错误?

有没有办法为文本中的下划线创建自定义样式?

我无法从 Cloud firestore 访问文档字段并在 statefulwidget 类中显示它

如何在 Flutter 中将列小部件添加到行小部件?

Flutter 用户过滤器