Flutter showbottomsheet更新自身状态和更新父widget状态

在使用showbottomsheet的时候,因为bottomsheet中有个dropdownbutton,需要选择之后更新dropdownbutton,按照正常的方式来使用没用效果.我先上一段正常使用的代码  一个选择性别的滚轮,我这里使用的是CupertinoPicker来实现的

先上效果图

1.model类

import 'package:scoped_model/scoped_model.dart';

class ScopedModelCupertinoPicker extends Model{

    int  _index=0;

    //获取当前被选中的index
    int get currentIndex=>_index;

     //设置被选中的index并更新
    void changeValue(int currentIndex){
        _index=currentIndex;
        notifyListeners();
    }

    //重置被选中的index为0
    void setIndexValueZero(){
        _index=0;
        notifyListeners();
    }

}

2.实现.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:xxxxx/yyyyyy/scopedmodel_cupertinopicker.dart';     //改成你自己的目录
import 'package:scoped_model/scoped_model.dart';

class BBBBBB extends StatelessWidget {
  ScopedModelCupertinoPicker mScopedModelCupertinoPicker=ScopedModelCupertinoPicker();

  @override
  Widget build(BuildContext context) {
    return ScopedModel<ScopedModelCupertinoPicker>(
      model: mScopedModelCupertinoPicker,
      child: Scaffold(
        appBar: AppBar(
          brightness: Brightness.light,
          backgroundColor: Colors.white,
          leading: IconButton(icon: Icon(Icons.chevron_left), onPressed: (){Navigator.of(context).pop();}),
          title: Text('用户资料',style: TextStyle(fontSize: 15),),
          centerTitle: true,
        ),
        body:MyBody() ,
      ),
    );
  }
}



class MyBody extends StatefulWidget {
  @override
  _MyBodyState createState() => _MyBodyState();
}

class _MyBodyState extends State<MyBody> {
  ScopedModelCupertinoPicker mScopedModelCupertinoPicker;
  @override
  void initState() {
    super.initState();
    mScopedModelCupertinoPicker=ScopedModel.of<ScopedModelCupertinoPicker>(context);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: 10,right: 10),
      child: Column(
        children: <Widget>[
          Container(
            height: 45,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text('性别',style: TextStyle(color: Color(0xff333333),fontSize: 13),),
                GestureDetector(
                  onTap:_showBottomSheetSex,
                  child:  Row(
                    children: <Widget>[
                      Text('${mTypeList[mScopedModelCupertinoPicker.currentIndex]}',style: TextStyle(fontSize: 13,color: Color(0xff333333)),),
                      Icon(Icons.keyboard_arrow_right,size: 13,color: Color(0xff999999),),
                    ],
                  ),
                )
              ],
            ),
          ),
          Divider(height: 1,),
        ],
      ),
    );
  }



  List<String>  mTypeList=['男','女'];
  ///展示性别选择底部滚轮弹窗
  void _showBottomSheetSex() {
    bool  changed=false;        //标记是直接点击确定还是调整过选项之后点击的
    Scaffold.of(context).showBottomSheet((BuildContext context) {
      return Container(
        height:200,
        child: Column(
          children: <Widget>[
            Container(
              height: 40,
              color: Colors.grey.withOpacity(0.25),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  FlatButton(onPressed: (){Navigator.of(context).pop();}, child: Text('取消',style: TextStyle(color: Color(0xff44c5fe),fontSize: 13,),)),
                  Text('选择性别',style: TextStyle(color: Color(0xff333333),fontSize: 13,fontWeight: FontWeight.bold),),
                  FlatButton(onPressed: (){
                    setState(() {
                      if(changed==false){
                        mScopedModelCupertinoPicker.setIndexValueZero();
                      }
                      debugPrint('${mTypeList[mScopedModelCupertinoPicker.currentIndex]}');
                      Navigator.of(context).pop();
                    });
                  }, child: Text('确认',style: TextStyle(color: Color(0xff44c5fe),fontSize: 13,),)),
                ],
              ),
            ),
            Container(
              width: double.infinity,
              color: Colors.grey.withOpacity(0.1),
              height: 100,
              child: CupertinoPicker(
                useMagnifier: true,
                backgroundColor: Colors.white, //选择器背景色
                itemExtent: 25, //item的高度
                onSelectedItemChanged: (index) {
                  changed=true;
                  mScopedModelCupertinoPicker.changeValue(index);
                  print("index = $index}");
                },
                children: <Widget>[ //所有的选择项
                  Text('${mTypeList[0]}'),
                  Text('${mTypeList[1]}'),
                ],
              ),
            )
          ],
        ),
      );
    },
    );
  }
}

以上代码可以看出我使用的

 Scaffold.of(context).showBottomSheet((BuildContext context) {})来实现的 。

但是在我另一个需求里面  弹出框里面有一个Dropdownbutton的时候 dropdownbutton切换选择项之后需要更新状态 这种方法却不凑效了  ,网上查资料  使用另一种方法实现了

class CarAdd extends StatefulWidget {
  @override
  _CarAddState createState() => _CarAddState();
}

class _CarAddState extends State<CarAdd> {
    MyScopedModel mScopedModel= new MyScopedModel();
  final _bottomSheetKey = GlobalKey<ScaffoldState>();
  String dropdown1Value = 'A';
  TextEditingController mController1 = TextEditingController();
  TextEditingController mController2 = TextEditingController();

  @override
  void initState() {
    super.initState();
    HHHHHH b1 = HHHHHH("AAAAAAA", "蓝",'1234', false, false);
    HHHHHH b2 = HHHHHH("BBBBBBB", "绿",'5678', true, false);
    mScopedModel..add(b1)..add(b2);
  }

  @override
  Widget build(BuildContext context) {
    return ScopedModel<BindCarScopedModel>(
      model: mScopedModel,
      child: Scaffold(
        key: _bottomSheetKey,
        appBar: AppBar(
          brightness: Brightness.light,
          backgroundColor: Colors.white,
          leading: GestureDetector(
            child: Icon(Icons.chevron_left),
            onTap: () {
              Navigator.of(context).pop();
            },
          ),
          title: Text(
            '标题',
            style: TextStyle(fontSize: 15, color: Color(0xff333333)),
          ),
          centerTitle: true,
          elevation: 1,
        ),
        body: SafeArea(
          child: CustomScrollView(
            shrinkWrap: true,     //必须添加  否则  就需要在slivers里面添加占位的sliverToBoxAdapter占位置  不然就会报错(我这里未指定listview的Item高度)
            slivers: <Widget>[
              SliverToBoxAdapter(        //绑定车辆按钮
                child: Container(
                  width: double.infinity,
                  height: 45,
                  margin: EdgeInsets.only(left: 10,right: 10,top: 50),
                  child: RaisedButton(
                    onPressed: _showBottomSheet,
                    color: Color(0xff44c5fe),
                    shape: StadiumBorder(
                        side: BorderSide(
                          style: BorderStyle.none,
                          color: Color(0xff44c5fe),
                        )),
                    child: Text(
                      '绑定',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }



  _showBottomSheet() {          //底部弹框
    _bottomSheetKey.currentState.showBottomSheet((BuildContext context) {
     //注意  这里return StatefulBuilder  然后调用state方法更新状态
      return StatefulBuilder(
        builder: (context, state) {
          return Container(
            width: double.infinity,
            color: Colors.grey.withOpacity(0.1),
            height: 300,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  padding: EdgeInsets.only(left: 10, right: 10),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      SizedBox(
                        width: 1,
                      ),
                      Text('添加'),
                      GestureDetector(
                        onTap: () {
                          Navigator.of(context).pop();
                        },
                        child: Icon(Icons.clear),
                      )
                    ],
                  ),
                ),
                Container(
                  padding: EdgeInsets.only(left: 10, right: 10),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.baseline,
                    textBaseline: TextBaseline.ideographic,
                    children: <Widget>[
                      Text(
                        '号码',
                        style: TextStyle(fontSize: 13),
                      ),
                      SizedBox(
                        width: 10,
                      ),
                      DropdownButtonHideUnderline(
                        child: DropdownButton<String>(
                          value: dropdown1Value,
                          iconEnabledColor: Color(0xff44c5fe),
                          onChanged: (String newValue) {
                            //注意  这里使用setState无效
                            state(() => dropdown1Value = newValue);
                          },
                          items: <String>[
                            'A',
                            'B',
                            'C',
                          ].map<DropdownMenuItem<String>>((String value) {
                            return DropdownMenuItem<String>(
                              value: value,
                              child: Text(
                                value,
                                style: TextStyle(fontSize: 13),
                              ),
                            );
                          }).toList(),
                        ),
                      ),
                      Expanded(
                        child: TextFormField(
                          controller: mController1,
                          inputFormatters: [
                            LengthLimitingTextInputFormatter(6)
                          ],
                          decoration: InputDecoration(
                            contentPadding: EdgeInsets.all(2),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                Container(
                  width: double.infinity,
                  height: 80,
                  padding: EdgeInsets.only(left: 10, right: 10),
                  child: TextFormField(
                    style: TextStyle(fontSize: 13),
                    controller: mController2,
                    inputFormatters: [LengthLimitingTextInputFormatter(4)],
                    decoration: InputDecoration(
                        contentPadding: EdgeInsets.all(2),
                        hintText: '请输入后四位',
                        hintStyle:
                        TextStyle(fontSize: 13, color: Color(0xff999999))),
                  ),
                ),
                Container(
                  width: double.infinity,
                  height: 45,
                  padding: EdgeInsets.only(left: 20, right: 20),
                  child: RaisedButton(
                    onPressed: () {
                      debugPrint(
                          '${dropdown1Value}:${mController1.text},,,,${mController2.text}');
                    },
                    shape: StadiumBorder(side: BorderSide.none),
                    color: Color(0xff44c5fe),
                    child: Text(
                      '确 定',
                      style: TextStyle(color: Colors.white, fontSize: 15),
                    ),
                  ),
                ),
              ],
            ),
          );
        },
      );
    });
  }

}

这个我删减了部分代码,大家主要看showbottomsheet方法  及bottomsheetkey的使用就行了   效果图先不贴了 ,对比上面的发现使用的

 _bottomSheetKey.currentState.showBottomSheet((BuildContext context) {
      return StatefulBuilder(
        builder: (context, state) {
            return Container();
        }
        ))

来实现的。如果使用第一种方法会报错

总结:第二种是更新Bottomsheet本身的状态用的 。

    第一种方法更新的是bottomsheet所依赖的widget的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Flutter的showBottomSheet中添加模糊层,请按照以下步骤进行操作: 1. 导入BackdropFilter和BlurFilter类: ``` import 'dart:ui'; import 'package:flutter/material.dart'; ``` 2. 将showBottomSheet方法包装在StatefulWidget中,并在State类中添加一个变量来跟踪是否应该显示模糊层: ``` class MyWidget extends StatefulWidget { const MyWidget({Key? key}) : super(key: key); @override _MyWidgetState createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { bool _showBlurLayer = false; void _toggleBlurLayer() { setState(() { _showBlurLayer = !_showBlurLayer; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('My App'), ), body: Center( child: ElevatedButton( onPressed: () { showModalBottomSheet<void>( context: context, builder: (BuildContext context) { return Container( height: 200.0, color: Colors.white, child: Center( child: Text('This is a modal bottom sheet'), ), ); }, ); _toggleBlurLayer(); }, child: const Text('Show Modal Bottom Sheet'), ), ), ); } } ``` 3. 在模态底部表单的构建器中添加一个BackdropFilter小部件,该小部件将一个模糊的图像层应用于其子元素,以创建模糊效果。您可以使用BackDropFilter的filter属性来指定要应用的滤镜,例如BlurFilter: ``` builder: (BuildContext context) { return BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( height: 200.0, color: Colors.white, child: Center( child: Text('This is a modal bottom sheet'), ), ), ); }, ``` 4. 最后,您需要在模态表单关闭时将_showBlurLayer变量设置为false,以便在下一次显示模态表单时不再显示模糊层: ``` Navigator.of(context).pop(); _toggleBlurLayer(); ``` 这样就可以在Flutter的showBottomSheet中添加模糊层了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值