SwiftUI中DatePicker学习

news2024/10/6 4:07:56

在界面开发中,经常要使用到DatePicker控件,如年月日,时分选择。

但我们还要修改它的显示方式,文字语言,及其他功能

先看下最简单的调用方法就是:

@State private var date = Date()

var body: some View {
    DatePicker(
        "Start Date",
        selection: $date,
        displayedComponents: [.date]
    )
}

就是一个最简单的年月日选择控件,如图:

年月日时分显示时,不出现年份的解决方法

我们当然需要默认设置为当 年月日,时分都放在一起,想让用户一次性选择年月日,时,分,结果不行。

DatePicker( selection: $selectedDate, in: dateRange(), displayedComponents: [.date,.hourAndMinute]),啊!!!燚

因此需要分开两个DataPicker处理,如下

contentView: View {
        @State private var selectedDate = Date()  

        var body: some View {
            VStack {
                Text("Selected date: \(selectedDate, formatter: dateFormatter)")
                
                DatePicker( selection: $selectedDate, displayedComponents: [.date]){ 
                        Text("日期")
                    }
                         
                DatePicker(selection: $selectedDate, displayedComponents:  [.hourAndMinute]) {
                        Text("时间")
                    }
                   
            }
        }

显示效果如下:

滚动式控件的界面

就在DatePicker后面加上:.datePickerStyle(WheelDatePickerStyle()) 就可以。

显示效果如下:

DatePicker的中文化和国际化

那还有问题就是这个月份是英文的,我们需要修改为中文语言,就需要在DatePicker后面加上:.environment(.locale, Locale(identifier: "zh_CN"))。

当然如果是想国际化APP的话,就使用:.environment(\.locale, Locale.autoupdatingCurrent)

日历列表控件界面

还有一种显示效果是直接出现日期列表控件(不包括时分),如下

只需要把.datePickerStyle(WheelDatePickerStyle())修改.datePickerStyle(.graphical)就可以

以下是完整代码:

struct testView: View {
        @State private var selectedDate = Date()
         
        var body: some View {
            VStack {
                Text("Selected date: \(selectedDate, formatter: dateFormatter)")
                
                
                DatePicker( selection: $selectedDate, displayedComponents: [.date]){ //添加一个DatePicker视图,将它和selectedDate属性进行绑定,并设置DatePicker的组件类型为小时和分钟
                    Text("日期")
                }
                .datePickerStyle(WheelDatePickerStyle())
                
                .environment(\.locale, Locale.autoupdatingCurrent)
                //.environment(.locale, Locale(identifier: "zh_CN")) //中文显示
                
                
                DatePicker(selection: $selectedDate, displayedComponents:  [.hourAndMinute]) { //添加一个DatePicker视图,将它和selectedDate属性进行绑定,并设置DatePicker的组件类型为小时和分钟
                    Text("时间")
                }
                .datePickerStyle(WheelDatePickerStyle())
                
            }
        }

        private var dateFormatter: DateFormatter {
            let formatter = DateFormatter()
            formatter.dateStyle = .medium
            formatter.timeStyle = .long
            return formatter
        }
    }

日期设置范围

我们显示的日历列表,如果需要设置一个特定的日期范围,就可以,需要创建一个:ClosedRange<Date>,其实就是一个startDate...endDate,你可以先定义开始和结束日期:

let startDate = Calendar.current.date(from: DateComponents(year: 2023, month: 3, day: 1))! 

let endDate = Calendar.current.date(from: DateComponents(year: 2023, month: 6, day: 30))!

然后调用

DatePicker( "",selection: $selectedDate,in: startDate...endDate,displayedComponents: [.date]),也可以定义一个ClosedRange<Date>

func dateRange() -> ClosedRange<Date> {

            let startDate = dateFormatter.date(from: "20230301")!

            let endDate = dateFormatter.date(from: "20230630")!

            return startDate...endDate

        }

再调用:

DatePicker( "",selection: $selectedDate,in: dateRange(),displayedComponents: [.date])

日期格式设置

我们代码中有一个DateFormatter,他就是格式化输出日期表达式,并用来显示的,你可以根据你们需要来定义

private var dateFormatter1: DateFormatter {

        let formatter = DateFormatter()

        formatter.dateFormat = "yyyyMMdd"

            return formatter

    }

private var dateFormatter2: DateFormatter {

            let formatter = DateFormatter()

            formatter.dateStyle = .medium

            formatter.timeStyle = .long

            return formatter

        }

 例1

let startDate = dateFormatter1.date(from: "20230301")!  --这就比刚才那个

let startDate = Calendar.current.date(from: DateComponents(year: 2023, month: 3, day: 1))! 简单多了

例2

Text("Selected date: \(selectedDate, formatter: dateFormatter)")

显示为

日期排除

DatePicker设置一个日期范围(如20230301-20230630),但要排除其中20230302,20230303两天。目前DatePicker不支持排除,需要自己处理,我这有个不完美的方案,就是这个日期显示时,弹出提示,而没有实现为灰不能选择(下一步实现)

struct testView: View {
    @State private var selectedDate = Date()
    @State private var showInvalidDate = false
    @State private var invalidDate: Date?

    // 定义日期范围
    let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMdd"
        return formatter
    }()

    var body: some View {
        VStack {
            DatePicker("选择日期", selection: $selectedDate, in: dateRange(), displayedComponents: .date)
                .padding()
                .onReceive([self.selectedDate].publisher.first()) { date in
                    if disabledDates().contains(where: { Calendar.current.isDate($0, inSameDayAs: date) }) {
                        self.invalidDate = date
                        self.showInvalidDate = true
                        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                            self.showInvalidDate = false
                        }
                        DispatchQueue.main.async {
                            self.selectedDate = self.previousValidDate(for: date)
                        }
                    }
                }
                .datePickerStyle(GraphicalDatePickerStyle())

            Text("所选日期:\(dateFormatter.string(from: selectedDate))")
                .padding()
        }
        .alert(isPresented: $showInvalidDate) {
            Alert(title: Text("不能选择"), message: Text("\(dateFormatter.string(from: invalidDate ?? selectedDate)) 无效。请重新选择日期。"), dismissButton: .default(Text("确定")))
        }
    }

    func dateRange() -> ClosedRange<Date> {
        let startDate = dateFormatter.date(from: "20230301")!
        let endDate = dateFormatter.date(from: "20230630")!

        return startDate...endDate
    }

    func disabledDates() -> [Date] {
        let disabledDateStrings: [String] = ["20230302", "20230303"]
        let disabledDates = disabledDateStrings.compactMap { dateFormatter.date(from: $0) }
        return disabledDates
    }

    func previousValidDate(for date: Date) -> Date {
        var previousDate = date
        while disabledDates().contains(where: { Calendar.current.isDate($0, inSameDayAs: previousDate) }) {
            previousDate = Calendar.current.date(byAdding: .day, value: -1, to: previousDate)!
        }
        return previousDate
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/510113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32F10X--中断

中断 中断优先级数值越小&#xff0c;中断优先级越高 中断编程的顺序 1、使能的是外设&#xff0c;配置外设寄存器 2、配置中断优先级分组&#xff0c;在msic.h里面有中断优先级组分组函数 这个函数里面配置了SCB->AIRCR寄存器 3、配置NVIC寄存器&#xff0c;初始化NVIC…

可视化和回归分析星巴克咖啡在中国的定价建议

可视化和回归分析星巴克咖啡在中国的定价建议。星巴克的拿铁大杯Tall 在各国的价格。 Claude AI | 代码自动生成的数据可视化代码 选择Claude AI 而非 ChatGPT的理由是前者更懂中文​&#xff01;具体可以参见我前面的两篇文章对比两者的中英文翻译的表现及使用安装等难易程度​…

2.SpringBoot运维实用篇

SpringBoot运维实用篇 ​ 基础篇发布以后&#xff0c;看到了很多小伙伴在网上的留言&#xff0c;也帮助超过100位小伙伴解决了一些遇到的问题&#xff0c;并且已经发现了部分问题具有典型性&#xff0c;预计将有些问题在后面篇章的合适位置添加到本套课程中&#xff0c;作为解…

做公有云服务,为什么对象存储不可或缺?

试问&#xff1a;公有云的竞争&#xff0c; 你觉得从什么时候开始白热化了&#xff1f; 【全球云观察 &#xff5c; 热点关注】对于这个问题&#xff0c;可谓仁者见仁智者见智。 在我看来&#xff0c;火山引擎还未推出全面的云服务之前&#xff0c;在国内的公有云领域&#x…

KingbaseES V8R6运维案例之---MySQL和KingbaseES字符串排序规则对比

案例说明&#xff1a; 相同数据排序后查询&#xff0c;在MySQL和KingbaseES下得到的排序顺序不一致&#xff0c;本案例从MySQL和KingbaseES的排序规则分析&#xff0c;两种数据库排序的异同点。适用版本&#xff1a; KingbaseES V8R6、MySQL 8.0 一、MySQL的排序规则1、排序规则…

各种预训练模型的理论和调用方式大全

诸神缄默不语-个人CSDN博文目录 本文主要以模型被提出的时间为顺序&#xff0c;系统性介绍各种预训练模型的理论&#xff08;尤其是相比之前工作的创新点&#xff09;、调用方法和表现效果。 最近更新时间&#xff1a;2023.5.10 最早更新时间&#xff1a;2023.5.10 BertRobe…

上海亚商投顾:沪指缩量调整跌超1% 新能源车产业链掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 大小指数今日再度分化&#xff0c;沪指低开低走&#xff0c;午后一度跌超1.5%&#xff0c;创业板指则拉升涨超1%&a…

nodejs安装和环境配置-Windows

0.安装过程中遇到的常见问题 访问&#xff1a;https://blog.csdn.net/weixin_52799373/article/details/125718587?spm1001.2014.3001.5502 1.下载node.js 下载地址: https://nodejs.org/en/ 2.安装 2.1 安装 其实就是无脑下一步&#xff0c;第三步的时候可以选择自定义目…

springboot配置文件加载顺序, java启动参数优先级

搜索: "spring boot 外化配置" Spring Boot Reference Guide Spring Boot 中文文档 参考手册 中文版 SpringBoot中配置文件加载位置与优先级_apllication 配置文件项目启动时加载参数_流烟默的博客-CSDN博客 SpringBoot的外部化配置最全解析!_广州建站小戴BOTAO博…

k8s之HPA(Pod水平自动伸缩)

1.hpa介绍 HPA是根据指标来进行自动伸缩的&#xff0c;目前HPA有两个版本–v1和v2beta HPA的API有三个版本&#xff0c;通过kubectl api-versions | grep autoscal可看到 kubectl api-versions | grep autosca autoscaling/v1 autoscaling/v2beta1 autoscaling/v2beta2 查看使…

Uboot源码目录分析

在分析uboot源码之前一定要在Ubuntu中编译一下uboot源码&#xff0c;因为编译过程会生成一些文件&#xff0c;而生成的这些恰恰是分析uboot源码不可或缺的文件。 arch文件夹 存放和架构有关的文件&#xff0c;我们现在用的是ARM芯片&#xff0c;所以只需要关系arm文件夹即可 …

2.是人就能学会的Spring源码教学-Spring的简单使用

是人就能学会的Spring源码教学-Spring的简单使用 Spring的最简单入门使用第一步 创建项目第二步 配置项目第三步 启动项目 Spring的最简单入门使用 各位道友且跟我一道来学习Spring的最简单的入门使用&#xff0c;为了方便和简单&#xff0c;我使用了Spring Boot项目&#xff…

linux CentOs 安装 mysql8.0.30

心酸历程。。。 网上的各种教程都有各种bug&#xff0c;安了三个小时终于安好。现在奉上我的宝典秘籍。 第一步&#xff0c;去mysql官网下载&#xff0c;然后将下载的tar包放到linux里面&#xff0c;最好专门创建一个目录来存放&#xff0c;我放到了/usr/local/src的mysql目录下…

基于51单片机的简易电子秤

首先看看题目要求&#xff1a; 1.方案论证 &#xff08;1&#xff09;压力传感器的论证与选择 方案一&#xff1a;采用惠更斯电桥&#xff0c;当电阻应变片承受载荷产生变形时&#xff0c;其阻值将发生变化。从而使电桥失去平衡&#xff0c;产生相应的差动信号&#xff0c;但…

Jenkins入门系列之Gitlab账号登录

目录 背景步骤1. 安装插件2. Gitlab 配置3. Jenkins 配置4. 验证 背景 版本 Jenkins Version&#xff1a;Jenkins 2.403Gitlab Version: Gitlab 15.6部署环境&#xff1a;群晖NAS Docker 部署JenkinsGitlab Jenkins 默认使用的是自带的数据库&#xff0c;支持LDAP&#xff0…

【C++】-类和对象之初始化列表(explicit的简单介绍)(下)

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树 ❤️‍&#x1fa79;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a8;作者gitee:gitee &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 文章目录 前言 前言 经过前面的好几篇博客&#xff0c;大家应…

SpringSecurity自定义实现手机短信登录

SpringSecurity自定义登录验证-手机验证码登录 其实实现原理上跟账号密码登录一样的 1、自定义短信验证Token 定义一个仅使用手机号验证权限的鉴权Token&#xff0c;SpringSecurity原生的UsernamePasswordAuthenticationToken是使用username和password&#xff0c;如下图 pr…

向量时钟算法

向量时钟不仅同步本进程的时钟值&#xff0c;而且还同步已知的其他进程时钟值 分布式系统中每个进程Pi保存一个本地逻辑时钟向量值VCi&#xff0c;VCi(j)代表进程Pi知道的进程Pj的本地逻辑时钟值 初始化VCi向量为[0,…]进程Pi每发生一次事件&#xff0c;VCi[i]加一进程Pi给进…

应付模块无法关账问题 APP-AR-11332 您必须在关闭此期之前过账其中的所有事务处理

问题描述 AR关账时遇到了这个问题&#xff0c;根本原因是&#xff0c;因为用户录入另一个贷项的发票&#xff0c;做过核销&#xff0c;后来又取消了核销&#xff0c;未创建会计分类&#xff0c;未传送总&#xff0c;不想要这个贷项发票了&#xff0c;前台删除不了&#xff0c;…

经验分享,api 接口设计原则有这几条

结合我多年在 API 行业摸爬滚打的经验&#xff0c;我总结了一下&#xff0c;API 接口设计原则有这几条&#xff1a; 接口设计应该简单易用&#xff0c;易于理解和使用&#xff1b; 接口设计应该支持多种格式&#xff0c;如JSON、XML等&#xff1b; 接口设计应该支持多种请求方…