flutter 实现自定义时间选择器

最近开始写flutter,有个简单的需求就是按照,设计样子写个时间选择器。

这个就是 设计需要的样子,底部弹出  选择时间,分为三个小滚轮分别选择天,时,分,返回一个datetime。

我想这个很简单啊,原来写ios 的直接用选择器 选择器可以直接UIPickerView 要几列选择 直接代理回调数据就可以了啊,

只是没享到到 flutter 确实有点麻烦。首先flutter 现场的时间选择器,但是很明显,做不到这个样子, 还有个CupertinoPicker 但是他是单个的选择。明显不符合要求。

于是去pub去搜,还真有个叫flutter_picker 的, 于是直接用上,然后看它的例子,发现还是不符合我的要求,因为 他是直接调用的方法尔不是一个widget,我需要的是widget 这样可以 直接放在我写好的页面了,而它只就是直接一个对象然后是调用它的showDialog,showModal,show 方法,而且自带例子和网上能查到的都是这种直接弹出的放啊发。这样弹出来的页面 根本和设计的页面不相同, 而且基本改不到能和设计的一样。

现在的情况是 弹出页面,我写好了,就缺个时间选择的滚轮widget,然而flutter_picker又不给我,于是只能去看它的代码,一开始看到 有个直接返回widget的方法, 直接用上然而不行。只能继续,

看到这里时,发现所有弹出方法体里都有个makepicker 方法,这个是直接返回widget的,而且也能外部调用,抱着试试看的心情就试下,结果完美,这就是我想要的。

附上的我push出来的时间选择页面代码

class DateTimePikerPage extends StatefulWidget {
  final DateTime dateTime;

  const DateTimePikerPage(this.dateTime, {Key key}) : super(key: key);
  @override
  _DateTimePikerPageState createState() => _DateTimePikerPageState();
}

class _DateTimePikerPageState extends State<DateTimePikerPage> {
  int s1 = 0;
  int s2 = 0;
  int s3 = 0;
  DateTime _now = DateTime.now();
  DateTime _selectDatetime;
  List _pickerdata = ServerCore.instance.getTimerPickerData();

  @override
  void initState() {
    _selectDatetime = widget.dateTime;
    String day = getDayAndWeekday(widget.dateTime);
    String hour = getHourSubfix(widget.dateTime);
    String minite = getMiniteSubfix(widget.dateTime);
    s1 = (_pickerdata[0] as List).indexOf(day);
    s2 = (_pickerdata[1] as List).indexOf(hour);
    s3 = (_pickerdata[2] as List).indexOf(minite);

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      body: Stack(
        children: [
          GestureDetector(
              child: Container(color: Colors.transparent),
              onTap: () => Navigator.of(context).pop()),
          Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              decoration: BoxDecoration(
                  color: ColorFFFFFF,
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(15),
                    topRight: Radius.circular(15),
                  )),
              height: 280,
              child: Column(
                children: [
                  Container(
                    height: 42,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        GestureDetector(
                          onTap: () {
                            Navigator.of(context).pop();
                          },
                          child: Padding(
                            padding: const EdgeInsets.only(left: 15, right: 15),
                            child: Text(
                              "取消",
                              style: TextStyle(
                                  color: Color2F54EB,
                                  fontSize: 17,
                                  fontWeight: FontWeight.w500),
                            ),
                          ),
                        ),
                        GestureDetector(
                          onTap: () =>
                              Navigator.of(context).pop(_selectDatetime),
                          child: Padding(
                            padding: const EdgeInsets.only(left: 15, right: 15),
                            child: Text(
                              "确认",
                              style: TextStyle(
                                  color: Color2F54EB,
                                  fontSize: 17,
                                  fontWeight: FontWeight.w500),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Expanded(
                      child: Stack(
                    children: [
                      Center(
                        child: Container(
                          decoration: BoxDecoration(
                            color: ColorF8F9FB,
                            border: Border(
                                top: BorderSide(width: 2, color: ColorE5E5E5),
                                bottom:
                                    BorderSide(width: 2, color: ColorE5E5E5)),
                          ),
                          height: 30,
                        ),
                      ),
                      Picker(
                        adapter: PickerDataAdapter<String>(
                          pickerdata: _pickerdata,
                          isArray: true,
                        ),
                        // looping: true,
                        hideHeader: true,
                        columnFlex: [3, 2, 2],
                        diameterRatio: 1,
                        backgroundColor: Colors.transparent,
                        selecteds: [s1, s2, s3],
                        height: 236,
                        containerColor: Colors.transparent,
                        textStyle: TextStyle(color: Color333333, fontSize: 16),
                        selectionOverlay: null,
                        selectedTextStyle:
                            TextStyle(color: Color333333, fontSize: 16),
                        onSelect: (picker, index, selected) {
                          DateTime ds = _now.add(Duration(days: selected[0]));
                          int hh = selected[1];
                          int mm = selected[2] * 15;
                          _selectDatetime =
                              DateTime(ds.year, ds.month, ds.day, hh, mm);
                          llog("$_selectDatetime");
                        },
                      ).makePicker(),
                    ],
                  )),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

数据结构

getTimerPickerData() {
    DateTime now = DateTime.now();
    List days = List.generate(90, (index) {
      DateTime _tmp = now.add(Duration(days: index));
      return getDayAndWeekday(_tmp);
    });

    return [
      days,
      [
        "00时",
        "01时",
        "02时",
        "03时",
        "04时",
        "05时",
        "06时",
        "07时",
        "08时",
        "09时",
        "10时",
        "11时",
        "12时",
        "13时",
        "14时",
        "15时",
        "16时",
        "17时",
        "18时",
        "19时",
        "20时",
        "21时",
        "23时",
        "24时",
      ],
      ["00分", "15分", "30分", "45分"]
    ];
  }

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flutter 底部弹出动画可以通过使用 BottomSheet widget 和 AnimatedContainer widget 来实现。 首先,创建一个 StatefulWidget,包含一个 bool 变量用于控制 BottomSheet 的显示和隐藏。 ``` class BottomSheetDemo extends StatefulWidget { @override _BottomSheetDemoState createState() => _BottomSheetDemoState(); } class _BottomSheetDemoState extends State<BottomSheetDemo> { bool _isVisible = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Bottom Sheet Demo'), ), body: Center( child: RaisedButton( child: Text('Show Bottom Sheet'), onPressed: () { setState(() { _isVisible = true; }); }, ), ), bottomSheet: _isVisible ? Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 5.0, spreadRadius: 1.0, offset: Offset(0.0, -1.0), ), ], ), child: SafeArea( child: AnimatedContainer( duration: Duration(milliseconds: 300), height: _isVisible ? 200.0 : 0.0, child: Center( child: Text('This is a Bottom Sheet'), ), ), ), ) : null, ); } } ``` 在上面的代码中,我们使用了一个 RaisedButton 来触发 Bottom Sheet 的显示,当用户点击按钮后,我们将 _isVisible 变量设置为 true,Bottom Sheet 就会显示出来。 Bottom Sheet 的内容是一个 AnimatedContainer,它的高度可以通过修改 _isVisible 变量来控制。在 AnimatedContainer 中,我们设置了一个动画时长为 300 毫秒,当 _isVisible 变量变化时,高度会从 0.0 到 200.0 进行动画过渡。 在 Bottom Sheet 的外部,我们使用了一个 Container 来包装它,并设置了一些阴影效果和背景颜色。我们还使用了 SafeArea 来确保 Bottom Sheet 不会被设备的导航栏遮挡。 通过这种方式,我们可以很容易地实现一个底部弹出动画效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值