簡體   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