【问题标题】:Using video_player package with Flutter Hooks to play a background fullscreen video使用带有 Flutter Hooks 的 video_player 包播放背景全屏视频
【发布时间】:2021-01-28 06:11:34
【问题描述】:

我有一个主屏幕小部件,它使用 video_player 包播放全屏背景视频。 这段代码对我来说很好用:

class HomeScreen extends StatefulWidget {
  HomeScreen({Key key}) : super(key: key);

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

class _HomeScreenState extends State<HomeScreen> {
  VideoPlayerController _controller;

  void initState() {
    super.initState();
    // Pointing the video controller to mylocal asset.
    _controller = VideoPlayerController.asset("assets/waterfall.mp4");

    _controller.initialize().then((_) {
      // Once the video has been loaded we play the video and set looping to true.
      _controller.play();
      _controller.setLooping(true);
      // Ensure the first frame is shown after the video is initialized.
      setState(() {});
    });
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Stack(
          children: <Widget>[
            SizedBox.expand(
              child: FittedBox(
                // If your background video doesn't look right, try changing the BoxFit property.
                // BoxFit.fill created the look I was going for.
                fit: BoxFit.fill,
                child: SizedBox(
                  width: _controller.value.size?.width ?? 0,
                  height: _controller.value.size?.height ?? 0,
                  child: VideoPlayer(_controller),
                ),
              ),
            ),
            Container(
              child: Center(
                child: Text('Hello!'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

问题是,如何使用颤振 Hooks 来实现这一点?我知道我必须使用 useEffect() 来实现 initState() 和 dispose()、useFuture() 的功能,也许还有 useMemoized() 来处理异步 _controller.initialize() 调用,还有什么可能?但是,我无法将它们粘合以获得所需的结果。谁能告诉我上述代码的“使用 Hooks”实现?

【问题讨论】:

    标签: flutter flutter-hooks


    【解决方案1】:

    当我遇到这个问题时,我正在寻找如何将 VideoPlayer 演示从 StatefulWidget 转换为 HookWidget 的答案。我想出了一些可行的方法,因此我将其发布在这里,因为在其他地方我找不到任何东西,而其他一些人正在访问此页面寻找答案。

    我使用了视图模型。视频控制器是视图模型的属性。此代码不会编译,因为某些控件不包括在内。但它将演示视图模型的结构和合并。

    这是小部件文件:

    import 'package:flutter/foundation.dart';
    import 'package:flutter_hooks/flutter_hooks.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'package:video_player/video_player.dart';
    
    import 'intro_viewmodel.dart';
    
    class IntroPage extends HookWidget {
      Future<void> saveAndGetStarted(BuildContext context) async {
        final IntroViewModel introViewModel = context.read(introViewModelProvider);
        await introViewModel.completeIntro();
      }
    
      Future<void> onNext(BuildContext context) async {
        final IntroViewModel introViewModel = context.read(introViewModelProvider);
        await introViewModel.incrementIntro();
      }
    
      final List<SliderModel> slides = [
        SliderModel(
            description: 'A word with you before you get started.\n',
            title: 'Why This App?',
            localImageSrc: 'media/Screen1-Movingforward-pana.svg',
            backgroundColor: Colors.lightGray),
        SliderModel(
            description: 'This information will help the app be more accurate\n',
            title: 'Personal Profile',
            localImageSrc: 'media/Screen2-Teaching-cuate.svg',
            backgroundColor: Colors.lightGray)
      ];
    
      @override
      Widget build(BuildContext context) {
        final IntroViewModel introViewModel = context.read(introViewModelProvider);
    
        return Scaffold(
            body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Center(
            child: Column(
              children: [
                Text(
                  slides[introViewModel.index].description,
                  style: Theme.of(context).textTheme.headline5,
                  textAlign: TextAlign.center,
                ),
                Expanded(
                    child: FractionallySizedBox(
                  widthFactor: .98,
                  heightFactor: .5,
                  child: VideoPlayer(introViewModel.videoController),
                )),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: CustomRaisedButton(
                    onPressed: () {
                      if (introViewModel.index == slides.length - 1) {
                        saveAndGetStarted(context);
                      } else {
                        onNext(context);
                      }
                    },
                    color: Theme.of(context).accentColor,
                    borderRadius: 15,
                    height: 50,
                    child: Text(
                      introViewModel.index == 0
                          ? 'Continue'
                          : 'Save and Get Started',
                      style: Theme.of(context)
                          .textTheme
                          .headline5
                          .copyWith(color: Colors.white),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ));
      }
    
      @override
      void debugFillProperties(DiagnosticPropertiesBuilder properties) {
        super.debugFillProperties(properties);
        properties.add(IterableProperty<SliderModel>('slides', slides));
      }
    }
    
    

    这是视图模型代码

    import 'package:flutter/foundation.dart';
    import 'package:hooks_riverpod/hooks_riverpod.dart';
    import 'package:video_player/video_player.dart';
    import '../top_level_providers.dart';
    
    final introViewModelProvider = ChangeNotifierProvider<IntroViewModel>((ref) {
    //this singleton class provides global access to selected variables
      final SharedPreferencesService localSharedPreferencesService =
          ref.watch(sharedPreferencesService);
      return IntroViewModel(localSharedPreferencesService);
    });
    
    class IntroViewModel extends ChangeNotifier {
      IntroViewModel(this.localSharedPreferencesService) : super() {
        state = localSharedPreferencesService?.isIntroComplete();
    
        // Pointing the video controller to my local asset.
        videoController = VideoPlayerController.asset('media/test_search.mp4');
    
        videoController.initialize().then((_) {
          // Once the video has been loaded we play the video and set looping to true.
          //  not autoplaying yet
    //  videoController.play();
          //    videoController.setLooping(true);
        });
      }
    
      final SharedPreferencesService localSharedPreferencesService;
      VideoPlayerController videoController;
      bool state = false;
      int index = 0;
    
      Future<void> completeIntro() async {
        await localSharedPreferencesService.setIntroComplete();
        state = true;
        notifyListeners();
      }
    
      Future<void> incrementIntro() async {
        ++index;
        notifyListeners();
      }
    
      bool get isIntroComplete => state;
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 2019-02-25
      • 2021-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      相关资源
      最近更新 更多