首页 > 解决方案 > 当我使用 youtube_player_flutter 和 carousel_slider 包时,Youtube 播放器在 Flutter / Dart 应用程序中不起作用:

问题描述

我在 Flutter / Dart 中使用以下 youtube_player_flutter 和 carousel_slider 包:

https://pub.dev/packages/youtube_player_flutter

https://pub.dev/packages/carousel_slider

我已经在视频预览屏幕上设置了它们,但是当我使用 carousel_slider 从 youtube 视频导航到另一个 youtube 视频屏幕时,在控制台面板中出现以下错误:

W/ContentCatcher(17665): Failed to notify a WebView
E/flutter (17665): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: MissingPluginException(No implementation found for method evaluateJavascript on channel com.pichillilorenzo/flutter_inappwebview_7)
E/flutter (17665): #0      MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:156
E/flutter (17665): <asynchronous suspension>
E/flutter (17665): #1      InAppWebViewController.evaluateJavascript
package:flutter_inappwebview/…/in_app_webview/in_app_webview_controller.dart:1375
E/flutter (17665): <asynchronous suspension>

我有 10 MB/s 的网速,所以我 100% 确定这不是网速/网络问题。

Youtube 视频网址是https://www.youtube.com/watch?v=ZN_XrB_St-8

在此处输入图像描述

请找到随附的应用程序屏幕截图。请检查问题并建议我如何解决它。非常感谢。期待听到你的声音。

标签: flutterdartvideoyoutube

解决方案


下面是我们使用这两个包的预览屏幕的完整代码:

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:videoproject/screens/PhotoEnlargeViewScreen.dart';
import 'package:videoproject/vendor/Constants.dart';
import 'package:videoproject/vendor/Masterfunctions.dart';
import 'package:videoproject/widgets/CustomLoaderWidget.dart';
import 'package:videoproject/widgets/CustomerLoaderCircularProgressIndicatorWidget.dart';
import 'package:videoproject/widgets/ShowAppDialog.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';

class PhotosViewerScreen extends StatefulWidget {
  final List filesPathList;
  final int fileIndex;

  PhotosViewerScreen({required this.filesPathList, this.fileIndex = 0});

  @override
  _PhotosViewerScreenState createState() => _PhotosViewerScreenState();
}

class _PhotosViewerScreenState extends State<PhotosViewerScreen> {
  MasterFunctions mf = MasterFunctions();
  CarouselController _carouselController = CarouselController();

  List _filesPathList = [];
  int? _activeFileIndex;
  String? _activeFilePath;
  bool _isPlayingVideo = false;

  bool _isLoading = false;

  YoutubePlayerController? _yTPlayerController;

  @override
  void initState() {
    _filesPathList = widget.filesPathList;
    _activeFileIndex = widget.fileIndex;
    _activeFilePath = widget.filesPathList[widget.fileIndex];

    if (_activeFilePath.toString().indexOf('youtube.com') != -1) {
      // video case
      _isPlayingVideo = true;
      _videoinit();
    } else {
      // photo case
      _isPlayingVideo = false;
    }

    //
    super.initState();
  }

  customcallbackFunction(
      int currentPhotoIndex, CarouselPageChangedReason reason) async {
    _activeFileIndex = currentPhotoIndex;
    _activeFilePath = _filesPathList[_activeFileIndex as int];

    print("_activeFilePath: $_activeFilePath");

    //
    if (_activeFilePath.toString().indexOf('youtube.com') != -1) {
      // video case
      _isPlayingVideo = true;
      _videoinit();
    } else {
      // photo case
      _isPlayingVideo = false;
    }

    if (mounted) {
      setState(() {});
    }
  }

  _videoinit() {
    String videoId;
    videoId = YoutubePlayer.convertUrlToId(_activeFilePath.toString())!;

    if (_yTPlayerController == null) {
      _yTPlayerController = YoutubePlayerController(
        initialVideoId: videoId, //'iLnmTe5Q2Qw',
        flags: YoutubePlayerFlags(
          autoPlay: true,
          // mute: true,
        ),
      );
      if (mounted) {
        setState(() {});
      }
    } else {
      // already initialized a video and wants to play next video
      // dispose last video if playing
      final _oldYTPlayerController = _yTPlayerController;
      WidgetsBinding.instance!.addPostFrameCallback((_) async {
        _oldYTPlayerController!.dispose();

        // Initing new controller
        _yTPlayerController = YoutubePlayerController(
          initialVideoId: videoId, //'iLnmTe5Q2Qw',
          flags: YoutubePlayerFlags(
            autoPlay: true,
            // mute: true,
          ),
        );
        if (mounted) {
          setState(() {});
        }
      });

      //
      if (mounted) {
        setState(() {
          _yTPlayerController = null;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final double heightWrapper = MediaQuery.of(context).size.height;
    bool isPortrait =
        (MediaQuery.of(context).orientation == Orientation.portrait);

    return CustomLoaderWidget(
      isLoadingStatus: _isLoading,
      appBodyWidget: Scaffold(
        appBar: (_isPlayingVideo == false ||
                (_isPlayingVideo == true && isPortrait == true))
            ? AppBar(
                title: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisSize: MainAxisSize.max,
                  children: [
                    Text(
                      (widget.filesPathList.length > 1)
                          ? 'Photos/Videos Preview'
                          : "${(_activeFilePath.toString().indexOf('youtube.com') != -1) ? 'Video' : 'Photo'} Preview",
                      style: Theme.of(context).appBarTheme.textTheme!.headline1,
                    ),
                    if (widget.filesPathList.length > 1)
                      Text(
                        // "${(_activeFilePath.toString().indexOf('youtube.com') != -1) ? 'Video' : 'Photo' } ${_activeFileIndex! + 1} out of ${widget.filesPathList.length}",
                        "Showing ${_activeFileIndex! + 1} out of ${widget.filesPathList.length}",
                        style: Theme.of(context).textTheme.bodyText2,
                      ),
                  ],
                ),
                actions: [
                  IconButton(
                    icon:
                        Icon(Icons.help, color: Theme.of(context).primaryColor),
                    onPressed: () {
                      ShowAppDialog.showAlertDialog(
                          context: context,
                          titleText: 'Tips',
                          subtitleText:
                              '- Swipe left or right to see more photos/videos.\n- Tap on photo to see enlarge view.\n- Rotate phone horizontally to see video on full screen.');
                    },
                  ),
                ],
              )
            : null,
        body: Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          decoration: BoxDecoration(
              // color: Colors.black,
              ),
          child: Center(
            child: (_filesPathList.length > 0)
                ? CarouselSlider(
                    carouselController: _carouselController,
                    options: CarouselOptions(
                      height: heightWrapper,
                      viewportFraction: 1.0,
                      initialPage: _activeFileIndex!,
                      enableInfiniteScroll: false,
                      enlargeCenterPage: false,
                      onPageChanged: customcallbackFunction,
                      // autoPlay: false,
                    ),
                    items: _filesPathList.map((mapFilePath) {
                      if (_activeFilePath.toString().indexOf('youtube.com') !=
                          -1) {
                        // video case
                        if (_yTPlayerController != null) {
                          return Container(
                            // color: Colors.black,
                            padding: EdgeInsets.symmetric(
                                vertical: (isPortrait)
                                    ? (heightWrapper * 0.20)
                                    : 0.0),
                            child: Hero(
                              tag: _activeFilePath.toString(),
                              child: YoutubePlayer(
                                controller: _yTPlayerController!,
                                showVideoProgressIndicator: true,
                                progressIndicatorColor: CONST_APP_PRIMARY_COLOR,
                                aspectRatio: 1,
                              ),
                            ),
                          );
                        } else {
                          return Container(
                            width: 200.0,
                            height: 200.0,
                            child: Text('player not found'),
                          );
                        }
                      } else {
                        // photo case
                        return Container(
                          child: (mf.isValidUrl(_activeFilePath!))
                              ? InkWell(
                                  onTap: () {
                                    Navigator.push(
                                      context,
                                      MaterialPageRoute(
                                        builder: (context) =>
                                            PhotoEnlargeViewScreen(
                                                photoPath: _activeFilePath!),
                                      ),
                                    );
                                  },
                                  child: Hero(
                                    tag: _activeFilePath.toString(),
                                    child: CachedNetworkImage(
                                      imageUrl: _activeFilePath!,
                                      placeholder: (context, url) =>
                                          new CustomerLoaderCircularProgressIndicatorWidget(),
                                      errorWidget: (context, url, error) =>
                                          new Icon(Icons.error),
                                    ),
                                  ),
                                )
                              : Image.asset(
                                  'assets/images/person04.jpg',
                                  alignment: Alignment.center,
                                  fit: BoxFit.cover,
                                ),
                        );
                      }
                    }).toList(),
                  )
                : Container(
                    child: CustomerLoaderCircularProgressIndicatorWidget(),
                  ),
          ),
        ),
      ),
    );
  }
}

请分享您的建议,将不胜感激。非常感谢。


推荐阅读