是否有通过上下滑动在两个小部件(在我的例子中为应用程序栏)之间切换的正确方法?

问题描述 投票:0回答:1

我目前正在开发 Flutter 应用程序中的一个页面,并面临着实现特定逻辑的挑战。当应用程序启动时,我希望页面最初显示“appbardown”小部件(较大的小部件)并保持该状态,直到用户决定向上滑动或滚动浏览选项卡之一内的“Ones”列表。

目前,当我尝试向上滑动时,小部件会切换到“appbarup”小部件,但转换既不平滑也不高效。此外,当我尝试滚动“Ones”列表时,我希望“appbardown”小部件能够平滑地过渡到“appbarup”小部件,然后再允许我滚动列表。

相反,当我向下滑动时,小部件应该从“appbarup”移动到“appbardown”。同样,当我在“Ones”列表中向下滚动时,应用栏应该相应移动。

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

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),
        ),
      ),
    );
  }
}
flutter flutter-animation flutter-appbar flutter-container
1个回答
0
投票

结果

说明

既然您正在处理

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'),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.