LastMonopoly / scaled_app

Scale the entire UI design proportionally, useful when your UI design is fixed-width.
https://pub.dev/packages/scaled_app
BSD 3-Clause "New" or "Revised" License
14 stars 8 forks source link

Wrong behavior when used with hostElement and selectable items #6

Open fhuonder opened 1 year ago

fhuonder commented 1 year ago

Hi,

I have found another issue regarding this lib with hostElement. When there are selectable elements on the screen the whole app screen moves out of the view.

Reproduce:

Create a new project with flutter create Then add your library to the pubspec. Then change the index.html code to:

<!DOCTYPE html>
<html>

<head>
  <!--
    If you are serving your web app in a path other than the root, change the
    href value below to reflect the base path you are serving from.

    The path provided below has to start and end with a slash "/" in order for
    it to work correctly.

    For more details:
    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

    This is a placeholder for base href that will be replaced by the value of
    the `--base-href` argument provided to `flutter build`.
  -->
  <base href="$FLUTTER_BASE_HREF">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A new Flutter project.">

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="test">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="favicon.png" />

  <title>test</title>
  <link rel="manifest" href="manifest.json">

  <script>
    // The value below is injected by flutter build, do not touch.
    var serviceWorkerVersion = null;
  </script>
  <!-- This script adds the flutter initialization JS code -->
  <script src="flutter.js" defer></script>
</head>

<body>
  <div id="flutter_host"
    style="background-color: yellow; width: 300px; height: 300px; position: absolute; left: calc(50% - 150px);">
  </div>
  <script>
    window.addEventListener('load', function (ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function (engineInitializer) {
          engineInitializer.initializeEngine({
            hostElement: document.querySelector("#flutter_host")
          }
          ).then(function (appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
  </script>
</body>

</html>

and change the main.dart code to:

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:scaled_app/scaled_app.dart';

void main() {
  ScaledWidgetsFlutterBinding.ensureInitialized(scaleFactor: (_) => 0.6);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    MediaQueryData md = MediaQuery.of(context);
    return MediaQuery(
        data: md.scale(),
        child: MaterialApp(
          title: 'Flutter Demo',
          scrollBehavior: const MaterialScrollBehavior()
              .copyWith(dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch, PointerDeviceKind.stylus, PointerDeviceKind.unknown}),
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        ));
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: BottomAppBar(child: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.plus_one))),
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: SingleChildScrollView(
            child: Form(
                child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            ListTile(
                leading: const Icon(Icons.phone),
                title: TextFormField(
                    onChanged: (_) {}, decoration: const InputDecoration(label: Text("Test")), autovalidateMode: AutovalidateMode.onUserInteraction))
          ],
        ))),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Here a video that demonstrates the behavior https://github.com/LastMonopoly/scaled_app/assets/39723648/a86458c2-f349-461f-ad67-c359a2d6959d

Would be great if you could make a fix as soon as possible. I am really stuck with this. Or do you have a workaround? (iFrame is not an option)

Regards, Florian

fhuonder commented 1 year ago

@elMuso You have almost the same code in your fork. Do you have an idea or fix?

flodaniel commented 2 weeks ago

I just stumbled across this very same issue. @fhuonder did you find a workaround/solution? We use the new flutter 3.22 web style:

<body>
  <div id="app-container">
    <script src="flutter_bootstrap.js" async></script>
  </div> 
</body>