久久精品国产亚洲高清|精品日韩中文乱码在线|亚洲va中文字幕无码久|伊人久久综合狼伊人久久|亚洲不卡av不卡一区二区|精品久久久久久久蜜臀AV|国产精品19久久久久久不卡|国产男女猛烈视频在线观看麻豆

    1. <style id="76ofp"></style>

      <style id="76ofp"></style>
      <rt id="76ofp"></rt>
      <form id="76ofp"><optgroup id="76ofp"></optgroup></form>
      1. 千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機構

        手機站
        千鋒教育

        千鋒學習站 | 隨時隨地免費學

        千鋒教育

        掃一掃進入千鋒手機站

        領取全套視頻
        千鋒教育

        關注千鋒學習站小程序
        隨時隨地免費學習課程

        當前位置:首頁  >  技術干貨  > Flutter鍵盤頂起底部

        Flutter鍵盤頂起底部

        來源:千鋒教育
        發(fā)布人:xqq
        時間: 2023-11-23 00:46:24 1700671584

        在Flutter中,打開鍵盤后,我們可能希望底部的內(nèi)容不被覆蓋。Flutter提供了一些方法來實現(xiàn)這一點。下面將從多個方面詳細闡述如何使用Flutter實現(xiàn)鍵盤頂起底部的效果。

        一、使用SingleChildScrollView

        使用SingleChildScrollView可以讓底部內(nèi)容在鍵盤彈出時自動滾動到可見區(qū)域。我們只需要將底部內(nèi)容包裹在SingleChildScrollView中,并在頁面初始化時獲得一個GlobalKey,然后在鍵盤彈出后通過該GlobalKey定位到bottom widget的位置,再通過動畫滾動到該位置。

        class MyWidget extends StatefulWidget {
          @override
          _MyWidgetState createState() => _MyWidgetState();
        }
        
        class _MyWidgetState extends State {
          final GlobalKey _bottomWidgetKey = GlobalKey();
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              body: SingleChildScrollView(
                child: Column(
                  children: [
                    // other widgets
                    Container(
                      key: _bottomWidgetKey,
                      child: // bottom widget
                    ),
                  ],
                ),
              ),
              appBar: AppBar(
                title: Text("Keyboard"),
              ),
              floatingActionButton: FloatingActionButton(
                onPressed: () {
                  // Show the keyboard
                  FocusScope.of(context).requestFocus(FocusNode());
                },
                child: Icon(Icons.add),
              ),
            );
          }
        
          @override
          void initState() {
            super.initState();
            final BottomWidgetRenderBox =
                _bottomWidgetKey.currentContext.findRenderObject() as RenderBox;
            SchedulerBinding.instance!.addPostFrameCallback((_) {
              Future.delayed(const Duration(milliseconds: 300)).then((_) {
                final RenderBox keyboard =
                    context.findRenderObject() as RenderBox;
                final keyboardHeight = keyboard.size.height;
                final heightDiff =
                    keyboardHeight - (MediaQuery.of(context).viewInsets.bottom);
                final double offsetY =
                    heightDiff > 0 ? -(BottomWidgetRenderBox.size.height + heightDiff) : 0;
                if (offsetY != 0) {
                  _controller.animateTo(
                      _controller.offset + offsetY,
                      duration: new Duration(milliseconds: 300),
                      curve: Curves.easeOut);
                }
              });
            });
          }
        }

        二、使用ListView

        如果你希望底部內(nèi)容可以滾動,我們可以使用ListView。ListView將自動在鍵盤彈出時滾動到底部,并且可以讓用戶滾動以查看所有內(nèi)容。

        class MyWidget extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              body: Column(
                children: [
                  Expanded(
                    child: ListView(
                      children: [
                        // other widgets
                        // bottom widget
                      ],
                    ),
                  ),
                  // input widget
                ],
              ),
              appBar: AppBar(
                title: Text("ListView"),
              ),
            );
          }
        }

        三、使用Stack和AnimatedPositioned

        使用Stack和AnimatedPositioned可以在鍵盤彈出時自動調(diào)整底部內(nèi)容的位置,使其不被鍵盤遮擋。我們可以將輸入框作為Stack的子元素,然后將底部內(nèi)容作為Stack的第二個子元素。在鍵盤彈出時,我們可以使用AnimatedPositioned調(diào)整第二個子元素的位置。

        class MyWidget extends StatefulWidget {
          @override
          _MyWidgetState createState() => _MyWidgetState();
        }
        
        class _MyWidgetState extends State {
          GlobalKey _globalKey = GlobalKey();
        
          double _bottom = 0;
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              resizeToAvoidBottomInset: false,
              appBar: AppBar(
                title: Text("Stack and AnimatedPositioned"),
              ),
              body: Stack(
                children: [
                  Positioned(
                    top: 0,
                    bottom: 0,
                    left: 0,
                    right: 0,
                    child: GestureDetector(
                      onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
                      child: Container(
                        color: Colors.white,
                        child: SingleChildScrollView(
                          child: Column(
                            key: _globalKey,
                            children: [
                              // other widgets
                              Container(
                                height: 800,
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                  AnimatedPositioned(
                    duration: Duration(milliseconds: 300),
                    bottom: _bottom,
                    left: 0,
                    right: 0,
                    child: Container(
                      color: Colors.lightBlue,
                      height: 140,
                      child: Center(
                        child: GestureDetector(
                          onTap: () {
                            FocusScope.of(context).requestFocus(FocusNode());
                          },
                          child: Text(
                            "Input",
                            style: TextStyle(
                              fontSize: 30,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            );
          }
        
          @override
          void initState() {
            super.initState();
            final RenderBox renderBoxRed = _globalKey.currentContext.findRenderObject() as RenderBox;
            WidgetsBinding.instance!.addPostFrameCallback((_) {
              double height = renderBoxRed.size.height;
              double screenHeight = MediaQuery.of(context).size.height;
              double diff = screenHeight - height;
              setState(() {
                _bottom = diff;
              });
            });
          }
        }

        四、結合SingleChildScrollView和Stack

        我們也可以結合ScrollView和Stack來實現(xiàn)鍵盤頂起底部的效果。具體操作是將輸入框與底部內(nèi)容放置在Stack中,并將Stack放置在SingleChildScrollView中。當鍵盤彈出時,可以與第一種方法類似地通過AnimationController將底部內(nèi)容滑動到屏幕中央。

        class MyWidget extends StatefulWidget {
          @override
          _MyWidgetState createState() => _MyWidgetState();
        }
        
        class _MyWidgetState extends State
            with SingleTickerProviderStateMixin {
          double _offset = 0.0;
        
          bool _isKeyboardShowing = false;
        
          late final AnimationController _controller = AnimationController(
              duration: const Duration(milliseconds: 200), vsync: this);
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              resizeToAvoidBottomInset: false,
              appBar: AppBar(
                title: Text("Stack and SingleChildScrollView"),
              ),
              body: SingleChildScrollView(
                child: Stack(
                  children: [
                    Column(
                      children: [
                        Container(
                          height: 800,
                        ),
                      ],
                    ),
                    Positioned(
                      bottom: _offset,
                      left: 0,
                      right: 0,
                      child: Container(
                        color: Colors.lightBlue,
                        height: 140,
                        child: Center(
                          child: GestureDetector(
                            onTap: () {
                              FocusScope.of(context).requestFocus(FocusNode());
                            },
                            child: Text(
                              "Input",
                              style: TextStyle(
                                fontSize: 30,
                                color: Colors.white,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            );
          }
        
          @override
          void initState() {
            super.initState();
            _controller.addListener(() {
              setState(() {
                _offset =
                    MediaQuery.of(context).viewInsets.bottom * _controller.value;
              });
            });
            _controller.addStatusListener((status) {
              if (status == AnimationStatus.completed) {
                setState(() {
                  _isKeyboardShowing = true;
                });
              } else if (status == AnimationStatus.dismissed) {
                setState(() {
                  _isKeyboardShowing = false;
                });
              }
            });
          }
        
          @override
          void dispose() {
            _controller.dispose();
            super.dispose();
          }
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              resizeToAvoidBottomInset: false,
              appBar: AppBar(
                title: Text("Stack and SingleChildScrollView"),
              ),
              body: SingleChildScrollView(
                child: Stack(
                  children: [
                    Column(
                      children: [
                        Container(
                          height: 800,
                        ),
                        GestureDetector(
                          onTap: () {
                            FocusScope.of(context).requestFocus(FocusNode());
                          }
                          child: // input widget
                        ),
                      ],
                    ),
                    Positioned(
                      bottom: _offset,
                      left: 0,
                      right: 0,
                      child: Container(
                        color: Colors.lightBlue,
                        height: 140,
                        child: Center(
                          child: GestureDetector(
                            onTap: () {
                              FocusScope.of(context).requestFocus(FocusNode());
                            },
                            child: Text(
                              "Input",
                              style: TextStyle(
                                fontSize: 30,
                                color: Colors.white,
                              ),
                            ),
                          ),
                        ),
                      ),
                    )
                  ],
                ),
              ),
            );
          }
        
          void _handleFocusChange() {
            if (FocusScope.of(context).hasFocus != _isKeyboardShowing) {
              _isKeyboardShowing = FocusScope.of(context).hasFocus;
              _controller.animateTo(
                  _isKeyboardShowing ? 1.0 : 0.0,
                  duration: const Duration(milliseconds: 150),
                  curve: Curves.linear);
            }
          }
        }

        五、小結

        本文介紹了Flutter中實現(xiàn)鍵盤頂起底部的幾種方法,包括使用SingleChildScrollView、ListView、Stack以及結合方法。在使用這些方法時,我們需要考慮底部內(nèi)容的特殊結構,確保鍵盤彈出時,底部內(nèi)容不會被遮擋。希望本文能對您在Flutter開發(fā)中實現(xiàn)鍵盤頂起底部的需求提供幫助。

        聲明:本站稿件版權均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
        10年以上業(yè)內(nèi)強師集結,手把手帶你蛻變精英
        請您保持通訊暢通,專屬學習老師24小時內(nèi)將與您1V1溝通
        免費領取
        今日已有369人領取成功
        劉同學 138****2860 剛剛成功領取
        王同學 131****2015 剛剛成功領取
        張同學 133****4652 剛剛成功領取
        李同學 135****8607 剛剛成功領取
        楊同學 132****5667 剛剛成功領取
        岳同學 134****6652 剛剛成功領取
        梁同學 157****2950 剛剛成功領取
        劉同學 189****1015 剛剛成功領取
        張同學 155****4678 剛剛成功領取
        鄒同學 139****2907 剛剛成功領取
        董同學 138****2867 剛剛成功領取
        周同學 136****3602 剛剛成功領取
        相關推薦HOT
        锦屏县| 深水埗区| 新津县| 当雄县| 河间市| 龙川县| 资中县| 临湘市| 信宜市| 德昌县| 来凤县| 凤台县| 平遥县| 望城县| 苗栗市| 凭祥市| 上杭县| 广河县| 濉溪县| 武鸣县| 米林县| 海原县| 刚察县| 留坝县| 临猗县| 邵阳市| 沙田区| 昌黎县| 横山县| 莱芜市| 鹤庆县| 海淀区| 盈江县| 阜新| 邹平县| 会理县| 铜山县| 阿荣旗| 石门县| 社会| 广宁县|