flutter_webview 不垂直滚动(overflow-y 滚动条不显示)

flutter_webview not scrolling vertically (overflow-y scrollbar not showing)

我正在尝试在 Flutter 应用程序中嵌入一个特定的网页 (https://bandcamp.com/EmbeddedPlayer/album=3538525485/size=large/bgcol=ffffff/linkcol=9c7b14/transparent=true/),但由于内容溢出,该页面无法滚动。

以下是它的显示方式,请注意可滚动的播放列表(来自 macOS Safari 响应式设计模式的屏幕截图)。

但在Flutter WebView中,目前显示如下(iOS模拟器截图):

注意,虽然有内容溢出,但是没有滚动条,无法滚动。

代码如下:

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(
        brightness: Brightness.light,
      ),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Home'),
      ),
      child: SafeArea(
        child: WebView(
          initialUrl: 'https://bandcamp.com/EmbeddedPlayer/album=3538525485/size=large/bgcol=ffffff/linkcol=9c7b14/transparent=true/',
          javascriptMode: JavascriptMode.unrestricted,
          zoomEnabled: false,
          gestureRecognizers: {}..add(Factory(() => VerticalDragGestureRecognizer())),
        ),
      ),
    );
  }
}

非常感谢任何帮助。

事实证明,我必须将 Bandcamp 播放器嵌入到 iframe 中。
在对嵌入式播放器的响应式布局应用一些基于 LayoutBuilder 约束的 CSS 之后,现在一切都按预期工作。

这是最终代码:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(
        brightness: Brightness.light,
      ),
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int _visibleChildIndex = 0;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text(
          'WebView Page',
          overflow: TextOverflow.ellipsis,
        ),
      ),
      child: SafeArea(
        child: IndexedStack(
          index: _visibleChildIndex,
          children: [
            const Center(
              child: CircularProgressIndicator.adaptive(),
            ),
            Center(
              child: Column(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: const [
                  Icon(
                    Icons.warning_amber_rounded,
                    size: 64.0,
                  ),
                  SizedBox(height: 8.0),
                  Text(
                    'Failed to load page.',
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),
            _buildWebView(
                'https://bandcamp.com/EmbeddedPlayer/album=3538525485/size=large/bgcol=ffffff/linkcol=9c7b14/transparent=true/'),
          ],
        ),
      ),
    );
  }

  String _getBandCampPlayerHTML({
    required String iframeSrc,
    required double width,
    required double height,
  }) {
    return '''
    <!DOCTYPE html>
    <html>
      <head>
        <title>Music Album</title>
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <style>
          html, body {
            margin: 0;
            padding: 0;
            overflow: hidden;
          }
          .page-container {
            max-width: ${width}px;
            margin: 0 auto;
          }
          .iframe-container {
            width: 0;
            height: 0;
            position: relative;
            padding: ${height}px 0 0 ${width}px;
          }
          iframe {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border: 0;
          }
        </style>
      </head>
      <body>
      <div class="page-container">
        <div class="iframe-container">
          <iframe src="$iframeSrc" scrolling="no" allow="encrypted-media;"></iframe>
        </div>
      </div>
      </body>
    </html> 
    ''';
  }

  Widget _buildWebView(String src) {
    return LayoutBuilder(builder: (context, constraints) {
      double width = 700.0;
      final height = constraints.maxHeight;
      width = (constraints.maxWidth > width) ? width : constraints.maxWidth;
      if (height <= width) {
        width = height * 0.6;
      }
      return WebView(
        initialUrl: Uri.dataFromString(
          _getBandCampPlayerHTML(
            iframeSrc: src,
            width: width,
            height: height,
          ),
          mimeType: 'text/html',
        ).toString(),
        javascriptMode: JavascriptMode.unrestricted,
        allowsInlineMediaPlayback: true,
        onWebResourceError: (error) {
          setState(() {
            _visibleChildIndex = 1;
          });
        },
        onPageFinished: (url) {
          setState(() {
            _visibleChildIndex = 2;
          });
        },
      );
    });
  }
}