• flutter悬浮按钮案例


    能滑动隐藏的悬浮按钮

    https://www.jianshu.com/p/18f6f6a532ec

    Flutter 可随意拖动按钮

    https://www.jianshu.com/p/167ddc5660dc

    flutter 滚动隐藏悬浮按钮

     
    Untitled.gif
    • 实现思路,当开始滚动的时候,执行动画让中间的悬浮按钮向右移动。当滚动结束的时候复位动画

    监听滚动的方法有两种

    第一种 NotificationListener 在widget树中,子widget滚动时会向上发送notification,通过NotificationListener可以监控到该notification。NotificationListener也是一个widget,可以将被监控的widget放入其child内。
    NotificationListener
    const NotificationListener({
        Key key,
        @required this.child,  被监控的子widget树
        this.onNotification,  监控到notification后的回调方法。
      }) 
    

    onNotification(ScrollNotification notification) , 此方法需要一个返回值,表示是否拦截住notification,如果是true,那么notifcation到此为止;如果是false,那么notification会继续向更外层widget传递。参数ScrollNotification包含了监听到的信息。
    ScrollNotification

    ScrollNotification({
        @required this.metrics,   所有信息都在这里存储 ScrollMetrics
        @required this.context,
      });
    
    第二种是通过ScrollController来监听

    ScrollController 常用方法

    • addListener 滑动监听方法,在initState中监听
    • _scrollController.position.pixels 滑动距离
    • _scrollController.offset 滚动的偏移量
    • _scrollController.position.maxScrollExtent 最大可滑动距离,滑动组件内容长度
    • -_scrollController.position.minScrollExtent 最小可滑动距离,0
    • _scrollController.position.viewportDimension 滑动视图所占长度
    • _scrollController.dispose() 销毁监听,在dispose方法中调用
    • _scrollController.jumpTo 控制滑动组件的滑动距离,无动画
    • _scrollController.animateTo(10); 控制滑动组件的滑动距离,有动画
    • _scrollController.position.jumpTo 同上
    • _scrollController.position.animateTo 同上
      controller.addListener((){
          print(controller......)
       });
    

    下面我们开始实现我们的效果

    第一步

    我们使用Scaffold floatingActionButton 来添加我们widget ,配合 floatingActionButtonLocation 设置下位置,

    Scaffold(
         appBar: PreferredSize(
           child: _getAppBar(),
           preferredSize: Size(double.infinity,44),
         ),
         backgroundColor: Colors.white,
         floatingActionButton: AnimationWidget(),
         floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
         body: ...,
    
       );
    

    创建悬浮按钮 AnimationWidget

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    //状态管理
    class NotifierAnimation extends ChangeNotifier{
    //回调方法
     ValueChanged stopValueChanged;
     void animationStartAndEnd(isStop){
       stopValueChanged(isStop);
       notifyListeners();
     }
    }
    
    class AnimationWidget extends StatefulWidget {
     @override
     _AnimationWidgetState createState() => _AnimationWidgetState();
    }
    
    class _AnimationWidgetState extends State<AnimationWidget> with SingleTickerProviderStateMixin{
     AnimationController _animationController;
     Animation<Offset> _animation;
     @override
     void initState() {
       super.initState();
       //实例化动画
       _animationController = new AnimationController(vsync: this,duration: new Duration(milliseconds: 240));
       _animation = Tween(begin: Offset(0,0), end: Offset(0.8, 0)).animate(_animationController);
     }
    
     @override
     void didChangeDependencies() {
       //Provider 状态管理 得到回调如果true 那就是开始动画
       final counter = Provider.of<NotifierAnimation>(context);
       if (counter !=null) {
         Provider.of<NotifierAnimation>(context,listen: false).stopValueChanged=((v){
           if(v){
             //开始动画
             _animationController.forward();
           }else{
             //复位动画
             _animationController.reverse();
    
           }
         });
       }
    
     }
     @override
     Widget build(BuildContext context) {
       return Align(
         alignment: Alignment.centerRight,
         child: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           children: <Widget>[
             SizedBox(height: 100),
             SlideTransition(
               child: Container(
                 width: 50,
                 height: 50,
                 decoration: BoxDecoration(
                     color: Colors.red
                 ),
               ),position: _animation,),
           ],
         )
       );
     }
    }
    
    

    这么这里使用到的是NotificationListener,因为ScrollController不能得到什么时候开始滚动什么时候结束滚动,
    第二步 创建 NotificationListener child就是你的滚动视图 可以是 ListView CustomScrollView,也可以包裹 三方插件 SmartRefresher

    NotificationListener<ScrollNotification>(
          onNotification: (notification){
            if( notification.depth == 0){
              switch (notification.runtimeType){
                case ScrollStartNotification:{
                  //开始滚动 执行动画
                    Provider.of<NotifierAnimation>(context,listen: false).animationStartAndEnd(true);
                }
                break;
                case ScrollUpdateNotification: print("正在滚动") ; break;
                case ScrollEndNotification:{
                  print("滚动停止");
                  //滚动停止 结束动画 复位
                  Provider.of<NotifierAnimation>(context,listen: false).animationStartAndEnd(false);
    
                } break;
                case OverscrollNotification: print("滚动到边界"); break;
              }
            }
            return;
          },
          child: ListView()
        );
    
    我们这里通过三方插件Provider状态共享来执行动画 ,当然了你也可以使用其他方法,无非就是一个回调,调用我们封装好的widget 来执行动画

    Main

    //Provider
    void main() {
      NotifierAnimation notifierAnimation = NotifierAnimation();
        runApp(MultiProvider(
          providers: [
            ChangeNotifierProvider.value(value: notifierAnimation),
    
          ],
          child: MyApp(),
        ));
    }


    作者:Faith_K
    链接:https://www.jianshu.com/p/18f6f6a532ec
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    Flutter 可随意拖动按钮

    停心阁
    0.0752020.03.31 13:38:55字数 36阅读 186

    实现这个功能主要用到了Stack、Positioned、Draggable等几个组件
    直接上代码:

    1.main.dart文件

    import 'package:flutter/material.dart';
    import 'FloatBtn.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: FloatBtn(),
        );
      }
    }
    
    1. FloatBtn.dart 文件
    import 'package:flutter/material.dart';
    
    class FloatBtn extends StatefulWidget {
      FloatBtn({Key key}) : super(key: key);
    
      @override
      _FloatBtnState createState() => _FloatBtnState();
    }
    
    class _FloatBtnState extends State<FloatBtn> {
      
      Offset offsetA = Offset(20, kToolbarHeight + 100);//按钮的初始位置
      
      @override
      Widget build(BuildContext context) {
    
        final size = MediaQuery.of(context).size;
        final width = size.width;
        final height = size.height;
    
        return Scaffold(
           body: Stack(
             children:<Widget>[
              Positioned(
                left: offsetA.dx,
                top: offsetA.dy,
                child: Draggable(
                    //创建可以被拖动的Widget
                    child:  FloatingActionButton(
                      tooltip: 'Increment',
                      child: Icon(Icons.add), onPressed: () {},
                    ),
                    //拖动过程中的Widget
                    feedback: FloatingActionButton(
                      tooltip: 'Increment',
                      child: Icon(Icons.add), onPressed: () {},
                    ),
                    //拖动过程中,在原来位置停留的Widget,设定这个可以保留原本位置的残影,如果不需要可以直接设置为Container()
                    childWhenDragging: Container(),
                    
                    // FloatingActionButton(
                    //   tooltip: 'Increment',
                    //   child: Icon(Icons.add), onPressed: () {},
                    // ),
                    //拖动结束后的Widget
                    onDraggableCanceled: (Velocity velocity, Offset offset) {
                      // 计算组件可移动范围  更新位置信息
                      setState(() {
                        var x = offset.dx;
                        var y = offset.dy;
                        if(offset.dx<0){
                          x = 20;
                        }
    
                        if(offset.dx>375){
                          x = 335;
                        }
    
                        if(offset.dy<kBottomNavigationBarHeight){
                          y = kBottomNavigationBarHeight;
                        }
    
                        if(offset.dy>height-100){
                          y = height - 100;
                        }
    
                        offsetA = Offset(x, y);
                      });
    
                    }
                  )
              )
             ]
           ),
        );
      }
    }
  • 相关阅读:
    OC面向对象—封装
    OC面向对象—继承
    hdu 4612 Warm up(缩点+树上最长链)
    hdu 4604 Deque(最长不下降子序列)
    hdu 4607 Park Visit(树上最长链)
    hdu 4609 3-idiots(快速傅里叶FFT)
    codeforces 333B
    codeforces 333A
    codeforces 334B
    codeforces 334A
  • 原文地址:https://www.cnblogs.com/sundaysandroid/p/13524713.html
Copyright © 2020-2023  润新知