首页 > 其他分享 >flutter 效果实现 —— 组件自由移动与大小调整

flutter 效果实现 —— 组件自由移动与大小调整

时间:2022-09-29 09:48:15浏览次数:45  
标签:final color height width key child 组件 移动 flutter

示例:

class DynamicBoxPage extends StatelessWidget {
  const DynamicBoxPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          backgroundColor: Colors.grey,
          body: Center(
            child: DynamicBox(
              width: 200,
              height: 100,
              color: Colors.white,
            ),
          )),
    );
  }
}

class DynamicBox extends StatelessWidget {
  const DynamicBox({Key? key, this.width, this.height, this.color}) : super(key: key);

  final double? width;
  final double? height;
  final Color? color;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return DynamicRectBox(
        width: min(width ?? double.infinity, constraints.maxWidth),
        height: min(height ?? double.infinity, constraints.maxHeight),
        color: color,
      );
    });
  }
}

class DynamicRectBox extends StatefulWidget {
  const DynamicRectBox({Key? key, required this.width, required this.height, this.color}) : super(key: key);

  final double width;
  final double height;

  final Color? color;

  @override
  State<DynamicRectBox> createState() => _DynamicRectBoxState();
}

class _DynamicRectBoxState extends State<DynamicRectBox> {
  bool _isHover = false;
  bool _isFocus = false;

  final FocusNode focusNode = FocusNode();

  Offset? _globalPos;

  Offset _localPos = Offset(0, 0);

  late double width;
  late double height;

  @override
  void initState() {
    super.initState();
    width = widget.width;
    height = widget.height;
  }

  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context);
    return Stack(
      children: [
        Positioned(
          left: _globalPos?.dx,
          top: _globalPos?.dy,
          child: GestureDetector(
            behavior: HitTestBehavior.translucent,
            onTap: () {
              focusNode.requestFocus();
            },
            onPanDown: (DragDownDetails details) {
              setState(() {
                _localPos = details.localPosition;
                _globalPos = details.globalPosition - _localPos;
              });
            },
            onPanUpdate: (DragUpdateDetails details) {
              if (_isFocus) {
                setState(() {
                  _globalPos = details.globalPosition - _localPos;
                });
              }
            },
            onPanEnd: (DragEndDetails details) {
              setState(() {
                _localPos = Offset(0, 0);
              });
            },
            child: Focus(
              focusNode: focusNode,
              onFocusChange: (focus) {
                setState(() {
                  _isFocus = focus;
                });
              },
              child: MouseRegion(
                onEnter: (event) {
                  if (!_isFocus) {
                    setState(() {
                      _isHover = true;
                    });
                  }
                },
                onExit: (event) {
                  setState(() {
                    _isHover = false;
                  });
                },
                onHover: (event) {
                  if (_isFocus) {
                    //根据所在位置坐标,按住后执行不同的操作(水平、垂直、斜拉伸)
                  }
                },
                child: Stack(
                  clipBehavior: Clip.none,
                  children: [
                    Container(
                      width: width,
                      height: height,
                      decoration: BoxDecoration(
                        color: widget.color,
                        border: (_isFocus || _isHover)
                            ? Border.all(
                                color: themeData.primaryColor,
                                width: 2,
                                strokeAlign: StrokeAlign.outside,
                              )
                            : null,
                      ),
                    ),
                    if (_isFocus) ...[
                      Positioned.fill(
                        top: -4,
                        left: -4,
                        child: Align(
                          alignment: Alignment.topLeft,
                          child: RectBoxCorner(),
                        ),
                      ),
                      Positioned.fill(
                        top: -4,
                        right: -4,
                        child: Align(
                          alignment: Alignment.topRight,
                          child: RectBoxCorner(),
                        ),
                      ),
                      Positioned.fill(
                        left: -4,
                        bottom: -4,
                        child: Align(
                          alignment: Alignment.bottomLeft,
                          child: RectBoxCorner(),
                        ),
                      ),
                      Positioned.fill(
                        right: -4,
                        bottom: -4,
                        child: Align(
                          alignment: Alignment.bottomRight,
                          child: RectBoxCorner(),
                        ),
                      ),
                    ]
                  ],
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class RectBoxCorner extends StatelessWidget {
  const RectBoxCorner({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context);
    return MouseRegion(
      //没有旋转的符号
      // cursor: SystemMouseCursors.rotate,
      child: GestureDetector(
        child: Container(
          width: 6,
          height: 6,
          decoration: BoxDecoration(
            color: Colors.white,
            border: Border.all(
              color: themeData.primaryColor,
              width: 2,
              strokeAlign: StrokeAlign.outside,
            ),
          ),
        ),
      ),
    );
  }
}

标签:final,color,height,width,key,child,组件,移动,flutter
From: https://www.cnblogs.com/lemos/p/16709672.html

相关文章

  • 遇到一个bug,组件不更新内容
    解决办法当v-if的值发生变化时,组件都会被重新渲染一遍。因此,利用v-if指令的特性,可以达到强制刷新组件的目的。<template><compv-if="update"></comp><button......
  • 【element UI】el-cascader 组件使用过程踩坑记录
    前言项目中使用到el-cascader组件,记录下遇到的一些问题以及解决方法,方便后续回顾查看。样式问题我是使用按需引入的elementUI,当使用到el-cascader组件时,下拉框里......
  • vue动态组件tab切换
     先弄3个tab组件,再导入 可以使用<component:is="activetab">那个,也可以使用下面注释的那个,二选一    选择TabA       第二部分如何切换之......
  • 鼠标自动移动
    importjava.awt.*;importjava.util.Random;publicclassMouse{publicstaticfinalintMILLISECOND=1;publicstaticfinalintSECOND=1000;......
  • Vue 组件间的通信方式
    前言在Vue组件库的开发过程中,组件之间的通信一直是一个重要的课题。虽然官方的Vuex状态管理方案可以很好的解决组件之间的通信问题,但是组件库内部对Vuex的使用往往比较繁重......
  • C++11:移动语义
    为什么需要移动语义#include<iostream>usingnamespacestd;classTest{public:Test(inta=0){//普通构造函数d=newint(a);cout<<"构造函......
  • Flutter中使用flutter_swiper实现轮播图
    1.安装插件配置flutter_swiper插件#配置轮播图插件flutter_swiper:^1.1.6在pubspec.yaml中配置保存后,在VSCode环境中会自动下载依赖包。如果无法正常下载,执......
  • ams启动组件时创建新进程的流程
    ams启动组件时创建新进程的流程activity~broadcast~service~provider->ProcessList.java->startProcessLocked("android.app.ActivityThread")AppZygote.getProcess().star......
  • 移动端touch拖动事件和click事件冲突问题解决
    通过一个悬浮球交互功能的案例来阐述问题,以及解决办法。实现效果类似微信里的悬浮窗效果,苹果手机的悬浮球功能效果可以点击拖动,然后吸附在窗口边缘点击悬浮球,可......
  • 13.javaweb三大组件
    ......