Flutter -可拖动和缩放小部件

r7knjye2  于 2022-12-14  发布在  Flutter
关注(0)|答案(2)|浏览(137)

bounty将在2天后过期。回答此问题可获得+50声望奖励。Lara希望吸引更多人关注此问题。

因此,对于此应用程序(Windows、Web),我有两个要求:
1.用户可以在屏幕上拖动控件(拖放)到任何位置。
1.应用程序必须缩放到屏幕/窗口大小
对于(1),我使用了this answer。对于(2),我使用了this solution
正如下面的代码注解中所提到的,我不能同时拥有这两种功能:
如果我根据窗口大小动态设置logicWidthlogicHeight,拖动工作正常,但可拖动的小部件不会缩放,而是保持相同的大小,而不管窗口大小。
如果我将logicWidthlogicHeight设置为一个常量值(当前cleanHeight的值),对于其他屏幕大小,拖动将变得混乱,但可拖动的小部件将随着窗口大小正确缩放。
换句话说就是:为了使拖动效果更好,这些值需要在任何时候都与窗口大小相匹配。2但是通过改变这些值,我破坏了我所需要的缩放。

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],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}
xqkwcwgp

xqkwcwgp1#

我有一个类似的问题,而不是从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,
                    ),
                )
            )
        );
    }
);
2w3rbyxf

2w3rbyxf2#

一种方法是将draggableWidget Package 在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)
              ],
            ),
          ),
        );
      },
    ),

相关问题