繁体   English   中英

Flutter - 可拖动和缩放的小部件

[英]Flutter - Draggable AND Scaling Widgets

所以对于这个应用程序(Windows,Web)我有两个要求:

  1. 用户可以将屏幕上的小部件拖动(拖放)到任何位置。
  2. 该应用程序必须缩放到屏幕/窗口大小

对于 (1) 我使用了这个答案 对于 (2) 我使用了这个解决方案

正如下面的代码注释中提到的,我不能同时拥有:

如果我根据窗口大小动态设置logicWidthlogicHeight ,则拖动工作正常,但可拖动的小部件不会缩放,而是保持相同的大小,而不管窗口大小如何。

如果我将logicWidthlogicHeight设置为一个常量值(当前cleanHeight的值),对于其他屏幕尺寸,拖动将被弄乱,但可拖动的小部件将随窗口尺寸正确缩放。

换句话说:为了使拖动能够很好地工作,这些值需要随时与窗口大小相匹配。 但是通过更改这些值,我破坏了我需要的缩放比例。

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:matrix_gesture_detector/matrix_gesture_detector.dart';

//containing widgets to drag around
const List<Widget> draggableWidgets = [
  DraggableWidget(
      draggableWidget: CircleAvatar(
    backgroundColor: Colors.green,
    radius: 32,
  )),
  DraggableWidget(
      draggableWidget: CircleAvatar(
    backgroundColor: Colors.red,
    radius: 24,
  )),
];

class FrontPageWidget extends ConsumerWidget {
  const FrontPageWidget({Key? key}) : super(key: key);
  static const routeName = '/frontPage';

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    //screen height and padding
    final height = MediaQuery.of(context).size.height;
    final padding = MediaQuery.of(context).viewPadding;
    // Height (without status and toolbar)
    final cleanHeight = height - padding.top - kToolbarHeight;

    //either make those values dynamic (cleanHeight updates depending on screen size / window size) OR constant (961px is the cleanHeight on full screen)
    //if values are dynamic => the draggable widgets not scaling to screen size BUT dragging works fine
    //if values are constant => the draggable widgets do scale to screen size BUT dragging is messed
    final logicWidth = cleanHeight; //961
    final logicHeight = cleanHeight; //961

    return Scaffold(
      appBar: AppBar(
        title: const Text('Main Page'),
      ),
      body: SizedBox.expand(
          child: FittedBox(
              fit: BoxFit.contain,
              alignment: Alignment.center,
              child: Container(
                color: Colors.grey,
                width: logicWidth,
                height: logicHeight,
                child: Stack(
                  children: draggableWidgets,
                ),
              ))),
    );
  }
}

class DraggableWidget extends StatelessWidget {
  final Widget draggableWidget;
  const DraggableWidget({Key? key, required this.draggableWidget})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    final ValueNotifier<Matrix4> notifier = ValueNotifier(Matrix4.identity());
    return Center(
      child: MatrixGestureDetector(
        onMatrixUpdate: (m, tm, sm, rm) {
          notifier.value = m;
        },
        child: AnimatedBuilder(
          animation: notifier,
          builder: (ctx, child) {
            return Transform(
              transform: notifier.value,
              child: Center(
                child: Stack(
                  children: [draggableWidget],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

一种方法是将draggableWidget包装在Transform小部件中,并设置与尺寸相关的scale因子:

   child: AnimatedBuilder(
      animation: notifier,
      builder: (ctx, child) {
        final height = MediaQuery.of(context).size.height;
        return Transform(
          transform: notifier.value,
          child: Center(
            child: Stack(
              children: [
                Transform.scale(
                    scale: height / 1000,
                    child: draggableWidget)
              ],
            ),
          ),
        );
      },
    ),

我有一个类似的问题,而不是从 MediaQuery 获取高度,而是从 LayoutBuilder 获取高度,我注意到它在调整窗口大小时工作得更好。

body: LayoutBuilder(
    builder: (context, constraints) {
        return SizedBox.expand(
            child: FittedBox(
                fit: BoxFit.contain,
                alignment: Alignment.center,
                child: Container(
                    color: Colors.grey,
                    width: constraints.maxWidth,
                    height: constraints.maxHeight,
                    child: Stack(
                        children: draggableWidgets,
                    ),
                )
            )
        );
    }
);

实现这一目标的另一种方法:
将屏幕上的小部件拖动(拖放)到任何位置。

并缩放屏幕/窗口大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM