亚洲 国产精品 日韩-亚洲 激情-亚洲 欧美 91-亚洲 欧美 成人日韩-青青青草视频在线观看-青青青草影院

千鋒教育-做有情懷、有良心、有品質的職業教育機構

手機站
千鋒教育

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

千鋒教育

掃一掃進入千鋒手機站

領取全套視頻
千鋒教育

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

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

Flutter鍵盤頂起底部

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

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

一、使用SingleChildScrollView

使用SingleChildScrollView可以讓底部內容在鍵盤彈出時自動滾動到可見區域。我們只需要將底部內容包裹在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

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

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可以在鍵盤彈出時自動調整底部內容的位置,使其不被鍵盤遮擋。我們可以將輸入框作為Stack的子元素,然后將底部內容作為Stack的第二個子元素。在鍵盤彈出時,我們可以使用AnimatedPositioned調整第二個子元素的位置。

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來實現鍵盤頂起底部的效果。具體操作是將輸入框與底部內容放置在Stack中,并將Stack放置在SingleChildScrollView中。當鍵盤彈出時,可以與第一種方法類似地通過AnimationController將底部內容滑動到屏幕中央。

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中實現鍵盤頂起底部的幾種方法,包括使用SingleChildScrollView、ListView、Stack以及結合方法。在使用這些方法時,我們需要考慮底部內容的特殊結構,確保鍵盤彈出時,底部內容不會被遮擋。希望本文能對您在Flutter開發中實現鍵盤頂起底部的需求提供幫助。

聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。
10年以上業內強師集結,手把手帶你蛻變精英
請您保持通訊暢通,專屬學習老師24小時內將與您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
裸体跳舞XXXX裸体跳舞| 亚洲美女高潮久久久久| 亚洲精品无码久久毛片 | 免费A级毛片在线播放不收费| 欧美黑人巨大VIDEOS精品| 日韩一中文字无码不卡| 性色AV 一区二区三区| 一面亲上边一面膜下边文字的含义 | 99国内精品久久久久久久漫画| 暴躁老外玩MINECRAFT| 国产日韩AV免费无码一区二区 | 国产精品免费久久久久影院| 久久精品国产亚洲AV蜜桃 | 无人区码一码二码三MBA| 亚洲线精品一区二区三八戒| 八戒成年私人影院| 国产午夜手机精彩视频| 免费国产黄网站在线观看可以下载 | 凸凹人妻人人澡人人添| 亚洲自偷自偷在线成人网站传媒| 宝贝把腿张开我要添你下边动态图 | 欧美黑人XXXⅩ高潮交| 无码一区二区三区老色鬼| 又小又紧女MAGNET| 丰满大爆乳波霸奶| 久久久久噜噜噜亚洲熟女综合| 日产乱码一二三区别免费影视| 亚洲国产精品久久久久秋霞1| AV在线播放网站| 黑人疯狂巨大XXⅩ0O0| 欧洲熟妇色XXXXX视频| 亚洲AV羞羞无码高潮喷水好爽| ASS黑森林PIC| 黑人狂虐中国人妻陈艳| 人妻巨大乳挤奶水HD免费看| 亚洲AV无码片VR一区二区三区| AV无码AV天天AV天天爽| 狠狠色丁香婷婷亚洲综合| 人C交ZO〇Z〇〇XX| 亚洲欧美中文日韩V在线观看不卡| 把她送上一个又一个巅峰| 精品久久久噜噜噜久久久| 日韩爆乳一区二区无码| 亚洲综合欧美色五月俺也去| 国产成人精欧美精品视频| 男人吃奶摸下挵进去好爽在线观看 | 秋霞网一区二区三区| 亚洲日韩电影久久| 国产AⅤ无码旗袍丝袜美腿| 狼人视频国产在线视频WWW色| 我被八个男人玩到早上| 95W乳液78WYW永久区域| 国内自拍视频一区二区三区| 日本肉体XXXX裸交| 尤物在线视频.YW163.成年| 国产女人喷潮视频免费| 人妻在夫面前被性爆| 野兽的夜晚第四季忘不掉的前任| 国产精品宾馆在线精品酒店 | AV无码AV无码专区| 精品亚洲国产成人小电影| 少妇色欲av永久性精品爽妇| 999国产精品999久久久久久| 精品综合久久久久久97超人| 无码人妻一区二区三区一| 宝贝把腿抬高点我让你更爽漫画| 久拍国产在线观看| 亚洲AV永久精品无码| 丰满老熟好大BBBXXX| 欧美性大片XXXXX久久久| 亚洲愉拍自拍欧美精品| 国产精品丝袜黑色高跟鞋| 日本一线二线三线四线五线| 综合人妻久久一区二区精品| 精品人妻系列无码人妻不卡| 无码中文字幕VA精品影院| 粗壮挺进邻居人妻无码| 欧美人妻体内射射| 伊伊人成亚洲综合人网7777| 激情内射日本一区二区三区| 无码人妻av一区二区三区毛片 | 精品国产一区二区三区AV片| 婷婷五月深爱憿情网六月综合| А√在线天堂官网| 女の乳搾りです在线观看| 亚洲中文无码永久在线电影| 国自产精品手机在线观看视频| 偷拍 亚洲 欧洲 综合| 初小VIDEOS第一次摘花| 全国主要城市天气预报| 18禁美女黄网站色大片免费看 | 国产亚洲成AV人片在线观黄桃| 少妇丰满大乳被男人揉捏视频| 99在线精品视频在线观看| 免费光看午夜请高视频| 用舌头去添高潮无码AV在线观看| 极品女教师波多野结衣电影衣 | 精品无人区麻豆乱码1区2| 亚洲AV成人午夜在线看见网站| 国产精品99无码一区二区| 熟妇高潮一区二区精品| 饭桌上故意张开腿让公在线观| 人人妻人人澡人人爽人人蜜臀| 99精品国产一区二区三区| 免费无码又爽又高潮视频| 呦香8黝黝狖呦香8| 久久婷婷五月综合色区| 一区三区四区产品乱码| 久久久久久精品免费免费英国| 亚洲日韩精品无码专区加勒比 | 熟女体下毛毛黑森林| 丰满人妻被中出中文字幕| 色惰日本视频网站WWW| 大波妺AV网站影院| 少妇极品熟妇人妻200片| 丰满人妻无码AⅤ一区二区| 色悠久久久久综合先锋影音下载| 大BBW大BBW超大BBW| 熟妇的荡欲乱色欲av浪潮| 国产成人精品2021| 无码AV在线一本无码| 国产精品久久久久久免费软件| 无码H黄肉动漫在线观看| 国产人成无码视频在线观看| 亚洲AⅤ在线无码播放毛片一线天| 国内极度色诱视频网站| 亚洲国产欧美在线人成长黄瓜| 精品少妇无码AV在线播放| 野花高清在线观看免费官网中文版| 久久久久免费看成人影片| 在线播放国产精品三级网| 没带罩子被校霸C了一节课怎么办| 最新精品国偷自产在线下载| 欧美猛片BBBBBⅩXXXX| 把插八插露脸对白内射| 色偷偷88888欧美精品久久久| 国产SM调教视频在线观看| 小雪尝禁果又粗又大的中国地图| 黑人巨大精品欧美一区二区| 亚洲熟妇无码另类久久久| 猫咪AV最新永久网址无码| GAY国产GV又粗又长又大| 日韩精品久久久久久久电影蜜臀 | 天堂8中文在线最新版官网| 国产日韩未满十八禁止观看 | 无码办公室丝袜OL中文字幕| 国产香蕉97碰碰视频VA碰碰看| 亚洲精品无码久久久久秋霞| 裸体美女洗澡啪啪裸J网站| 锕锕锕锕锕~好深啊APP网站| 色天使亚洲综合一区二区 | 肥臀浪妇太爽了快点再快点| 无码少妇一区二区性色AV| 精品国产18久久久久久| 在线观看无码H片| 人妻丰满AV中文久久不卡| 国产盗摄XXXX视频XXXX| 亚洲国产欧美在线人成大黄瓜| 免费看又黄又无码的网站| 成人毛片一区二区| 性做久久久久久久久| 久久丫精品国产亚洲AV不卡| CHINASEXSEX高潮对白| 天天天狠天天碰天天爱| 精品人妻系列无码人妻在线不 | 亚洲日本乱人伦片中文| 欧美成人精品一区二区| 国产AV无码专区亚洲AV中文 | 亚洲AV无码专区国产乱码京东传| 久久香蕉国产线看观看亚洲小说 | 英语老师的小兔子好大好软水| 秋霞国产午夜伦午夜无码灬| 国产精品内射后入合集| 一本加勒比波多野结衣高清| 人妻体内射精一区二区三四| 国产午夜成人精品视频APP| 在线观看ww亚洲精品| 色悠久久久久综合网国产| 精品无码国产自产拍在线观看蜜 | 色五月五月丁香亚洲综合网| 寂寞视频一对一视频APP| JIZZJIZZJIZZ日本丰| 亚洲A∨无码男人的天堂| 免费观看四虎精品国产地址| 国产AV成人精品播放| 亚洲综合激情另类小说区| 日韩AV高清在线观看| 精品亚洲国产AⅤ在线| 被下春药爽翻天按摩的人妻| 亚洲А∨天堂久久精品PPYPP| 女人被狂躁c到高潮视频| 国产精品自在拍首页视频8| 中文在线А√天堂官网| 无码成人免费AV片在线观看| 老狼一区忘忧草欢迎您大豆男男 | 丰满人妻妇伦又伦精品国产| 亚洲中文字幕久久精品无码VA| 日韩一区二区三区精品视频| 久久久精品久久久久久96| 国产95在线 | 欧美|