首页 > 其他 > 详细

flutter悬浮按钮案例

时间:2020-08-18 18:07:35      阅读:250      评论:0      收藏:0      [点我收藏+]

能滑动隐藏的悬浮按钮

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

                }
              )
          )
         ]
       ),
    );
  }
}

 

flutter悬浮按钮案例

原文:https://www.cnblogs.com/sundaysandroid/p/13524713.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!