• flutter显示出底部控件的引导页


    需求:同一个页面的两个不同的入口,同一个控件的位置有变化,显示引导页时对应这个控件的引导内容的位置也需要改变;同时半透明底部显示出真实的页面内容。
    这样的需要如果切图然后再往页面上贴位置无法精确的对准。
    思路:先绘制一层半透明遮罩覆盖页面,在需要显示的控件位置绘制为全透明,然后再将引导内容绘制在遮罩上面(共有三层,真实页面、透明遮罩。控件对应的那些说明内容),获取控件的位置确定在哪里全透明。

    入口一进入时:
    在这里插入图片描述
    入口二进入时:
    在这里插入图片描述

    import 'package:common/sp_util.dart';
    import 'package:jade/configs/CommonConfig.dart';
    import 'package:jade/configs/PathConfig.dart';
    import 'package:jade/utils/JadeColors.dart';
    import 'package/jade/utils/Utils.dart';
    import 'package:util/navigator_util.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_screenutil/flutter_screenutil.dart';
    /*
    * 引导页
    * */
    class SharedPurchaseGuidePage extends StatelessWidget {
      final double width;
      final double height;
      final Offset offset;
      const SharedPurchaseGuidePage({this.width,this.height,this.offset});
    
      
      Widget build(BuildContext context) {
        return WillPopScope(
          child: Stack(
            children: [
              CustomPaint(
                size: Size(Utils().screenWidth(context), Utils().screenHeight(context)), // 自定义Widget的大小
                painter: MyCustomPainter(width,height,offset),
              ),
              Positioned(
                  left: offset.dx + width,
                  top: offset.dy,
                  child: _leftView(context))
            ],
          ),
          onWillPop: () async => false,);
      }
    
      _leftView(context){
        return Container(
          width: Utils().screenWidth(context) * 0.68,
          height: 210.w,
          padding: EdgeInsets.symmetric(vertical: 28.w),
          decoration: BoxDecoration(
              image: DecorationImage(
                  image: AssetImage(PathConfig.imageSharedPurchaseGuideBg),
                  fit: BoxFit.fill)
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Text('点击了解共享购',style: TextStyle(color: Colors.white,fontSize: 28.sp,fontWeight: FontWeight.w600)),
                  SizedBox(width: 54.w),
                  GestureDetector(
                    child: Container(
                      width: 100.w,
                      height: 40.w,
                      alignment: Alignment.center,
                      margin: EdgeInsets.only(right: 20.w),
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: Text('知道了',style: TextStyle(color: JadeColors.blue,fontSize: 22.sp,fontWeight: FontWeight.w600),),
                    ),
                    onTap: (){
                      SpUtil.putBool(CommonConfig.havePostDetailSharedPurchaseGuide, true);
                      NavigatorUtil.pop();
                    },
                  )
                ],
              ),
              Container(
                margin: EdgeInsets.only(right: 20.w,top: 26.w),
                child: Text('为促进交易,本版块加入了独特的共\n享购功能,与传统的团购与拼单很不\n一样,欢迎体验!',style: TextStyle(color: Colors.white,fontSize: 22.sp))
              )
            ],
          ),
        );
      }
    }
    
    class MyCustomPainter extends CustomPainter {
      final double width;
      final double height;
      final Offset offset;
      const MyCustomPainter(this.width,this.height,this.offset);
      
      void paint(Canvas canvas, Size size) {
        //背景
        Paint backgroundPaint = Paint()
          ..color = Colors.black45
          ..style = PaintingStyle.fill;
    
        //添加背景一个路径
        Path path = Path()
          ..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
    
    
        //留白的圆角矩形路径
        Path holePath = Path()
         // ..addRect(Rect.fromLTWH(offset.dx, offset.dy, width, height));
          ..addRRect(RRect.fromRectAndRadius(Rect.fromLTWH(offset.dx-5, offset.dy, width+5, height), Radius.circular(5)));
    
        Path combinedPath = Path.combine(PathOperation.difference, path, holePath);
        canvas.drawPath(combinedPath, backgroundPaint);
    
      }
    
      
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        return false; // 不需要重绘,因为我们只是绘制一次,并没有动画或状态更改
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    GlobalKey _sharedPurchaseKey = new GlobalKey();
    //需要全透明的控件
    Row(
                      key: _sharedPurchaseKey,
                      children: [
                        Text(S.current.sharedPurchase,style: TextStyle(color: JadeColors.blue,fontSize: 24.sp,fontWeight: FontWeight.bold)),
                        GestureDetector(
                          child: Container(
                            color: Colors.transparent,
                            padding: EdgeInsets.all(4),
                            child: Image.asset(PathConfig.iconQuestion,width: 34.w,height: 34.w),
                          ),
                          onTap: (){
                            NavigatorUtil.push(SharedPurchaseDesc());
                          },
                        ),
                      ],
                    ),
    
    //获取共享购文字加问号的坐标,跳转(这个方法需要在页面加载完成后调用)
      _getOffset() {
        if(_sharedPurchaseKey.currentContext != null){
          _sharedPurchaseWidth = _sharedPurchaseKey.currentContext.size.width;
          _sharedPurchaseHeight = _sharedPurchaseKey.currentContext.size.height;
          _offset = WidgetUtil.getWidgetLocalToGlobal(_sharedPurchaseKey.currentContext);
          bool sharedPurchaseGuide = SpUtil.getBool(CommonConfig.havePostDetailSharedPurchaseGuide,defValue: false);
          if(!sharedPurchaseGuide){
          //跳转一个透明页面
            NavigatorUtil.pushTransparentRoute(SharedPurchaseGuidePage(width: _sharedPurchaseWidth,height: _sharedPurchaseHeight,offset: _offset));
          }
        }
      }
      
     ///Get the coordinates of the widget on the screen.Widgets must be rendered completely.
      ///获取widget在屏幕上的坐标,widget必须渲染完成
      static Offset getWidgetLocalToGlobal(BuildContext context) {
        RenderBox box = context.findRenderObject();
        return box == null ? Offset.zero : box.localToGlobal(Offset.zero);
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    酷开科技丨酷开系统——智能家居生活的娱乐核心
    SpringMVC-RESTful快速开发及案例:基于RESTful页面数据交互
    使用hutool工具发送带附件的邮件(特简单)
    RK3568平台 IIC子系统框架
    ubuntu篇---ubuntu安装mysql教程
    基于tkwinter制作的exe小工具
    F3L600R10W4S7FC22BPSA1 EasyPACK IGBT模块 950V(F3L600R10W4S7FC22)
    Java面试题总结16之分布式id生成方案
    nothing to repeat at position 0(解决方案)
    删除链表的倒数第n个节点的最优算法实现
  • 原文地址:https://blog.csdn.net/androidhyf/article/details/134241851