国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter:自定義組件的上下左右彈出層

這篇具有很好參考價(jià)值的文章主要介紹了Flutter:自定義組件的上下左右彈出層。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

背景

最近要使用Flutter實(shí)現(xiàn)一個(gè)下拉菜單,需求就是,在當(dāng)前組件下點(diǎn)擊,其下方彈出一個(gè)菜單選項(xiàng),如下圖所示:

Flutter:自定義組件的上下左右彈出層,Flutter點(diǎn)石成金,flutter,Flutter開(kāi)發(fā),Flutter實(shí)現(xiàn)彈出層,Flutter彈出框

實(shí)現(xiàn)起來(lái),貌似沒(méi)什么障礙,在Flutter中本身就提供了彈出層PopupMenuButton組件和showMenu方法,于是開(kāi)搞,代碼如下:

PopupMenuButton<String>(
      initialValue: '下拉菜單一',
      child: const Text("下拉菜單"),
      itemBuilder: (context) {
        return <PopupMenuEntry<String>>[
          const PopupMenuItem<String>(
            value: '下拉菜單一',
            child: Text('下拉菜單一'),
          ),
          const PopupMenuItem<String>(
            value: '下拉菜單二',
            child: Text('下拉菜單二'),
          ),
          const PopupMenuItem<String>(
            value: '下拉菜單三',
            child: Text('下拉菜單三'),
          )
        ];
      },
    )

直接使用showMenu也行,代碼如下:

 showMenu(
            context: context,
            position: const RelativeRect.fromLTRB(0, 0, 0, 0),
            items: <PopupMenuEntry>[
              const PopupMenuItem(value: "下拉菜單一",child: Text("下拉菜單一"),),
              const PopupMenuItem(value: "下拉菜單二",child: Text("下拉菜單二"),),
              const PopupMenuItem(value: "下拉菜單三",child: Text("下拉菜單三"),),
            ]);

PopupMenuButton運(yùn)行看結(jié)果:

Flutter:自定義組件的上下左右彈出層,Flutter點(diǎn)石成金,flutter,Flutter開(kāi)發(fā),Flutter實(shí)現(xiàn)彈出層,Flutter彈出框

showMenu位置傳的是左上角,這個(gè)就不貼圖了。

看到效果后,我詫異了,這也不符合我的需求啊,直接把選項(xiàng)給我蓋住了,這還得了,況且位置也不對(duì)啊,怎么搞?還好,無(wú)論使用PopupMenuButton還是showMenu,都給我們提供了位置。

PopupMenuButton設(shè)置位置:

offset: Offset(dx, dy)

showMenu設(shè)置位置:

 position: const RelativeRect.fromLTRB(left, top, right, bottom)

使用位置后,我們?cè)倏葱Ч?/p>

dx設(shè)置為0,dy設(shè)置為50:

PopupMenuButton<String>(
      initialValue: '下拉菜單一',
      offset: const Offset(0, 50),
      itemBuilder: (context) {
        return <PopupMenuEntry<String>>[
          const PopupMenuItem<String>(
            value: '下拉菜單一',
            child: Text('下拉菜單一'),
          ),
          const PopupMenuItem<String>(
            value: '下拉菜單二',
            child: Text('下拉菜單二'),
          ),
          const PopupMenuItem<String>(
            value: '下拉菜單三',
            child: Text('下拉菜單三'),
          )
        ];
      },
      child: Text(
        "下拉菜單",
        key: _key,
      ),
    )

效果如下圖:

Flutter:自定義組件的上下左右彈出層,Flutter點(diǎn)石成金,flutter,Flutter開(kāi)發(fā),Flutter實(shí)現(xiàn)彈出層,Flutter彈出框

這樣看起來(lái)確實(shí)好多了,但是我的疑問(wèn)就來(lái)了,如果我想實(shí)現(xiàn)在左邊展示呢?在上邊、右邊,甚至左上右上,左下右下呢?通過(guò)坐標(biāo)計(jì)算,確實(shí)能實(shí)現(xiàn),但是計(jì)算起來(lái)麻煩,也不精確,很難作為上上策,再者,這種彈窗方式樣式,在實(shí)際開(kāi)發(fā)中也很難滿足我們的需求。

既然原生的組件無(wú)法滿足我們的需求,怎么搞?只有自定義一個(gè)組件了。

今天的內(nèi)容大致如下:

1、自定義彈出層效果一覽

2、彈出層邏輯實(shí)現(xiàn)

3、使用注意事項(xiàng)

4、源碼

一、自定義彈出層效果一覽

目前自定義的組件,可以在目標(biāo)組件,左、上、右、下,左上、右上,左下、右下八個(gè)方向進(jìn)行精確的彈出,當(dāng)然了,除此之外,也可以動(dòng)態(tài)的展示到自己想要的位置,并且彈出層效果可以自定義,效果是我彈出了一個(gè)黑色矩形,你可以彈出一個(gè)列表,一個(gè)圖片等等。

Flutter:自定義組件的上下左右彈出層,Flutter點(diǎn)石成金,flutter,Flutter開(kāi)發(fā),Flutter實(shí)現(xiàn)彈出層,Flutter彈出框

?

二、彈出層邏輯實(shí)現(xiàn)

1、懸浮在其他頂部小部件之上

為了更好的展示彈出效果,和不影響UI層的相關(guān)邏輯,針對(duì)彈出層,我們可以懸浮在內(nèi)容層之上,做透明處理即可,這里使用到了Overlay對(duì)象,它是一個(gè)類似懸浮小彈窗,如Toast,安卓的PopupWindow效果。

相關(guān)代碼如下,創(chuàng)建OverlayEntry,并插入到Overlay中,這樣就可以把OverlayEntry中構(gòu)建的小部件疊加懸浮在其他頂部小部件之上。

OverlayState overlayState = Overlay.of(key.currentContext!);

OverlayEntry _overlayEntry = OverlayEntry();

overlayState.insert(_overlayEntry!);

?

2、獲取彈出目標(biāo)組件的左上右下

所謂目標(biāo)組件,就是,你想要在哪個(gè)組件(左上右下)進(jìn)行彈出,確定了目標(biāo)組件之后,為了使彈出層,精確的展示在目標(biāo)組件的方位,需要拿到目標(biāo)組件的位置,也就是左上右下的位置,這里使用到了GlobalKey作為獲取方式,具體的位置信息獲取如下:

///獲取組件的位置
  static WidgetSize getWidgetSize(GlobalKey key) {
    //獲取組件的位置,在左上右下
    final RenderBox renderBox =
        (key.currentContext?.findRenderObject() as RenderBox);
    final left = renderBox.localToGlobal(Offset.zero).dx; //左邊
    final top = renderBox.localToGlobal(Offset(renderBox.size.width, 0)).dy;
    final bottom = renderBox.localToGlobal(Offset(0, renderBox.size.height)).dy;
    final right = renderBox
        .localToGlobal(Offset(renderBox.size.width, renderBox.size.height))
        .dx;
    return WidgetSize(left, top, right, bottom);
  }

創(chuàng)建記錄位置對(duì)象,用來(lái)標(biāo)記左上右下。

///組件對(duì)象,標(biāo)記左上右下
class WidgetSize {
  double left;
  double top;
  double right;
  double bottom;

  WidgetSize(this.left, this.top, this.right, this.bottom);
}

3、設(shè)置彈出層的位置

彈出層位置,這里利用到了Positioned組件,控制其left和top位置,基本上和PopupMenuButton類似,無(wú)非就是自己實(shí)現(xiàn)了位置的測(cè)量而已。

首先根據(jù)傳遞的屬性WindowDirection,確定要設(shè)置的方位。

具體各個(gè)方位計(jì)算如下:

目標(biāo)組件下邊:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)+邊距

left坐標(biāo):目標(biāo)組件的右部坐標(biāo)-彈出層的寬度/2-目標(biāo)組件寬度/2

目標(biāo)組件左邊:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)-彈出層的高度/2-目標(biāo)組件的高度/2

left坐標(biāo):目標(biāo)組件的左邊坐標(biāo)-彈出層的寬度-邊距

目標(biāo)組件上邊:

top坐標(biāo):目標(biāo)組件的上邊坐標(biāo)-彈出層的高度-邊距

left坐標(biāo):目標(biāo)組件的右部坐標(biāo)-彈出層的寬度/2-目標(biāo)組件寬度/2

目標(biāo)組件右邊:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)-彈出層的高度/2-目標(biāo)組件的高度/2

left坐標(biāo):目標(biāo)組件的右邊坐標(biāo)+邊距

目標(biāo)組件左上:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)-彈出層的高度-目標(biāo)組件的高度-邊距

left坐標(biāo):目標(biāo)組件的左邊坐標(biāo)-彈出層的寬度-邊距

目標(biāo)組件右上:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)-彈出層的高度-目標(biāo)組件的高度-邊距

left坐標(biāo):目標(biāo)組件的左邊坐標(biāo)+邊距

目標(biāo)組件左下:

top坐標(biāo):目標(biāo)組件的底部坐標(biāo)+邊距

left坐標(biāo):目標(biāo)組件的左邊坐標(biāo)-彈出層的寬度-邊距

目標(biāo)組件右下:

top坐標(biāo):目標(biāo)組件+邊距

left坐標(biāo):目標(biāo)組件右邊的坐標(biāo)+邊距

var size = getWidgetSize(key); //獲取在目標(biāo)組件的位置

    double widgetTop = 0.0;
    double widgetLeft = 0.0;
    switch (direction) {
      case WindowDirection.bottom: //下面
        widgetTop = size.bottom + margin;
        widgetLeft =
            size.right - childWidth / 2 - ((size.right - size.left) / 2);
        break;
      case WindowDirection.left: //左面
        widgetTop =
            size.bottom - childHeight / 2 - ((size.bottom - size.top) / 2);
        widgetLeft = size.left - childWidth - margin;
        break;
      case WindowDirection.top: //上面
        widgetTop = size.top - childHeight - margin;
        widgetLeft =
            size.right - childWidth / 2 - ((size.right - size.left) / 2);
        break;
      case WindowDirection.right: //右面
        widgetTop =
            size.bottom - childHeight / 2 - ((size.bottom - size.top) / 2);
        widgetLeft = size.right + margin;
        break;
      case WindowDirection.topLeft: //左上
        widgetTop =
            size.bottom - childHeight - (size.bottom - size.top) - margin;
        widgetLeft = size.left - childWidth - margin;
        break;
      case WindowDirection.topRight: //右上
        widgetTop =
            size.bottom - childHeight - (size.bottom - size.top) - margin;
        widgetLeft = size.right + margin;
        break;
      case WindowDirection.bottomLeft: //左下
        widgetTop = size.bottom + margin;
        widgetLeft = size.left - childWidth - margin;
        break;
      case WindowDirection.bottomRight: //右下
        widgetTop = size.bottom + margin;
        widgetLeft = size.right + margin;
        break;
      case WindowDirection.none: //取消 自己測(cè)量位置
        widgetTop = top;
        widgetLeft = left;
        break;
    }

三、使用注意事項(xiàng)

1、為了能夠精確的設(shè)置彈出層的位置,其彈出層的寬度和高度是必須要傳遞的,也就是childWidth和childHeight屬性。

2、如果想自己設(shè)置位置,可以不傳childWidth和childHeight,設(shè)置direction為WindowDirection.none,并且left和top坐標(biāo)需要傳遞。

3、margin屬性設(shè)置彈出層距離目標(biāo)組件的距離。

四、源碼

源碼地址

https://github.com/AbnerMing888/flutter_widget/blob/master/lib/utils/popup_window.dart

使用方式

PopupWindow.create(
              _key,
              const BaseWidget(
                width: 100,
                height: 100,
                backgroundColor: Colors.black,
              ),
              direction: direction,
              margin: 10,
              childWidth: 100,
              childHeight: 100);

參數(shù)介紹

屬性

類型

概述

key

GlobalKey

目標(biāo)組件的key

child

Widget

彈出層

childWidth

double

彈出層的寬

childHeight

double

彈出層的高

direction

WindowDirection

位置:

left//左

top//上

right//右

bottom//下

topLeft, //左上角

topRight, //右上角

bottomLeft, //左下

bottomRight, //右下

none//取消位置,自己定義

left

double

相對(duì)于屏幕的左側(cè)坐標(biāo)

top

double

相對(duì)于屏幕的頂部坐標(biāo)

margin

double

彈出層距離目標(biāo)組件的距離文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-683497.html

到了這里,關(guān)于Flutter:自定義組件的上下左右彈出層的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • [Python中矩陣上下左右翻轉(zhuǎn)(np.flip)]

    [Python中矩陣上下左右翻轉(zhuǎn)(np.flip)] 現(xiàn)代編程語(yǔ)言和相關(guān)庫(kù)的發(fā)展,使得數(shù)值計(jì)算和數(shù)據(jù)處理變得更加便捷和高效。在Python中,NumPy庫(kù)是眾多數(shù)據(jù)科學(xué)和工程應(yīng)用領(lǐng)域的重要支撐之一。其中,np.flip函數(shù)可以用于進(jìn)行矩陣的上下左右翻轉(zhuǎn)操作,是我們?cè)谔幚韴D像、信號(hào)、物理模

    2024年02月12日
    瀏覽(18)
  • vxe表格實(shí)現(xiàn)鍵盤(pán)上下左右方向鍵移動(dòng)聚焦

    vxe表格實(shí)現(xiàn)鍵盤(pán)上下左右方向鍵移動(dòng)聚焦

    vxe 表格分為 vxe-table 一般表格和 vxe-grid 高級(jí)表格,兩者之間的區(qū)別我就不說(shuō)啦,我們來(lái)實(shí)現(xiàn)這兩種表格用鍵盤(pán)按動(dòng)上下左右方向鍵達(dá)到移動(dòng)聚焦的效果。話不多說(shuō),上正文?。?! 首先在標(biāo)簽放入這兩個(gè)事件: 主要是利用vxe表格內(nèi)置的@cell-click事件,來(lái)監(jiān)聽(tīng)點(diǎn)擊單元格的行號(hào)

    2024年02月07日
    瀏覽(21)
  • Unity 控制攝像機(jī)鏡頭的上下左右移動(dòng)

    ? ? ? ? private float FollowPosx,FollowPosy; ? ? private float moveAmount=5; ? //控制鏡頭的移動(dòng)速度 ? ? // Update is called once per frame ? ? void Update() ? ? { ? ? ? ? if (Input.mousePosition.y Screen.height * 0.9)//如果鼠標(biāo)位置在頂部,就向上移動(dòng) ? ? ? ? { ? ? ? ? ? ? FollowPosy += moveAmount * Time.delta

    2024年02月11日
    瀏覽(26)
  • Ubuntu22.04上下左右全方位美化教程

    Ubuntu22.04上下左右全方位美化教程

    為了記錄和自己的反復(fù)查看,我還是用自己的方式記錄一下我的替換過(guò)程,為了回憶和共同進(jìn)步 官方文檔將 Plank 描述為“這個(gè)星球上最簡(jiǎn)潔的 dock”,其目的是僅提供一個(gè) dock 需要的功能。盡管這是很基礎(chǔ)的一個(gè)庫(kù),卻可以被擴(kuò)展,創(chuàng)造其他的含更多高級(jí)功能的 dock 程序。

    2024年02月10日
    瀏覽(24)
  • 鍵盤(pán)按鍵事件 通過(guò)鍵盤(pán)上下左右按鍵移動(dòng)界面上圖標(biāo)

    鍵盤(pán)按鍵事件 通過(guò)鍵盤(pán)上下左右按鍵移動(dòng)界面上圖標(biāo)

    #main.c文件 #include “keyevent.h” #include int main(int argc, char *argv[]) { QApplication a(argc, argv); KeyEvent w; w.show(); } #include “keyevent.h”//頭文件 #ifndef KEYEVENT_H #define KEYEVENT_H #include #include #include class KeyEvent : public QWidget { Q_OBJECT public: KeyEvent(QWidget *parent = 0); ~KeyEvent(); void drawPix(); void keyPre

    2024年02月09日
    瀏覽(21)
  • uniapp小程序—實(shí)現(xiàn)下滑關(guān)閉抽屜(包含上下左右滑動(dòng))

    uniapp小程序—實(shí)現(xiàn)下滑關(guān)閉抽屜(包含上下左右滑動(dòng))

    操作:點(diǎn)擊相應(yīng)文字時(shí)從底部出現(xiàn)彈框,下滑超過(guò)一定速率,彈框回到下方隱藏; 這個(gè)組件有些多余的地方我沒(méi)刪,可以自行擴(kuò)展。以下附帶移動(dòng)端的上下左右滑動(dòng),可以借鑒實(shí)現(xiàn)小程序的左右滑動(dòng)

    2024年02月13日
    瀏覽(21)
  • android:RecyclerView交互動(dòng)畫(huà)(上下拖動(dòng),左右滑動(dòng)刪除)

    android:RecyclerView交互動(dòng)畫(huà)(上下拖動(dòng),左右滑動(dòng)刪除)

    @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //監(jiān)聽(tīng)側(cè)滑;1.刪除數(shù)據(jù),2.調(diào)用adapter.notifyItemRemoved(position) mMoveCallback.onItemRemove(viewHolder.getAdapterPosition()); } //改變選中的Item @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { //判斷狀態(tài) if

    2024年04月12日
    瀏覽(89)
  • 上下左右視頻轉(zhuǎn)場(chǎng)模板PR項(xiàng)目工程文件 Vol. 05

    上下左右視頻轉(zhuǎn)場(chǎng)模板PR項(xiàng)目工程文件 Vol. 05

    pr轉(zhuǎn)場(chǎng)模板,視頻畫(huà)面上下左右轉(zhuǎn)場(chǎng)后帶有一點(diǎn)點(diǎn)回彈效果的PR項(xiàng)目工程模板 Vol. 05 項(xiàng)目特點(diǎn): 回彈效果視頻轉(zhuǎn)場(chǎng); Premiere Pro 2020及以上; 適用于照片和視頻轉(zhuǎn)場(chǎng); 適用于任何FPS和分辨率; 視頻教程。 PR轉(zhuǎn)場(chǎng):https://prmuban.com/37222.html

    2024年01月18日
    瀏覽(20)
  • uniapp 獲取 view 的寬度、高度以及上下左右左邊界位置

    uniapp 獲取 view 的寬度、高度以及上下左右左邊界位置

    boundingClientRect 返回的 res 結(jié)果(以像素[px]為單位) 屬性 類型 說(shuō)明 id String 節(jié)點(diǎn)的 ID dataset Object 節(jié)點(diǎn)的 dataset left Number 節(jié)點(diǎn)的左邊界坐標(biāo) right Number 節(jié)點(diǎn)的右邊界坐標(biāo) top Number 節(jié)點(diǎn)的上邊界坐標(biāo) bottom Number 節(jié)點(diǎn)的下邊界坐標(biāo) width Number 節(jié)點(diǎn)的寬度 height Number 節(jié)點(diǎn)的高度 更多可參

    2024年02月12日
    瀏覽(30)
  • python+opencv+mediapipe實(shí)現(xiàn)手勢(shì)檢測(cè)上下左右(含完整代碼)

    python+opencv+mediapipe實(shí)現(xiàn)手勢(shì)檢測(cè)上下左右(含完整代碼)

    應(yīng)用場(chǎng)景:ai換臉,根據(jù)左右手勢(shì)選擇圖片,上下則表示選中。 版本號(hào):python3.7(一開(kāi)始是3.6,但是mediapipe最低就是3.7 因?yàn)榫W(wǎng)上檢測(cè)的都不太準(zhǔn),所以我在判斷的時(shí)候加入了如果70次里55次檢測(cè)的是左才返回左,測(cè)試完之后效果還可以,蠻準(zhǔn)的。判斷方法想的頭都要禿了。 實(shí)

    2024年04月11日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包