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

Flutter中如何将TextFormField定位在屏幕底部且键盘弹出时自动上移

Flutter 底部固定输入框随键盘同步上浮解决方案

问题原因

  • 你当前将TextFormField放在了SingleChildScrollView内部的Column中,属于滚动内容的一部分,无法固定在屏幕底部,也无法跟随键盘触发的布局调整自动上移。

实现方案

调整Scaffold的布局结构即可实现需求:

  1. 将Scaffold的body改为Column结构,第一部分用Expanded包裹原有的SingleChildScrollView(包含帖子详情、评论列表等所有需要滚动的内容),第二部分直接放置输入框组件
  2. Scaffold默认开启resizeToAvoidBottomInset: true属性,键盘唤起时会自动压缩页面可用高度,底部输入框就会同步跟随键盘上移

核心代码修改示例

import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:untitled/ui/view/threadModel/thread_viewmodel.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:untitled/ui/view/comment_view.dart';
import 'package:flutter/services.dart';

class ThreadView extends StatelessWidget {
// const ThreadView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ViewModelBuilder<ThreadViewModel>.reactive(
  builder: (context, model, child) => Scaffold(
    // 该属性默认就是true,不需要额外配置,不要手动改为false
    resizeToAvoidBottomInset: true,
    appBar: AppBar(
      systemOverlayStyle: SystemUiOverlayStyle(
        statusBarColor: HexColor('00b87c'),
      ),
      backgroundColor: Colors.white,
      toolbarHeight: 54,
      leading: Icon(
        Icons.arrow_back_ios_rounded,
        color: HexColor('#333333'),
        size: 16,
      ),
      titleSpacing: 0,
      title: Text(
        model.threads,
        style: GoogleFonts.lato(
          textStyle: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.w700,
            fontStyle: FontStyle.normal,
            color: HexColor('#201e1f'),
          ),
        ),
      ),
    ),
    // body改为Column结构
    body: Column(
      children: [
        // 滚动内容用Expanded包裹,占除输入框外的所有高度
        Expanded(
          child: SingleChildScrollView(
            physics: BouncingScrollPhysics(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Container(
                  child: ConstrainedBox(
                    constraints: BoxConstraints(minHeight: 212),
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(16, 16, 21, 16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Row(
                            children: [
                              SizedBox(height: 16),
                              Text(
                                'Message in',
                                style: GoogleFonts.lato(
                                  fontWeight: FontWeight.w400,
                                  fontSize: 14,
                                  fontStyle: FontStyle.normal,
                                  color: HexColor('#727272'),
                                ),
                              ),
                              SizedBox(
                                width: 4,
                              ),
                              Icon(
                                Icons.lock,
                                size: 12,
                                color: HexColor('#1A61DB'),
                              ),
                              SizedBox(
                                width: 4,
                              ),
                              Text(
                                'team-socrates',
                                style: GoogleFonts.lato(
                                  color: HexColor('#1A61DB'),
                                  fontSize: 12,
                                  fontStyle: FontStyle.normal,
                                  fontWeight: FontWeight.w600,
                                ),
                              ),
                            ],
                          ),
                          SizedBox(
                            height: 16,
                          ),
                          Row(
                            children: [
                              Container(
                                decoration: BoxDecoration(
                                  border: Border.all(
                                    color: Colors.white,
                                  ),
                                  borderRadius: BorderRadius.all(
                                    Radius.circular(4),
                                  ),
                                ),
                                width: 42,
                                height: 42,
                                child: FittedBox(
                                  child: Image.asset('images/Rectangle 172.png'),
                                  fit: BoxFit.fill,
                                ),
                              ),
                              SizedBox(
                                width: 16,
                              ),
                              Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  Row(
                                    children: [
                                      Text(
                                        'princessliz',
                                        style: GoogleFonts.lato(
                                          fontWeight: FontWeight.w700,
                                          fontStyle: FontStyle.normal,
                                          fontSize: 16,
                                        ),
                                      ),
                                      Container(
                                        margin: EdgeInsets.only(left: 4.0),
                                        height: 14,
                                        width: 14,
                                        child:
                                            Image.asset('images/Group 1280.png'),
                                      ),
                                    ],
                                  ),
                                  SizedBox(
                                    height: 4,
                                  ),
                                  Text(
                                    '30 Aug at 20:31',
                                    style: GoogleFonts.lato(
                                        fontWeight: FontWeight.w400,
                                        fontSize: 12,
                                        fontStyle: FontStyle.normal),
                                  )
                                ],
                              ),
                              Icon(
                                Icons.bookmark_border_outlined,
                                size: 18,
                              ),
                            ],
                          ),
                          SizedBox(
                            height: 12,
                          ),
                          Text(
                            "Aristotle - @caculuz.,\n"
                            "Aquinas - @caculuz.,\n"
                            "Socrates - @Feranmi..",
                            style: GoogleFonts.lato(
                              fontWeight: FontWeight.w400,
                              fontSize: 16,
                              fontStyle: FontStyle.normal,
                              height: 1.3,
                              color: HexColor('#424141'),
                            ),
                          ),
                          SizedBox(
                            height: 16,
                          ),
                          Container(
                            decoration: BoxDecoration(
                              color: HexColor('#93B0E1'),
                              borderRadius: BorderRadius.all(
                                Radius.circular(5),
                              ),
                              border: Border.all(
                                color: HexColor('#1a61db'),
                              ),
                            ),
                            width: 45,
                            height: 25,
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Image.asset(
                                  "images/po.png",
                                  width: 16,
                                  height: 16,
                                ),
                                SizedBox(
                                  width: 4,
                                ),
                                Text(
                                  '3',
                                  style: GoogleFonts.lato(
                                      fontSize: 12,
                                      fontStyle: FontStyle.normal,
                                      fontWeight: FontWeight.w700),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
                Divider(
                  color: HexColor('#7b8794'),
                ),
                Padding(
                  padding: EdgeInsets.fromLTRB(16, 12, 20, 13),
                  child: Container(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          "1 reply",
                          style: GoogleFonts.lato(
                            fontWeight: FontWeight.w600,
                            fontStyle: FontStyle.normal,
                            fontSize: 15,
                            color: HexColor('#424141'),
                          ),
                        ),
                        Row(
                          children: [
                            Icon(
                              Icons.forward_outlined,
                              size: 24,
                              color: HexColor('#424141'),
                            ),
                            SizedBox(
                              width: 33.92,
                            ),
                            Icon(
                              Icons.more_vert_rounded,
                              color: HexColor('#424141'),
                              size: 24,
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Divider(
                  color: HexColor('#7b8794'),
                ),
                Comment(),
                // 删掉原来放在这里的输入框代码
              ],
            ),
          ),
        ),
        // 输入框移到这里,固定在Column底部
        Container(
          // 可根据需求加背景色、内边距等样式
          padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
          child: TextFormField(
            decoration: InputDecoration(
              contentPadding: EdgeInsets.fromLTRB(16, 12, 8, 12),
              hintText: "Add a reply",
            ),
          ),
        ),
      ],
    ),
  ),
  viewModelBuilder: () => ThreadViewModel(),
);
}
}

补充注意事项

  • 可以给输入框外层Container增加底部安全区适配,避免全面屏设备上输入框被系统手势条遮挡:padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom)
  • 如果需要在输入框右侧加发送、表情等操作按钮,直接在输入框所在的Container中嵌套Row布局即可

内容的提问来源于stack exchange,提问作者Emmanuel Ekpenyong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:39:03