You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:键盘弹出时如何上推Stack中的视频以保持TextField可见

解决Stack视频背景下键盘遮挡TextField的问题

问题原因

当前布局中,SingleChildScrollView直接包裹Stack,但Stack内的视频组件没有明确的全屏高度约束,导致滚动视图无法正确识别内容高度,进而使resizeToAvoidBottomInset: true的上推逻辑失效。同时,Stack的层级结构也干扰了滚动视图与键盘弹出事件的绑定。


解决方案一:给Stack添加明确高度约束

通过将Stack放入全屏高度的Container中,让滚动视图能正确感知内容范围,触发键盘上推逻辑:

return Scaffold(
  resizeToAvoidBottomInset: true,
  body: OrientationBuilder(builder: (context, orientation) {
    final screenHeight = MediaQuery.of(context).size.height;
    return SingleChildScrollView(
      reverse: true,
      child: Container(
        // 固定容器高度为屏幕高度,确保Stack占满全屏
        height: screenHeight,
        child: Stack(
          children: [
            _controller.value.isInitialized
                ? SizedBox.expand( // 用SizedBox.expand让视频铺满容器
                    child: FittedBox(
                      fit: BoxFit.cover,
                      child: SizedBox(
                        width: _controller.value.size.width ?? 0,
                        height: _controller.value.size.height ?? 0,
                        child: VideoPlayer(_controller),
                      ),
                    ),
                  )
                : Container(color: Colors.black), // 未初始化时添加背景色避免空白
            Container(
              width: double.infinity,
              child: Column(
                children: [
                  SizedBox(
                    height: isTab ? 20 : 53.h,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: [
                      Padding(
                        padding: EdgeInsets.only(left: screenWidth * 0.02),
                        child: InkWell(
                          onTap: () {
                            _controller.pause();
                            _controller.dispose();
                            Navigator.of(context).push(
                                createFadeInRoute(const HomeScreen()));
                          },
                          child: Container(
                            alignment: Alignment.center,
                            width: isTab ? 28 : 28,
                            height: isTab ? 28 : 28,
                            decoration: BoxDecoration(
                              color: const Color(0xFF75ABC9),
                              borderRadius: BorderRadius.circular(5),
                              boxShadow: const [
                                BoxShadow(
                                  color: Color(0xFF192D5D),
                                  offset: Offset(0, 1),
                                  blurRadius: 3,
                                ),
                              ],
                            ),
                            child: Padding(
                              padding: const EdgeInsets.only(left: 6),
                              child: Icon(
                                Icons.arrow_back_ios,
                                color: Colors.white,
                                size: isTab ? 23 : 18,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  SizedBox(
                    height: isTab
                        ? (orientation == Orientation.portrait
                            ? screenHeight * 0.20
                            : screenHeight * 0.280)
                        : screenWidth < 390
                            ? 170.h
                            : 170.h,
                  ),
                  ChatBox(
                    profilePic: widget.profilePic,
                    userd: widget.guruUserId,
                    isPlayingAnimatedAudio: _isAnimationAudioEnabled,
                    isPlayingAudio: _isAudioEnabled,
                    onToggleAnimationAudio: _toggleAudio,
                    onToggleBackAudio: _toggleAudioAnimation,
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }),
);

解决方案二:调整布局层级,分离背景与滚动内容

将视频背景作为Scaffold的底层,可滚动内容放在Stack上层,避免滚动视图与背景布局冲突:

return Scaffold(
  resizeToAvoidBottomInset: true,
  body: Stack(
    children: [
      // 视频背景作为底层布局
      _controller.value.isInitialized
          ? SizedBox.expand(
              child: FittedBox(
                fit: BoxFit.cover,
                child: SizedBox(
                  width: _controller.value.size.width ?? 0,
                  height: _controller.value.size.height ?? 0,
                  child: VideoPlayer(_controller),
                ),
              ),
            )
          : Container(color: Colors.black),
      // 可滚动内容放在上层,直接绑定键盘事件
      OrientationBuilder(builder: (context, orientation) {
        return SingleChildScrollView(
          reverse: true,
          child: Container(
            width: double.infinity,
            child: Column(
              children: [
                SizedBox(
                  height: isTab ? 20 : 53.h,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Padding(
                      padding: EdgeInsets.only(left: screenWidth * 0.02),
                      child: InkWell(
                        onTap: () {
                          _controller.pause();
                          _controller.dispose();
                          Navigator.of(context).push(
                              createFadeInRoute(const HomeScreen()));
                        },
                        child: Container(
                          alignment: Alignment.center,
                          width: isTab ? 28 : 28,
                          height: isTab ? 28 : 28,
                          decoration: BoxDecoration(
                            color: const Color(0xFF75ABC9),
                            borderRadius: BorderRadius.circular(5),
                            boxShadow: const [
                              BoxShadow(
                                color: Color(0xFF192D5D),
                                offset: Offset(0, 1),
                                blurRadius: 3,
                              ),
                            ],
                          ),
                          child: Padding(
                            padding: const EdgeInsets.only(left: 6),
                            child: Icon(
                              Icons.arrow_back_ios,
                              color: Colors.white,
                              size: isTab ? 23 : 18,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                SizedBox(
                  height: isTab
                      ? (orientation == Orientation.portrait
                          ? screenHeight * 0.20
                          : screenHeight * 0.280)
                      : screenWidth < 390
                          ? 170.h
                          : 170.h,
                ),
                ChatBox(
                  profilePic: widget.profilePic,
                  userd: widget.guruUserId,
                  isPlayingAnimatedAudio: _isAnimationAudioEnabled,
                  isPlayingAudio: _isAudioEnabled,
                  onToggleAnimationAudio: _toggleAudio,
                  onToggleBackAudio: _toggleAudioAnimation,
                )
              ],
            ),
          ),
        );
      }),
    ],
  ),
);

额外注意事项

  • 确保ChatBox内部的TextField没有被固定高度的容器包裹,否则会限制滚动视图的上推范围。
  • 若使用方案一,需保证SingleChildScrollView的reverse: true属性保留,确保键盘弹出时内容向顶部滚动。

内容的提问来源于stack exchange,提问作者Sahil Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:54:52