我的视频呼叫输出

enter image description here

当另一个人登录到此视频呼叫时,会显示为这样.但我希望当有人登录到视频呼叫时,我的视频应该很小. 像这样.

enter image description here

另外,当点击我的视频时,我的视频应该是大的,而另一个人的视频应该是小的.如何做到这一点?我找不到任何如何做到这一点的文件

编码视频呼叫用户界面

// video view
  Widget _viewRows() {
    final views = _getRenderViews();
    switch (views.length) {
      case 1:
        return Column(
          children: <Widget>[_videoView(views[0])],
        );
      case 2:
        return Column(
          children: <Widget>[
            _expandedVideoRow([views[0]]),
            _expandedVideoRow([views[1]])
          ],
        );
      case 3:
        return Column(
          children: <Widget>[
            _expandedVideoRow(views.sublist(0, 2)),
            _expandedVideoRow(views.sublist(2, 3))
          ],
        );
      case 4:
        return Column(
          children: <Widget>[
            _expandedVideoRow(views.sublist(0, 2)),
            _expandedVideoRow(views.sublist(2, 4))
          ],
        );
      default:
    }
    return Container();
  }

如何像我提到的那样定制视频用户界面?

error

enter image description here

enter image description here

推荐答案

要创建所需的布局,请使用以下代码编辑_viewRow(CallNotifierNotifier)和_ExpandedVideoRow(列表视图)函数:-

Widget_viewRow(CallNotiator通知程序):-

case 2:
    return Container(
            margin: EdgeInsets.only(top: 100, bottom: 100),
            child: Stack(
              children: [
                _expandedVideoRow([views[secondScreen]]),
                Align(
                  alignment: Alignment.bottomRight,
                  child: Padding(
                    padding: const EdgeInsets.only(right: 10, bottom: 10),
                    child: GestureDetector(
                      onTap: () {
                        tempSwap = firstScreen;
                        firstScreen = secondScreen;
                        secondScreen = tempSwap;
                        setState(() {});
                      },
                      child: SizedBox(
                          height: 200,
                          width: 100,
                          child: _expandedVideoRow([views[firstScreen]])),
                    ),
                  ),
                ),
              ],
            ));

上面的代码包含_expemdedVideoRow([Views[Second Screen]]),它只是一个简单的可扩展容器,我们将屏幕的索引作为参数传递.在我们的例子中,有两个屏幕,因此有两个index,即0和1.我在这里声明了三个整数变量,int first Screen=0,int Second Screen=1和int tempSwitp=0.SizedBox减小其宽度和高度,并对齐小部件,以便在用户点击该屏幕时交换变量的索引,从而导致屏幕交换.

Widget_ExpandedVideo行(列表视图):-

Widget _expandedVideoRow(List<Widget> views) {
    final wrappedViews = views.map<Widget>(_videoView).toList();
    return Row(
      children: wrappedViews,
    );
}

删除像上面的代码一样包装行的展开小部件,因为我们不能使用Stack下展开的小部件.

如果你想改变底部的图标,那么根据你的需要改变_工具栏(CallNotifierNotifier.CallNotifier.cn)功能.

Widget _toolbar(CallNotifier notifier) {
return Container(
  alignment: Alignment.bottomCenter,
  padding: const EdgeInsets.symmetric(vertical: 20),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      RawMaterialButton(
        onPressed: () {
          _onToggleMute(notifier);
          setState(() {
            isMute = !isMute;
          });
        },
        child: Icon(
          isMute ? Icons.mic_off : Icons.mic,
          color: isMute ? Colors.white : Colors.teal,
          size: 20.0,
        ),
        shape: CircleBorder(),
        elevation: 2.0,
        fillColor: isMute ? Colors.teal : Colors.white,
        padding: const EdgeInsets.all(12.0),
      ),
      RawMaterialButton(
        onPressed: () => _onCallEnd(context),
        child: Icon(
          Icons.call_end,
          color: Colors.white,
          size: 20.0,
        ),
        shape: CircleBorder(),
        elevation: 2.0,
        fillColor: Colors.redAccent,
        padding: const EdgeInsets.all(15.0),
      ),
    ],
  ),
);
}

我在应用程序中使用的代码,完整代码:-

class _CallScreenState extends State<CallScreen> {
  double globalHeight;
  int firstScreen = 0;
  int secondScreen = 1;
  int tempSwap = 0;
  bool isMute = false;

  void initState() {
    super.initState();
  }

  List<Widget> _getRenderViews(CallNotifier model) {
    final List<StatefulWidget> list = [];
    list.add(RtcLocalView.SurfaceView());
    model.users
        .forEach((int uid) => list.add(RtcRemoteView.SurfaceView(uid: uid)));
    return list;
  }

  Widget _videoView(view) {
    return Expanded(child: Container(child: view));
  }

  Widget _expandedVideoRow(List<Widget> views) {
    final wrappedViews = views.map<Widget>(_videoView).toList();
    return Row(
      children: wrappedViews,
    );
  }

  Widget _viewRows(CallNotifier notifier) {
    final views = _getRenderViews(notifier);
    switch (views.length) {
      case 1:
        return Container(
            margin: EdgeInsets.only(top: 100, bottom: 100),
            child: Column(
              children: <Widget>[_videoView(views[0])],
            ));
      case 2:
        return Container(
            margin: EdgeInsets.only(top: 100, bottom: 100),
            child: Stack(
              children: [
                _expandedVideoRow([views[secondScreen]]),
                Align(
                  alignment: Alignment.bottomRight,
                  child: Padding(
                    padding: const EdgeInsets.only(right: 10, bottom: 10),
                    child: GestureDetector(
                      onTap: () {
                        tempSwap = firstScreen;
                        firstScreen = secondScreen;
                        secondScreen = tempSwap;
                        setState(() {});
                      },
                      child: SizedBox(
                          height: 200,
                          width: 100,
                          child: _expandedVideoRow([views[firstScreen]])),
                    ),
                  ),
                ),
              ],
            ));

      default:
    }
    return Container();
  }

  Widget _toolbar(CallNotifier notifier) {
    return Container(
      alignment: Alignment.bottomCenter,
      padding: const EdgeInsets.symmetric(vertical: 20),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RawMaterialButton(
            onPressed: () {
              _onToggleMute(notifier);
              setState(() {
                isMute = !isMute;
              });
            },
            child: Icon(
              isMute ? Icons.mic_off : Icons.mic,
              color: isMute ? Colors.white : Colors.teal,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: isMute ? Colors.teal : Colors.white,
            padding: const EdgeInsets.all(12.0),
          ),
          RawMaterialButton(
            onPressed: () => _onCallEnd(context),
            child: Icon(
              Icons.call_end,
              color: Colors.white,
              size: 20.0,
            ),
            shape: CircleBorder(),
            elevation: 2.0,
            fillColor: Colors.redAccent,
            padding: const EdgeInsets.all(15.0),
          ),
        ],
      ),
    );
  }

  void _onCallEnd(BuildContext context) {
    Navigator.pop(context);
  }

  void _onToggleMute(CallNotifier notifier) {
    notifier.isMuted = notifier.isMuted;
    notifier.engine.muteLocalAudioStream(notifier.isMuted);
  }

  @override
  Widget build(BuildContext context) {
    return BaseWidget<CallNotifier>(
        model: CallNotifier(),
        onModelReady: (model) => model.init(widget.channelName, widget.token),
        builder: (context, notifier, child) {
          return Scaffold(
            backgroundColor: Colors.black,
            body: SafeArea(
              child: Stack(
                children: <Widget>[
                  _viewRows(notifier),
                  Align(
                      alignment: Alignment.bottomCenter,
                      child: _toolbar(notifier)),
                ],
              ),
            ),
          );
        });
  }
}

Flutter相关问答推荐

当仅点击一行时,所有行都被选中

Fighter:基于ChangeNotifier状态动态更新AppBar中的图标

我如何才能动态地将小部件排成一排进行排列呢?

在Flutter 中创建自定义Snackbar类

Flutter :执行com.android.build.gradle.internal.tasks.MergeNativeLibsTask$MergeNativeLibsTaskWorkAction时出现故障

使用ImageFilter模糊并剪裁同一renderObject中的元素

Flutter中有没有办法区分鼠标左右平移?

自定义类提供程序 Riverpod Flutter 中的可变变量

尽管设置了对齐方式,如何对齐列中的行?

要禁用按钮上的通知声音,请点击Flutter

来自服务器的数据未分配给变量

splash_screen 没有被推送到登录页面

提供者、存储库和服务之间有什么区别?

如何流畅切换画面?

如何在 flutter 的 onChanged(更改字符)处更改 TextField 边框 colored颜色 ?

避免长单词中断

将一个 Flutter 应用程序集成到另一个 Flutter 应用程序中

TextSpan 避免符号字符串组上的换行符

更新未知文档 ID firebase\flutter 中的字段

如何在 Flutter 中创建类似箭头标签的设计