Repository: flutter
Issue: [webview_flutter] Bug: webview window size is zero when webview is not visible
Labels: a: platform-views,p: webview,package,team-ecosystem,P2,triaged-ecosystem

### What package does this bug report belong to?

webview_flutter

### What target platforms are you seeing this bug on?

iOS

### Have you already upgraded your packages?

Yes

### Dependency versions

<details><summary>pubspec.lock</summary>

```lock
  webview_flutter:
    dependency: "direct main"
    description:
      name: webview_flutter
      sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
      url: "https://pub.dev"
    source: hosted
    version: "4.7.0"
  webview_flutter_android:
    dependency: transitive
    description:
      name: webview_flutter_android
      sha256: f038ee2fae73b509dde1bc9d2c5a50ca92054282de17631a9a3d515883740934
      url: "https://pub.dev"
    source: hosted
    version: "3.16.0"
  webview_flutter_platform_interface:
    dependency: transitive
    description:
      name: webview_flutter_platform_interface
      sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
      url: "https://pub.dev"
    source: hosted
    version: "2.10.0"
  webview_flutter_wkwebview:
    dependency: transitive
    description:
      name: webview_flutter_wkwebview
      sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7
      url: "https://pub.dev"
    source: hosted
    version: "3.13.0"
```

</details>


### Steps to reproduce

Minimal code to reproduce the issue:

<details><summary>demo.dart</summary>

```dart
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

const pageScrollPhysics = PageScrollPhysics();

class ReaderV2 extends StatefulWidget {
  const ReaderV2({super.key});

  @override
  State<ReaderV2> createState() => _ReaderV2State();
}

const String _kInitialData = '''
<html>
  <head>
    <title>Flutter WebView Test</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        width: 100vw;
        height: 100vh;
        background: linear-gradient(to right, red, yellow);
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
      }
    </style>
  </head>
  <script>
    console.log("Web loaded, initial size, width=" + window.innerWidth + ", height=" + window.innerHeight);
    setTimeout(function() {
      console.log('timeout, width=' + window.innerWidth + ', height=' + window.innerHeight);
    }, 3000);
  </script>
  <body>
    <div>
      Hello, World!
    </div>
  </body>
</html>
''';

class _ReaderV2State extends State<ReaderV2> {
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.sizeOf(context);
    return Scaffold(
      body: ListView(
        scrollDirection: Axis.horizontal,
        physics: pageScrollPhysics,
        cacheExtent: size.width * 10,
        children: [
          WebviewWrapper(size: size),
          WebviewWrapper(size: size),
          WebviewWrapper(size: size),
        ],
      ),
    );
  }
}

class WebviewWrapper extends StatefulWidget {
  final Size size;
  const WebviewWrapper({super.key, required this.size});

  @override
  State<WebviewWrapper> createState() => _WebviewWrapperState();
}

class _WebviewWrapperState extends State<WebviewWrapper> {
  final WebViewController _controller = WebViewController();

  @override
  void initState() {
    super.initState();

    _controller
      ..enableZoom(false)
      ..setOnConsoleMessage((msg) => log(msg.message))
      ..loadHtmlString(_kInitialData);
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.size.width,
      height: widget.size.height,
      child: WebViewWidget(
        controller: _controller,
        gestureRecognizers: const {}, // disable webview's gesture recognizers
      ),
    );
  }
}
```

</details>


In above code, I created 3 webviews, and each webivew should have the same size of current screen.  The JS code will print the actual content size of each webview after 3 seconds.
```js
    setTimeout(function() {
      console.log('timeout, width=' + window.innerWidth + ', height=' + window.innerHeight);
    }, 3000);
 ```
 
 But only the first webview is rendered property because it is visible. The second and the third webview's window size will remains to be zero . If I scroll to the second or the third webview, they will be rendered immediately with proper window size.
 
 I know this default behavior could potentially improve the performance. But I want to get the webview content size while they are not visible. I wish I can prerender the webviews with the desired size before they are visible.
 
 PS: If it is not possible to render a webview when it is not visible, can I at least get the correct window size instead of a 0 width 0 height size?
 
### Expected results

Expected log should be:

```log
[log] Web loaded, initial size, width=980, height=2121
[log] Web loaded, initial size, width=980, height=2121
[log] Web loaded, initial size, width=980, height=2121
[log] timeout, width=390, height=844
[log] timeout, width=390, height=844
[log] timeout, width=390, height=844
```

### Actual results

Actual log is:

```log
[log] Web loaded, initial size, width=980, height=2121
[log] Web loaded, initial size, width=0, height=0
[log] Web loaded, initial size, width=0, height=0
[log] timeout, width=390, height=844
[log] timeout, width=0, height=0
[log] timeout, width=0, height=0
```

### Code sample

<details open><summary>Code sample</summary>

```dart
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

const pageScrollPhysics = PageScrollPhysics();

class ReaderV2 extends StatefulWidget {
  const ReaderV2({super.key});

  @override
  State<ReaderV2> createState() => _ReaderV2State();
}

const String _kInitialData = '''
<html>
  <head>
    <title>Flutter WebView Test</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        width: 100vw;
        height: 100vh;
        background: linear-gradient(to right, red, yellow);
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
      }
    </style>
  </head>
  <script>
    console.log("Web loaded, initial size, width=" + window.innerWidth + ", height=" + window.innerHeight);
    setTimeout(function() {
      console.log('timeout, width=' + window.innerWidth + ', height=' + window.innerHeight);
    }, 3000);
  </script>
  <body>
    <div>
      Hello, World!
    </div>
  </body>
</html>
''';

class _ReaderV2State extends State<ReaderV2> {
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.sizeOf(context);
    return Scaffold(
      body: ListView(
        scrollDirection: Axis.horizontal,
        physics: pageScrollPhysics,
        cacheExtent: size.width * 10,
        children: [
          WebviewWrapper(size: size),
          WebviewWrapper(size: size),
          WebviewWrapper(size: size),
        ],
      ),
    );
  }
}

class WebviewWrapper extends StatefulWidget {
  final Size size;
  const WebviewWrapper({super.key, required this.size});

  @override
  State<WebviewWrapper> createState() => _WebviewWrapperState();
}

class _WebviewWrapperState extends State<WebviewWrapper> {
  final WebViewController _controller = WebViewController();

  @override
  void initState() {
    super.initState();

    _controller
      ..enableZoom(false)
      ..setOnConsoleMessage((msg) => log(msg.message))
      ..loadHtmlString(_kInitialData);
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.size.width,
      height: widget.size.height,
      child: WebViewWidget(
        controller: _controller,
        gestureRecognizers: const {}, // disable webview's gesture recognizers
      ),
    );
  }
}
```

</details>


### Screenshots or Videos

N/A.

### Logs

_No response_

### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.2, on macOS 14.4.1 23E224 darwin-x64, locale
    en-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for
      more details.
[!] Xcode - develop for iOS and macOS (Xcode 15.3)
    ! CocoaPods 1.12.0 out of date (1.13.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods for instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.1)
[✓] VS Code (version 1.87.1)
[✓] Connected device (3 available)            
[✓] Network resources

! Doctor found issues in 2 categories.% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.2, on macOS 14.4.1 23E224 darwin-x64, locale
    en-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for
      more details.
[!] Xcode - develop for iOS and macOS (Xcode 15.3)
    ! CocoaPods 1.12.0 out of date (1.13.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods for instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.1)
[✓] VS Code (version 1.87.1)
[✓] Connected device (3 available)            
[✓] Network resources

! Doctor found issues in 2 categories.
```

</details>