skip to Main Content

So for this application (Windows, Web) I have 2 requirements:

  1. User can drag around widgets on the screen (drag and drop) to any location.
  2. The app must scale to screen/window size

For (1) I used this answer.
For (2) I used this solution.

As mentioned in the code comment below I can’t have both:

If I set logicWidth and logicHeight dynamically depending on the window size, the dragging works fine but the draggable widgets won’t scale but instead stay the same size regardless of the window size.

If I set logicWidth and logicHeight to a constant value (the value of the current cleanHeight ) the dragging will be messed up for other screen sizes but then the draggable widgets will scale correctly with the window size.

In other words: for the dragging to work nicely these values need to be matching the window size at any time. But by changing these values I ruin the scaling I need.

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

3

Answers


  1. Chosen as BEST ANSWER

    One way of doing it is wrapping the draggableWidget in a Transform widget and set the scale factor in relation to the dimensions:

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

  2. I had a similar issue, instead of getting the height from the MediaQuery get it from the LayoutBuilder, I noticed it is working much better when resizing the window.

    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,
                        ),
                    )
                )
            );
        }
    );
    
    Login or Signup to reply.
  3. Another way of achieving this:
    To drag around widgets on the screen (drag and drop) to any location.

    And to scale screen/window size.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search