flutter入門之使用PopupRoute自定義實現PopupWindow功能

    【原創不易,轉載請註明出處:https://blog.csdn.net/email_jade/article/details/87922051

    本文起因是由於一個彈窗,要實現一個能夠通過點擊顯示隱藏的功能,效果如下:

    第一選擇是採用原生的PopupMenuItem,但是本應用的需求比較特殊,彈出的item自帶背景圖片,並且圖片上面附件了一個Text的文本,item個數恆定爲1個。採用PopupMenuItem會給彈出的item附加一個背景色,默認是跟Theme的cardColor顏色,導致圖片周圍有顏色,並且點擊的時候也會有顏色,看起來體驗極差,放棄該方案。

   第二選擇是採用一個隱藏的widget,當點擊的時候展示,然後點擊其他地方的時候隱藏,這個方案是可行的,但是由於該頁面有很多點擊事件,如果每個事件做處理比較麻煩。

    第三種方案是模擬原生的PopupMenuItem的控件,自定義子控件。於是閱讀源代碼,發現了PopupRoute,這是一個可以彈出透明的佈局的抽象Route,因此需要自定義一個PopRoute,代碼如下:

class PopRoute extends PopupRoute{
  final Duration _duration = Duration(milliseconds: 300);
  Widget child;

  PopRoute({@required this.child});

  @override
  Color get barrierColor => null;

  @override
  bool get barrierDismissible => true;

  @override
  String get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return child;
  }

  @override
  Duration get transitionDuration => _duration;

}

    需要注意的是transitionDuration不能返回null,否則會報錯。

    這個Route是爲了點擊按鈕的時候彈出一個新的頁面,這個新頁面除了自己定義的child,其他全是透明,來看看新的頁面的代碼:

class Popup extends StatelessWidget{
  final Widget child;
  final Function onClick; //點擊child事件
  final double left; //距離左邊位置
  final double top; //距離上面位置

  Popup({
    @required this.child,
    this.onClick,
    this.left,
    this.top,
  });

  @override
  Widget build(BuildContext context) {
    return Material(color: Colors.transparent, child: GestureDetector(child: Stack(
      children: <Widget>[
        Container(width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, color: Colors.transparent,),
        Positioned(child: GestureDetector(child: child, onTap: (){ //點擊子child
          if(onClick != null){ 
            Navigator.of(context).pop();
            onClick();
          }
        }),
        left: left,
        top: top,),
      ],
    ),
      onTap: (){ //點擊空白處
        Navigator.of(context).pop();
      },
    ),);
  }

}

    以上代碼就是用來展示的popup的代碼了。

    來看看是怎麼使用的:

  ///構建用戶頭像按鈕
  ///點擊頭像彈出退出按鈕
  Widget _buildUserIcon() {
    return Padding(
      padding: EdgeInsets.fromLTRB(20, 22, 0, 0),
      child: GestureDetector(
        child: Container(
            child: Image.asset(
              "assets/images/icon_user.png",
            ),
            width: 32,
            height: 32,
            alignment: AlignmentDirectional.bottomStart),
        onTap: _showExit,
      ),
    );
  }

  ///構建退出按鈕
  Widget _buildExit() {
    return Container(
      width: 91,
      height: 36,
      child: Stack(
        children: <Widget>[
          Image.asset(
            "assets/images/exit.png",
            fit: BoxFit.fill,
          ),
          Center(
            child: Text(
              ProjectLocalizations.of(context).exit,
              style: TextStyle(fontSize: 14, color: Colors.black),
            ),
          ),
        ],
      ),
    );
  }

  ///彈出退出按鈕
  ///點擊退出調用onClick
  void _showExit() {
    Navigator.push(context, PopRoute(child: Popup(
        child: _buildExit(),
    left: 64,
    top: 22,
    onClick: (){
    print("exit");
    },
    ),),);
  }

    使用起來也很方便,直接用Navigator的push方法即可,需要注意的是可以通過left和top計算出來新頁面item的展示位置,可以通過onClick監聽item的點擊事件。

    以上就是自定義PopupWindow的全部內容了,代碼比較少,並且全部貼在博客中了,就不貼GitHub地址了。

 

    flutter很好,路還很長,讓我們一起奮鬥前行!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章