如何在滚动时过渡 Flutter 应用栏的颜色和标题?

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

我想在 Flutter 中创建一个一开始是透明的应用程序栏(其中有一些图标按钮),如果你慢慢滚动它,它就会开始过渡到某种颜色,并且标题会淡入。在特定的偏移量之后,过渡应该完成。

我尝试将普通的应用程序栏小部件与滚动控制器结合使用,但遇到了一些错误。也许是因为我想在无状态小部件中实现它。

flutter flutter-animation flutter-appbar
1个回答
0
投票

我不知道如何拖动appbar,直到ChatGpt教我。 我不太清楚你想要什么,但我做了一个可能有帮助的例子。 如果足以解决您的问题,请将我设为最佳答案。`

import 'package:flutter/material.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      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> {
  

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return const Scaffold(
      
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            TopWidget(child: DraggableAppBar())
          ],
        ),
      ),
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
class TopWidget extends StatelessWidget {
  final Widget child;
  const TopWidget({required  this.child, super.key});

  @override
  Widget build(BuildContext context) {
    return  Container(
      color: Colors.grey,
      width: double.infinity,
      height: 300,
      child: child,
      
    );
  }
}

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

  @override
  State<DraggableAppBar> createState() => _DraggableAppBarState();
}
double appBarheight=60;
class _DraggableAppBarState extends State<DraggableAppBar> {
  double top = 0;
  

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned(
          height: appBarheight,
          left: 0,
          top: top,
          child: Draggable(
            onDragUpdate: (details) {
              setState(() {
                top = top + details.delta.dy;
                if(top>300-appBarheight){
                  top=300-appBarheight;
                }
                if(top<0){
                  top=0;
                }
              });
            },
            feedback: Container(),
            
            childWhenDragging: CustomAppBar(top: top),
            child:const CustomAppBar(top: 0,),
          ),
          
        ),
      ],
    );
  }
}

class CustomAppBar extends StatelessWidget {
  final double top;
  final String text='Drag me';
  const CustomAppBar({required this.top,super.key});
  Color colorFromTop(double top) {
    // Clamp the value of top between 0 and 240
    double normalizedTop = top.clamp(0.0, 240.0);

    // Convert the top value to a value between 0.0 and 1.0
    double t = normalizedTop / 240.0;

    // Use Color.lerp to interpolate between black and white based on t
    return Color.lerp(Colors.black, Colors.white, t)!;
  }

  @override
  Widget build(BuildContext context) {
    print(top);
    double width = MediaQuery.of(context).size.width;

    return  Container(
      decoration: BoxDecoration(color: colorFromTop(top)),
      height: appBarheight,
      width: width,
      child: Text(text,style:const TextStyle(color: Colors.black),),
    );
  }
}```
© www.soinside.com 2019 - 2024. All rights reserved.