簡體   English   中英

在 Flutter 中僅使一個小部件浮在鍵盤上方

[英]Make only one widget float above the keyboard in Flutter

我想在鍵盤可見時在鍵盤上方顯示一個“關閉鍵盤”按鈕。

我知道 resizeToAvoidBottomInset 會影響鍵盤與應用程序的 rest 交互的方式,但它並不能完全滿足我的要求。

我有一個背景圖像和其他小部件(未在下面的示例中顯示),它們在顯示鍵盤時不應調整大小和移動。 resizeToAvoidBottomInset屬性設置為 false 時,這是一個正常的行為。

但是,我想添加一個應該出現在鍵盤上方的按鈕。

我怎樣才能做到這一點? 我只希望一個小部件漂浮在鍵盤上方,而不是所有應用程序。

這是一個示例代碼:

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: 0,
        left: 0,
        right: 0,
        child: Container(
          height: 50,
          child: Text("Aboveeeeee"),
          decoration: BoxDecoration(color: Colors.pink),
        ),
      ),
    ]);
  }
}

您的Positioned小部件的bottom為 0,用適當的值替換應該可以完成這項工作。

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("Aboveeeeee"),
          decoration: BoxDecoration(color: Colors.pink),
        ),
      ),
    ]);
  }
}

gif

為了實現基於鍵盤可見性的動畫填充,這里是對@10101010 的好答案的一些修改:

如果您希望在鍵盤更改可見性時bottom更改為動畫,並且您希望在浮動子項下有額外的填充,那么:

1- 使用keyboard_visibility flutter pub

要在鍵盤出現/消失時收聽,如下所示:

  bool isKeyboardVisible = false;

  @override
  void initState() {
    super.initState();

    KeyboardVisibilityNotification().addNewListener(
      onChange: (bool visible) {
        isKeyboardVisible = visible;
      },
    );
  }

您可以選擇編寫自己的本機插件,但它已經存在,您可以檢查 pub 的 git repo。

2- 在AnimatedPostioned可見性標志:

對於微調的動畫填充,如下所示:

Widget _getBody() {
    double bottomPadding = 0;
    if (isKeyboardVisible) {
      // when keyboard is shown, our floating widget is above the keyboard and its accessories by `16`
      bottomPadding = MediaQuery.of(context).viewInsets.bottom + 16;
    } else {
      // when keyboard is hidden, we should have default spacing
      bottomPadding = 48; // MediaQuery.of(context).size.height * 0.15;
    }

    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()],
        ),
      ),
      AnimatedPositioned(
        duration: Duration(milliseconds: 500),
        bottom: bottomPadding,
        left: 0,
        right: 0,
        child: Container(
          height: 50,
          child: Text("Aboveeeeee"),
          decoration: BoxDecoration(color: Colors.pink),
        ),
      ),
    ]);
}

3- 鍵盤特定的動畫曲線和同步動畫的持續時間

目前這仍然是一個已知的持續問題

檢查這個包,它可以在鍵盤上方顯示一個關閉按鈕。

您可以使用 Scaffold 的 bottomSheet 參數,它可以保持一個持久的底部表。 見下面的代碼。

class InputScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Close')),
      bottomSheet: Container(
          padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
          color: Colors.black,
          child: const SizedBox(width: double.infinity, height: 10)),
      body: Column(
        children: [
          const TextField(
            decoration: InputDecoration(
              border: OutlineInputBorder(),
              hintText: 'Enter your input here',
            ),
          ),
          ElevatedButton(
            onPressed: () {},
            child: const Text('Submit'),
          ),
        ],
      ),
    );
  }
}

您可以使用Scaffold小部件的bottomSheet

例子:

    return Scaffold(
      appBar: AppBar(
        title: const Text("New Game"),
      ),
      bottomSheet: Container(
          padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
          color: Colors.blue,
          child: const SizedBox(
            width: double.infinity,
            height: 20,
            child: Text("Above Keyboard"),
          ))
...
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM