【问题标题】:How to make widget stick to top of keyboard如何使小部件粘在键盘顶部
【发布时间】:2018-09-17 20:06:24
【问题描述】:

我想制作一个贴在页面底部的小部件,然后固定在键盘顶部(当它出现时)。

请注意下图中输入文本字段是如何固定到键盘的:

我该怎么做?我试着把它放在bottomNavigationBar 中,但这(显然)没有用。有没有内置的方法可以做到这一点?

【问题讨论】:

  • 我手头没有代码。但我认为你可以通过制作脚手架来做到这一点。在脚手架的主体中放置一个扩展的。扩展的孩子是您的聊天消息等。在扩展下,您可以像在什么应用程序中一样放置文本框。如果您将其放在展开后的下方,则展开后的内容将不断扩展到屏幕的末尾,从而为文本框留出足够的空间。如果你想不出来,我会试试的。告诉我!

标签: keyboard flutter


【解决方案1】:

这是您想要的东西的一个工作示例。我想! 只需复制/粘贴/运行

此示例中重要的是展开。一个非常好的小部件,可以扩展到尽可能多的空间。结果是尽可能地将聊天框向下推
(屏幕底部或键盘底部)

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
    // This widget is the root of your application.
    @override
    Widget build(BuildContext context) {
        return new MaterialApp(
            title: 'Flutter Demo',
            theme: new ThemeData(
                primarySwatch: Colors.blue,
            ),
            home: new MyHomePage(title: 'Flutter Demo Home Page'),
        );
    }
}

class MyHomePage extends StatefulWidget {
    MyHomePage({Key key, this.title}) : super(key: key);
    final String title;

    @override
    _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

    @override
    Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(
                title: new Text('49715760 Stackoverflow'),
            ),
            body: new Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                    new Expanded(
                        child: new Material(
                            color: Colors.red,
                            child: new Text("Filled"),
                        ),
                    ),
                    new Container(
                        color: Colors.white,
                        padding: new EdgeInsets.all(10.0),
                        child: new TextField(
                            decoration: new InputDecoration(
                                hintText: 'Chat message',
                            ),
                        ),
                    ),
                ],
            ),
        );
    }
}

【讨论】:

  • 安卓示例?
  • 遗憾的是,此解决方案与其他解决方案相似,因为它并不理想,因为 TextField 以与键盘不同的速度移动到其新位置,导致动画不太理想。
【解决方案2】:

解决此问题的最佳方法是使用专用小部件。

MediaQuery.of(context).viewInsets.bottom 将为您提供系统 UI(在本例中为键盘)覆盖的高度值。

import 'dart:async';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var home = MyHomePage(title: 'Flutter Demo Home Page');
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: home,
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _getBody(),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }

  Widget _getBody() {
    return Stack(children: <Widget>[
      Container(
        decoration: BoxDecoration(
            image: DecorationImage(
                image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
        // color: Color.fromARGB(50, 200, 50, 20),
        child: Column(
          children: <Widget>[TextField()],
        ),
      ),
      Positioned(
        bottom: MediaQuery.of(context).viewInsets.bottom,
        left: 0,
        right: 0,
        child: Container(
          height: 50,
          child: Text("Hiiiii"),
          decoration: BoxDecoration(color: Colors.pink),
        ),
      ),
    ]);
  }
}

【讨论】:

  • 谢谢!使用 Positioned + MediaQuery 搞定了 :)
  • 这是一个不错的干净解决方案,但并不理想,因为 TextField 以与键盘不同的速度移动到新位置,导致动画效果不太理想。
【解决方案3】:

有一个库:

https://pub.dev/packages/keyboard_attachable

Widget build(BuildContext context) => FooterLayout(
    footer: MyFooterWidget(),
    child: PageMainContent(),
);

【讨论】:

    【解决方案4】:

    使用 Scaffold 中的 bottomSheet 选项。

    Scaffold(
        bottomSheet: chatBar(),
        body: Column(
               children: [
                  Expanded(
                   child: ListView()
                  )
               ]
             )
        )
    

    当键盘打开时,聊天栏位于键盘顶部。

    对于透明的聊天栏:可以用 Scaffold 包裹

    Theme(
              data: ThemeData.light().copyWith(
                  bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.transparent),
                  
              ),
    

    【讨论】:

      【解决方案5】:

      这对我有用,

      showBottomSheet(
        context: context,
        builder: (context) => Container(
        height: // YOUR WIDGET HEIGHT
        child: // YOUR CHILD
      )
      

      showBottomSheet 是一个 Flutter 内置函数。

      【讨论】:

        【解决方案6】:

        mohammad byervand 的解决方案确实是最好的。但请记住,如果您设置 android:windowSoftInputMode="adjustPan",它将不起作用。与 MediaQuery.of(context).viewInsets.bottom 和 resizeToAvoidBottomInset: false 一样

        【讨论】:

          猜你喜欢
          • 2019-04-21
          • 1970-01-01
          • 2022-08-17
          • 2015-12-09
          • 1970-01-01
          • 2011-04-12
          • 1970-01-01
          • 1970-01-01
          • 2019-05-04
          相关资源
          最近更新 更多