【问题标题】:Change size/position of Text relative to other Widget更改文本相对于其他小部件的大小/位置
【发布时间】:2020-05-12 06:14:43
【问题描述】:

谁能帮忙?

目前,我在视频上显示的文本具有固定的大小和位置。

我想知道如何动态/响应地更改它以匹配其父小部件(视频)的大小。

我尝试了一种使用GlobalKey的方法,但出现错误,我认为是因为视频没有加载..

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
      body: Container(
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              NavBar(),
              Body(),
              Footer(),
            ],
          ),
        ),
      ),
    );
  }
}

class Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ResponsiveLayout(
      largeScreen: LargeScreen(),
      mediumScreen: LargeScreen(),
      smallScreen: LargeScreen(),
    );
  }
}

class LargeScreen extends StatefulWidget {
  @override
  _LargeScreenState createState() => _LargeScreenState();
}

class _LargeScreenState extends State<LargeScreen> {
  VideoPlayerController _videoPlayerController;
  Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    _videoPlayerController = VideoPlayerController.asset(
      'assets/videos/video.mp4',
    );
    _initializeVideoPlayerFuture = _videoPlayerController.initialize();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 40),
      child: Column(
        children: <Widget>[
          FutureBuilder(
            future: _initializeVideoPlayerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done &&
                  !_videoPlayerController.value.isBuffering) {
                // If the VideoPlayerController has finished initialization, use
                // the data it provides to limit the aspect ratio of the VideoPlayer.
                return AspectRatio(
                  aspectRatio: _videoPlayerController.value.aspectRatio,
                  // Use the VideoPlayer widget to display the video.
                  child: Stack(
                    children: <Widget>[
                      VideoPlayer(_videoPlayerController),
                      Positioned(
                        bottom: 20,
                        left: 20,
                        child: FittedBox(
                          child: Text(
                            'Text over\na video',
                            style: TextStyle(
                                color: Colors.white,
                                fontSize:50),
                          ),
                        ),
                      )
                    ],
                  ),
                );
              } else {
                // If the VideoPlayerController is still initializing, show a
                // loading spinner.
                return Center(child: CircularProgressIndicator());
              }
            },
          ),
        ],
      ),
    );
  }

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

【问题讨论】:

    标签: flutter dart flutter-layout flutter-web


    【解决方案1】:

    LayoutBuilder可以为你提供widthheight属性,对应当前可用空间。检查此文档here。它为构建器提供BoxConstraints 实例,如here。您可以使用此信息来调整文本大小。

    检查Align widget。它可以将子控件放置在父控件坐标系中的特定位置。在您的情况下,它将位于 Stack 小部件的坐标上。

    我会尝试以下方法。

    1. Text 小部件包装在Align 小部件中,并使用FractionalOffset 放置对齐小部件。您也可以直接使用Alignment 实例。两种方法的起源会有所不同。检查文档here
    2. 然后将我的Align 小部件包裹在LayoutBuilder 小部件中以获取可用大小并根据它决定我的字体大小。类似fontSize: constraints.maxWidth / 25

    以下是示例工作代码。

    // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
    // for details. All rights reserved. Use of this source code is governed by a
    // BSD-style license that can be found in the LICENSE file.
    
    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.black,
          // drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
          body: Container(
            child: SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  // NavBar(),
                  Body(),
                  // Footer(),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class Body extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // return ResponsiveLayout(
        //   largeScreen: LargeScreen(),
        //   mediumScreen: LargeScreen(),
        //   smallScreen: LargeScreen(),
        // );
        return LargeScreen();
      }
    }
    
    class LargeScreen extends StatefulWidget {
      @override
      _LargeScreenState createState() => _LargeScreenState();
    }
    
    class _LargeScreenState extends State<LargeScreen> {
      VideoPlayerController _videoPlayerController;
      Future<void> _initializeVideoPlayerFuture;
    
      @override
      void initState() {
        _videoPlayerController = VideoPlayerController.network(
          'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4',
        );
        _initializeVideoPlayerFuture =
            _videoPlayerController.initialize().then((onValue) {
          setState(() {});
        });
    
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 40),
          child: Column(
            children: <Widget>[
              FutureBuilder(
                future: _initializeVideoPlayerFuture,
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done &&
                      !_videoPlayerController.value.isBuffering) {
                    // If the VideoPlayerController has finished initialization, use
                    // the data it provides to limit the aspect ratio of the VideoPlayer.
                    return AspectRatio(
                      aspectRatio: _videoPlayerController.value.aspectRatio,
                      // Use the VideoPlayer widget to display the video.
                      child: Stack(
                        children: <Widget>[
                          VideoPlayer(_videoPlayerController),
                          LayoutBuilder(
                            builder: (context, constraints) {
                              return Align(
                                // this decides the position of the text.
                                alignment: FractionalOffset(0.05, 0.95),
                                child: FittedBox(
                                  child: Text(
                                    'Text over\na video',
                                    style: TextStyle(
                                      color: Colors.white,
                                      // here font size is ratio of the maxwidth available for this widget.
                                      fontSize: constraints.maxWidth / 25,
                                    ),
                                  ),
                                ),
                              );
                            },
                          )
                        ],
                      ),
                    );
                  } else {
                    // If the VideoPlayerController is still initializing, show a
                    // loading spinner.
                    return Center(child: CircularProgressIndicator());
                  }
                },
              ),
              FloatingActionButton(
                onPressed: () {
                  setState(() {
                    _videoPlayerController.value.isPlaying
                        ? _videoPlayerController.pause()
                        : _videoPlayerController.play();
                  });
                },
                child: Icon(
                  _videoPlayerController.value.isPlaying
                      ? Icons.pause
                      : Icons.play_arrow,
                ),
              ),
            ],
          ),
        );
      }
    
      @override
      void dispose() {
        super.dispose();
        _videoPlayerController.dispose();
      }
    }
    

    【讨论】:

    • 谢谢!我稍后会试一试 - 会回来报告:D
    • 当然。希望能帮助到你。 :-)
    • 嘿伙计,知道为什么当我将视频切换为图像时此方法不起作用吗?
    • 取决于图像小部件是否重新缩放到寡妇大小。究竟是什么不工作?也许您可以随代码打开一个新帖子。 :)
    【解决方案2】:

    可通过MediaQuery.of(context).size (Documentation) 轻松访问。

    请记住,您必须在构建方法内部调用,因为它需要上下文

    【讨论】:

    • 不确定这是我要找的... MediaQuery 不是返回设备大小吗?
    • 你是对的,我完全误解了你的问题。向我致敬:/
    猜你喜欢
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多