From 9dc99b8b07decd7159a330a5dbe527836f4fd0e2 Mon Sep 17 00:00:00 2001 From: abbassabeti Date: Thu, 25 Jul 2024 20:27:53 +0200 Subject: [PATCH] iOS 18 Styling - Event --- .../CustomCalendarExampleController.swift | 47 +++++++++++++++++-- Sources/Timeline/EventView.swift | 15 ++++-- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/CalendarKitDemo/CalendarApp/CustomCalendarExampleController.swift b/CalendarKitDemo/CalendarApp/CustomCalendarExampleController.swift index a414aba3..c312fa85 100644 --- a/CalendarKitDemo/CalendarApp/CustomCalendarExampleController.swift +++ b/CalendarKitDemo/CalendarApp/CustomCalendarExampleController.swift @@ -87,14 +87,53 @@ final class CustomCalendarExampleController: DayViewController { let duration = Int.random(in: 60 ... 160) event.dateInterval = DateInterval(start: workingDate, duration: TimeInterval(duration * 60)) - var info = data.randomElement() ?? [] + let info = data.randomElement() ?? [] + let attributedInfo = NSMutableAttributedString( + string: info.reduce("", { $0 + $1 + "\n" }), + attributes: [.font: UIFont.systemFont(ofSize: 12, weight: .semibold)] + ) let timezone = dayView.calendar.timeZone print(timezone) - info.append(dateIntervalFormatter.string(from: event.dateInterval.start, to: event.dateInterval.end)) - event.text = info.reduce("", {$0 + $1 + "\n"}) - event.color = colors.randomElement() ?? .red + let durationText = dateIntervalFormatter.string( + from: event.dateInterval.start, + to: event.dateInterval.end + ) + + let color = colors.randomElement() ?? .red + + let durationAttributedText: NSMutableAttributedString = { + var attributedString: NSMutableAttributedString! + if #available(iOS 13.0, *) { + let clockIcon = NSTextAttachment() + let config = UIImage.SymbolConfiguration(pointSize: 12, weight: .thin, scale: .small) + let image = UIImage(systemName: "clock", withConfiguration: config) + clockIcon.image = image + let text = NSMutableAttributedString(attachment: clockIcon) + attributedString = text + } else { + attributedString = NSMutableAttributedString(string: "") + } + attributedString.addAttribute( + .paragraphStyle, + value: { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.paragraphSpacingBefore = 5 + return paragraphStyle + }(), + range: NSRange(location: 0, length: attributedString.string.count) + ) + return attributedString + }() + let attributedDuration = NSAttributedString( + string: String(format: " %@", durationText), + attributes: [.font: UIFont.systemFont(ofSize: 11, weight: .light)] + ) + durationAttributedText.append(attributedDuration) + attributedInfo.append(durationAttributedText) + event.attributedText = attributedInfo + event.color = color event.isAllDay = Bool.random() event.lineBreakMode = .byTruncatingTail diff --git a/Sources/Timeline/EventView.swift b/Sources/Timeline/EventView.swift index 7a7096cc..98b2d4ad 100644 --- a/Sources/Timeline/EventView.swift +++ b/Sources/Timeline/EventView.swift @@ -13,6 +13,7 @@ open class EventView: UIView { view.isUserInteractionEnabled = false view.backgroundColor = .clear view.isScrollEnabled = false + view.clipsToBounds = true return view }() @@ -44,6 +45,7 @@ open class EventView: UIView { public func updateWithDescriptor(event: EventDescriptor) { if let attributedText = event.attributedText { textView.attributedText = attributedText + textView.setNeedsLayout() } else { textView.text = event.text textView.textColor = event.textColor @@ -53,7 +55,9 @@ open class EventView: UIView { textView.textContainer.lineBreakMode = lineBreakMode } descriptor = event - backgroundColor = event.backgroundColor + backgroundColor = .clear + layer.backgroundColor = event.backgroundColor.cgColor + layer.cornerRadius = 5 color = event.color eventResizeHandles.forEach{ $0.borderColor = event.color @@ -104,13 +108,16 @@ open class EventView: UIView { context.saveGState() context.setStrokeColor(color.cgColor) context.setLineWidth(3) + context.setLineCap(.round) context.translateBy(x: 0, y: 0.5) let leftToRight = UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .leftToRight let x: Double = leftToRight ? 0 : frame.width - 1.0 // 1 is the line width let y: Double = 0 + let hOffset: Double = 3 + let vOffset: Double = 5 context.beginPath() - context.move(to: CGPoint(x: x, y: y)) - context.addLine(to: CGPoint(x: x, y: (bounds).height)) + context.move(to: CGPoint(x: x + 2 * hOffset, y: y + vOffset)) + context.addLine(to: CGPoint(x: x + 2 * hOffset, y: (bounds).height - vOffset)) context.strokePath() context.restoreGState() } @@ -123,7 +130,7 @@ open class EventView: UIView { if UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft { return CGRect(x: bounds.minX, y: bounds.minY, width: bounds.width - 3, height: bounds.height) } else { - return CGRect(x: bounds.minX + 3, y: bounds.minY, width: bounds.width - 3, height: bounds.height) + return CGRect(x: bounds.minX + 8, y: bounds.minY, width: bounds.width - 6, height: bounds.height) } }() if frame.minY < 0 {