【问题标题】:Add Colon (:) between Hour and Minute & Disable default AM/PM in UIDatePicker在 Hour 和 Minute 之间添加冒号 (:) 并在 UIDatePicker 中禁用默认 AM/PM
【发布时间】:2019-09-02 13:31:05
【问题描述】:

我正在尝试为 12-Hour 格式禁用 UIDatePicker 中的默认 AM/PM,并尝试在 Hour 和 Minute 之间添加冒号 (:)。但没能做到。

我在日期选择器中设置了以下代码以在UIDatePicker 中设置时间。

self.datePicker.datePickerMode = .time

以上代码以 12 小时格式显示时间,上午 / 下午。

见下图:

谁能帮我解决这个问题?

【问题讨论】:

  • 简单地使用普通的UIPickerView不是更容易吗?
  • 如何使用UIPickerView实现?
  • 只需分配一个数据源和一个委托。返回 2 个组件,一个为几小时,另一个为几分钟。您可以设置任何您想要的文本,包括冒号。尽管在您的图像上,其中一个组件似乎只有冒号...
  • (与问题无关,但有些人会阅读您的问题,而不是喜欢他们并投反对票。我不希望他们以后甚至会阅读您的 cmets。)
  • 有几个这样的技巧stackoverflow.com/a/26064121/526828

标签: ios swift uidatepicker


【解决方案1】:

我认为您最好的解决方案是简单地使用普通的UIPickerView。这样你几乎可以控制一切。作为演示,我创建了这个全代码示例,它几乎可以满足您的需求:

class ViewController: UIViewController {

    private let pickerView: UIPickerView = UIPickerView(frame: CGRect(x: 0.0, y: 300.0, width: 100.0, height: 300.0))

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(pickerView)
        pickerView.dataSource = self
        pickerView.delegate = self
        pickerView.reloadAllComponents()
        pickerView.selectRow(50000, inComponent: 0, animated: false)
        pickerView.selectRow(50000, inComponent: 1, animated: false)

        view.addSubview({
            let label = UILabel(frame: .zero)
            label.text = ":"
            label.sizeToFit()
            label.center = pickerView.center
            label.isUserInteractionEnabled = false
            return label
        }())
    }

}

extension ViewController: UIPickerViewDataSource, UIPickerViewDelegate {

    private func hourValueAtIndex(index: Int) -> Int {
        return index%12
    }
    private func minuteValueAtIndex(index: Int) -> Int {
        return index%60
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return 100000
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0: return String(hourValueAtIndex(index: row))
        case 1: return String(minuteValueAtIndex(index: row))
        default: return ""
        }
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let calendarToUse = Calendar.autoupdatingCurrent
        var components = calendarToUse.dateComponents([.year, .month, .day], from: Date())
        components.hour = hourValueAtIndex(index: pickerView.selectedRow(inComponent: 0))
        components.minute = minuteValueAtIndex(index: pickerView.selectedRow(inComponent: 1))
        let selectedDate = calendarToUse.date(from: components)

        print("Selected new time (in UTC): \(selectedDate!)")

        let formatter = DateFormatter()
        formatter.calendar = calendarToUse
        formatter.dateStyle = .short
        formatter.timeStyle = .short
        print("Selected new time (local): \(formatter.string(from: selectedDate!))")
    }

}

如果需要,我会将所有这些都放在故事板甚至 xib 中以使其可重用。结肠的定位和样式可能需要一些工作,但这取决于您想要什么设计。我只是为组件使用了 100k 值来模拟无限滚动。至少应该为此定义一些常量。

通知hourValueAtIndexminuteValueAtIndex;这些可以被操纵以使用几乎任何你需要的东西。要让它在 0-23 小时内运行,您只需使用 index%24。不过,要拥有它1-24 需要做更多的工作:您将返回index%24 + 1,但在构造日期时,您需要将 24 的值作为异常处理。您将使用 0 并添加额外的一天。但是您不能直接向组件添加额外的一天,因为您可能会在 7 月 32 日这样的情况下溢出。您确实需要在末尾添加一天:

selectedDate = calendarToUse.date(byAdding: DateComponents(day: 1), to: selectedDate)

【讨论】:

  • 非常感谢。这对我来说真的是非常好的解决方案。我已经从上面修改了一些代码,并且按照我的预期效果要好得多。
【解决方案2】:

我相信 UIDatePicker 使用本地时间配置,所以我不建议您更改它。不过,更改dateTimePicker.locale 就足够了。

【讨论】:

  • 我知道这件事。但是,我不想设置语言环境。此外,在某些国家/地区,日期选择器将使用 24 小时格式。所以它会在没有 AM / PM 的情况下显示。我不想使用 24 小时格式。
  • 那么我同意 cmets,使用 UIPickerView 将是最好的解决方案。
  • @SagarChauhan 这与国家或语言无关,这与用户在设备设置中设置的内容始终有关。如果你想覆盖它(为什么?用户设置它是有原因的),你需要使用en_US_POSIX 语言环境。
  • 是的,我能理解。但大多数用户总是会设置他居住的地区,所以日期选择器会根据设备的地区自动设置。
【解决方案3】:

UIDatePicker 应按原样使用,无需自定义。你不应该弄乱它的观点,所以你可能不走运。如果您想要UIDatePicker 不提供的行为,那么您可能需要使用UIPickerView 创建自己的控件。

引用文档:

外观

UIDatePicker 的外观不可自定义。

为此,您需要创建一个包含 2 个组件(小时和分钟)的选取器视图,并设置一个数据源,其中一个组件附加了一个冒号。请注意,组件也会滚动冒号,这可能不是您想要的。

您始终可以创建一个完全自定义的控件,但要让它完全按照您的意愿工作将需要大量工作,并且可能需要使用 CALayersCAAnimation,这两个控件都相当先进

【讨论】:

  • 谢谢,我试试这个。
猜你喜欢
  • 2011-01-09
  • 2016-03-18
  • 2018-01-21
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多