flutter_overlay_window icon indicating copy to clipboard operation
flutter_overlay_window copied to clipboard

Values in resizeOverlay not coherent with values in showOverlay

Open jglatre opened this issue 1 year ago • 5 comments

I'm showing an overlay with parameters width: 500, height: 200 without any issue, then I try to double the height doing FlutterOverlayWindow.resizeOverlay(500, 400) and the window grows far too much, both in width and height. I've been trying with other values, trying to guess some correlation but to no avail, it seems like the two methods accept different units.

jglatre avatar Aug 25 '23 08:08 jglatre

Looking source code of OverlayService I see you are applying dpToPx to parameters of resizeOverlay buy not applying it to parameters of showOverlay. I hope that will be a hint.

jglatre avatar Aug 25 '23 09:08 jglatre

The initial width/height does not take in to account the display metrics whilst resizeOverlay does. A workaround is to apply the display metrics yourself when setting the initial width/height by multiplying your desired size by MediaQuery.devicePixelRatioOf(context). The result is not exactly identical as there seems to be a rounding difference but it should be within 1px.

EDIT: The rounding difference is avoidable. The resizeOverlay method applies the display metrics and then truncates (drops the decimal) the resulting width/height since it needs to be specified as an int. My setting of the initial width/height was rounding up to make sure I have at least as much space as I ask for. Two options to get a more consistent size:

  1. When applying the device pixel ratio to the original width/height, round down. This can result in a slightly lower size than desired.
  2. When calling resizeOverlay we can round up the width/height so that when it is multiplied by the device pixel ratio and then truncated it will be at least as large as our desired width/height. Unfortunately since the arguments to resizeOverlay are ints we cannot totally avoid unnecessary rounding up (without modifying the package). Here is an example method:
  static Future<bool?> resizeOverlay(BuildContext context, Size size) {
    final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);

    final adjustedWidth =
        (((size.width * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();
    final adjustedHeight =
        (((size.height * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();

    return FlutterOverlayWindow.resizeOverlay(adjustedWidth, adjustedHeight);
  }

rorystephenson avatar Mar 07 '24 08:03 rorystephenson

Why was resizeOverlay written that way, seems unnecessary to me. Can someone explain pls?

Ahmadu-Suleiman avatar Jul 15 '24 12:07 Ahmadu-Suleiman

The initial width/height does not take in to account the display metrics whilst resizeOverlay does. A workaround is to apply the display metrics yourself when setting the initial width/height by multiplying your desired size by MediaQuery.devicePixelRatioOf(context). The result is not exactly identical as there seems to be a rounding difference but it should be within 1px.

EDIT: The rounding difference is avoidable. The resizeOverlay method applies the display metrics and then truncates (drops the decimal) the resulting width/height since it needs to be specified as an int. My setting of the initial width/height was rounding up to make sure I have at least as much space as I ask for. Two options to get a more consistent size:

  1. When applying the device pixel ratio to the original width/height, round down. This can result in a slightly lower size than desired.
  2. When calling resizeOverlay we can round up the width/height so that when it is multiplied by the device pixel ratio and then truncated it will be at least as large as our desired width/height. Unfortunately since the arguments to resizeOverlay are ints we cannot totally avoid unnecessary rounding up (without modifying the package). Here is an example method:
  static Future<bool?> resizeOverlay(BuildContext context, Size size) {
    final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);

    final adjustedWidth =
        (((size.width * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();
    final adjustedHeight =
        (((size.height * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();

    return FlutterOverlayWindow.resizeOverlay(adjustedWidth, adjustedHeight);
  }

I have the similar issue with this. " await FlutterOverlayWindow.showOverlay( enableDrag: true, overlayTitle: "来电显示", overlayContent: "name:${callerIdData.phoneNumber},region:${callerIdData.countryName},carrier:${callerIdData.carrier}", alignment: OverlayAlignment.center, flag: OverlayFlag.defaultFlag, visibility: overlay.NotificationVisibility.visibilityPublic, positionGravity: PositionGravity.auto, height: (styleProvider.windowHeight * (pixelRatio ?? 3.0)) .toInt(), // 使用 styleProvider.windowHeight width: (styleProvider.windowWidth * (pixelRatio ?? 3.0)).toInt()," i have to use "PixelRatio = MediaQuery.of(context).devicePixelRatio" other wise It will be 1/3 than its real size, I don't know what is the issue with this

haygcao avatar Sep 04 '24 12:09 haygcao

The initial width/height does not take in to account the display metrics whilst resizeOverlay does. A workaround is to apply the display metrics yourself when setting the initial width/height by multiplying your desired size by MediaQuery.devicePixelRatioOf(context). The result is not exactly identical as there seems to be a rounding difference but it should be within 1px. EDIT: The rounding difference is avoidable. The resizeOverlay method applies the display metrics and then truncates (drops the decimal) the resulting width/height since it needs to be specified as an int. My setting of the initial width/height was rounding up to make sure I have at least as much space as I ask for. Two options to get a more consistent size:

  1. When applying the device pixel ratio to the original width/height, round down. This can result in a slightly lower size than desired.
  2. When calling resizeOverlay we can round up the width/height so that when it is multiplied by the device pixel ratio and then truncated it will be at least as large as our desired width/height. Unfortunately since the arguments to resizeOverlay are ints we cannot totally avoid unnecessary rounding up (without modifying the package). Here is an example method:
  static Future<bool?> resizeOverlay(BuildContext context, Size size) {
    final devicePixelRatio = MediaQuery.devicePixelRatioOf(context);

    final adjustedWidth =
        (((size.width * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();
    final adjustedHeight =
        (((size.height * devicePixelRatio).ceilToDouble()) / devicePixelRatio)
            .ceil();

    return FlutterOverlayWindow.resizeOverlay(adjustedWidth, adjustedHeight);
  }

I have the similar issue with this. " await FlutterOverlayWindow.showOverlay( enableDrag: true, overlayTitle: "来电显示", overlayContent: "name:${callerIdData.phoneNumber},region:${callerIdData.countryName},carrier:${callerIdData.carrier}", alignment: OverlayAlignment.center, flag: OverlayFlag.defaultFlag, visibility: overlay.NotificationVisibility.visibilityPublic, positionGravity: PositionGravity.auto, height: (styleProvider.windowHeight * (pixelRatio ?? 3.0)) .toInt(), // 使用 styleProvider.windowHeight width: (styleProvider.windowWidth * (pixelRatio ?? 3.0)).toInt()," i have to use "PixelRatio = MediaQuery.of(context).devicePixelRatio" other wise It will be 1/3 than its real size, I don't know what is the issue with this

Unfortunately, I had to go into the code and change the resize method myself

Ahmadu-Suleiman avatar Sep 27 '24 13:09 Ahmadu-Suleiman