flutter 使用PopupRoute构建popupWindow弹窗并 动态刷新弹窗UI

flutter 开发app中,弹窗应该是必定会用到的,这里推荐使用PopupRoute去实现,怎么实现不是本文的重点,重点是动态刷新弹窗中控件的UI样式,比如下图:在弹窗中,点击第一个列表某个item,将item状态设为选中状态样式,其它item还原为未选中样式,并且 重置刷新第二个列表数据(第二个列表会根据第一个列表item的选择而呈现不同数据)。做过弹窗动态刷新UI的应该都知道,如果直接在当前页面使用setState,并不会使弹窗上的UI动态更新,那么该如何做呢?

废话不多说,这里提供一种我的实现方式,如果有更好的方法欢迎留言探讨,共同进步。

首先简单看下popupRoute弹窗的代码:

 RenderBox renderBox = _globalKey1.currentContext.findRenderObject();
 Rect box = renderBox.localToGlobal(Offset.zero) & renderBox.size;
  Navigator.push(context,DropDownMenuRoute(
                      position: box,//弹窗位置信息
                      menuWidth:ScreenUtil.getScreenW(context) - model.getAh(10),//弹窗宽度
                      menuHeight: model.getAh(549),//弹窗高度
                      offset: model.getAh(5),//偏移量
                      itemView:PopSubjectWidget(courseModel: model)//这里的PopSubjectWidget就是弹窗布局
                ));

可以看到弹窗的UI布局是通过自定义方式将view传进去的,那么我们可以把弹窗布局PopSubjectWidget单独抽出来构建(如果你是直接写在当前页面的一个widget,setState方法是不会起作用的)继承StatefulWidget,这样在PopSubjectWidget使用setState方法更新列表数据就可以刷新列表UI了。

最后贴一下自定义弹窗DropDownMenuRoute 代码:

import 'package:flutter/material.dart';

///自定义下拉弹窗  实现思路:
///通过自定义路由继承自PopupRoute,并结合Navigator.push使弹出的下拉列表能够覆盖在当前页面显示
///使用CustomSingleChildLayout组件,自定义SingleChildLayoutDelegate并结合RelativeRect来控制下拉列表显示的位置和高度
/// 使用SizeTransition实现下拉列表的下拉动画效果
class DropDownMenuRoute extends PopupRoute {
  ///点击控件的相对位置信息
  final Rect position;
  ///下拉控件高度
  final double menuHeight;
  ///下拉控件宽度
  final double menuWidth;
  ///弹窗控件布局
  final Widget itemView;
  ///偏移量
  final double offset;
  ///构造方法
  DropDownMenuRoute({this.position,this.menuWidth, this.menuHeight,this.offset,this.itemView});

  @override
  // TODO: implement barrierColor
  Color get barrierColor => null;

  @override
  // TODO: implement barrierDismissible
  bool get barrierDismissible => true;

  @override
  // TODO: implement barrierLabel
  String get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return CustomSingleChildLayout(
      delegate: DropDownMenuRouteLayout(position: position,menuWidth: menuWidth, menuHeight: menuHeight,offset:offset),
      ///这里加入了下拉动画
      child: SizeTransition(
        sizeFactor: Tween<double>(
            begin: 0.0,
            end: 1.0
        ).animate(animation),
        ///这里写具体布局,通过外面传入
        child:itemView,
      ),
    );
  }

  @override
  // TODO: implement transitionDuration
  Duration get transitionDuration => Duration(milliseconds: 300);

}
///下拉选择布局控制器
class DropDownMenuRouteLayout extends SingleChildLayoutDelegate {
  final Rect position;
  final double menuHeight;
  final double menuWidth;
  final double offset;
  DropDownMenuRouteLayout({this.position,this.menuWidth, this.menuHeight,this.offset});

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    ///控制下拉控件的宽高

    return BoxConstraints.loose(Size(menuWidth, menuHeight));
  }

  @override
  Offset getPositionForChild(Size size, Size childSize) {
    ///控制下拉控件显示位置,这里始终居于点击控件的下方
    return Offset(offset, position.bottom+5);
  }

  @override
  bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
    // TODO: implement shouldRelayout
    return true;
  }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值