Flutter中如何实现登录页全屏视频背景

11

我想在我的登录页面上显示一个视频,就像Spotify一样,你可以播放视频并拥有登录或注册按钮:

enter image description here

到目前为止我找到的插件是:

video_player 0.7.2 但我认为它的用途不同。

我知道如何显示一张图片,但我无法使用上述插件替换图片。这是我现在使用图像作为背景的情况。

body: new Container(
    height: MediaQuery.of(context).size.height,
    decoration: BoxDecoration(
      color: Colors.redAccent,
      image: DecorationImage(
        colorFilter: new ColorFilter.mode(
            Colors.black.withOpacity(0.1), BlendMode.dstATop),
        image: AssetImage('assets/my_image.jpg'),
        fit: BoxFit.cover,
      ),
    ),
    ...
  ..

感谢您的阅读,祝您编码愉快


嗨,你找到解决方案了吗? - alessandro buffoli
Nop @alessandrobuffoli - Faustino Gagneten
5个回答

11

使用FittedBox小部件处理溢出的解决方案:

Stack(
  children: <Widget>[
    SizedBox.expand(
      child: FittedBox(
        fit: BoxFit.cover,
        child: SizedBox(
          width: _controller.value.size?.width ?? 0,
          height: _controller.value.size?.height ?? 0,
          child: VideoPlayer(_controller),
        ),
      ),
    ),
    LoginWidget()
  ],
)

一个完整的示例可能是:

import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';

void main() => runApp(BackgroundVideo());

class BackgroundVideo extends StatefulWidget {
  @override
  _BackgroundVideoState createState() => _BackgroundVideoState();
}

class _BackgroundVideoState extends State<BackgroundVideo> {
  VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
        'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4')
      ..initialize().then((_) {
        _controller.play();
        _controller.setLooping(true);
        // Ensure the first frame is shown after the video is initialized
        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: <Widget>[
            SizedBox.expand(
              child: FittedBox(
                fit: BoxFit.cover,
                child: SizedBox(
                  width: _controller.value.size?.width ?? 0,
                  height: _controller.value.size?.height ?? 0,
                  child: VideoPlayer(_controller),
                ),
              ),
            ),
            LoginWidget()
          ],
        ),
      ),
    );
  }

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

class LoginWidget extends StatelessWidget {
  const LoginWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        Container(),
        Container(
          padding: EdgeInsets.all(16),
          width: 300,
          height: 200,
          color: Colors.grey.withAlpha(200),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              TextField(
                decoration: InputDecoration(
                  hintText: 'Username',
                ),
              ),
              TextField(
                decoration: InputDecoration(
                  hintText: 'Password',
                ),
              ),
              RaisedButton(
                child: Text('Login'),
                onPressed: () {},
              ),
            ],
          ),
        ),
      ],
    );
  }
}

1
也许堆叠小部件是其中一种解决方案。
如果您想以简单的方式重叠多个子元素,例如将一些文本和图像重叠,并覆盖渐变和底部附加的按钮,则堆叠类非常有用。
     Stack(
        //alignment:new Alignment(x, y)
        children: <Widget>[
          new Container(
            //play video here
          ),
          new Container(
            //have your Ui here
          ),
        ],
      ),

没起作用。你能否给一个完整的解决方案?也许我做错了什么。 - Faustino Gagneten

0
我接近解决方案的唯一方法是这样的。
假设这是一个1920 x 1080的视频,你正在使用video_player
Container(
  width: *screen width*,
  height: *screen height*,
  child: Stack(
    children: <Widget>[
      Center(
        child: Transform.scale(
          scale: 3.9, //change this number as needed
          AspectRatio(
            aspectRatio: _controller.value.aspectRatio,
            child: VideoPlayer(_controller),
          ),
        ),
      ),
      *widgets will go on top of screen*
    ],
  ),
)

找到合适的比例尺是最困难的部分,您可能需要找到一个小方程式,可以适用于所有设备。如果您发现任何拼写错误或想要添加内容,请随意进行更改。 希望这有所帮助!


0

我也在做同样的事情,以下代码对我有效。

Stack(
      fit: StackFit.expand,
      children: [
        Container(
        child: _controller.value.initialized
            ? AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: VideoPlayer(_controller),
              )
            : Container(),
      ), ] )

0
尝试下面的代码。
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';

void main() => runApp(VideoPlayerApp());

class VideoPlayerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Player Demo',
      home: VideoPlayerScreen(),
    );
  }
}

class VideoPlayerScreen extends StatefulWidget {
  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  VideoPlayerController _controller;
  Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.
    _controller = VideoPlayerController.network(
      'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
    );

    // Initialize the controller and store the Future for later use.
    _initializeVideoPlayerFuture = _controller.initialize();

    // Use the controller to loop the video.
    _controller.setLooping(true);

    super.initState();
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Use a FutureBuilder to display a loading spinner while waiting for the
      // VideoPlayerController to finish initializing.
      body: FutureBuilder(
        future: _initializeVideoPlayerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // If the VideoPlayerController has finished initialization, use
            // the data it provides to limit the aspect ratio of the video.
            return Stack(
              fit: StackFit.expand,
              children: <Widget>[
                Container(
                  child: AspectRatio(
                    aspectRatio: _controller.value.aspectRatio,
                    // Use the VideoPlayer widget to display the video.
                    child: VideoPlayer(_controller),
                  ),
                ),
              ],
            );
          } else {
            // If the VideoPlayerController is still initializing, show a
            // loading spinner.
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Wrap the play or pause in a call to `setState`. This ensures the
          // correct icon is shown.
          setState(() {
            // If the video is playing, pause it.
            if (_controller.value.isPlaying) {
              _controller.pause();
            } else {
              // If the video is paused, play it.
              _controller.play();
            }
          });
        },
        // Display the correct icon depending on the state of the player.
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

使视频完美适应整个屏幕的主要代码是 fit: StackFit.expand,


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接