一些新东西
预览
用的#Preview宏, 这里主要讲预览UIKit.
// viewcontroller
class LibraryViewController: UIViewController {
// ...
}
#Preview("Library") {
let controller = LibraryViewController()
controller.displayCuratedContent = true
return controller
}
// view
class SlideshowView: UIView {
// ...
}
#Preview("Memories") { // You can also specify name of preview here `Memories` will appear as a tab
let view = SlideshowView()
view.title = "Memories"
view.subtitle = "Highlights from the past year"
view.images = ...
return view
}
空状态
iOS17 开始提供了一系列空状态视图,用于在数据为空时显示友好的提示信息。比如加载中(loading), 无数据(empty), 无搜索结果(search)等, 同任何其他系统组件一件, 你需要操作一堆内置属性来自定义, 如果你不是很熟它的结构, UI稿又和默认UI不一样, 花的时间可能跟自己写一个差不多, 毕竟只是一个静态视图, 但如果你只是想快速实现一个空状态, 那么它还是很有用的。
var config = UIContentUnavailableConfiguration.empty()
config.image = UIImage(systemName: "star.fill")
config.text = "No"
config.secondaryText = "Your favorite translations will appear here."
// setting contentUnavailableConfiguration
viewController.contentUnavailableConfiguration = config
通过text, image, button及一堆关联的properties来个性化.
更新状态的时机:
// Represent no search results empty state
override func updateContentUnavailableConfiguration(using state: UIContentUnavailableConfigurationState) {
var config: UIContentUnavailableConfiguration?
if searchResults.isEmpty {
config = .search()
}
// 可见, 设为nil就能移除
contentUnavailableConfiguration = config
}
// Update search results for query
searchResults = backingStore.results(for: query)
setNeedsUpdateContentUnavailableConfiguration()
经过我的测试, unavailable视图只会把特定的图标文字覆盖在当前视图上, 不会全屏覆盖, 所以旧视图的清理工作还是需要你自己做的.
动图
// Bounce the symbol once
imageView.addSymbolEffect(.bounce)
// 让颜色由深到浅进行动画(可以循环播放, 直到你remove)
// Add a variable color effect, which repeats
imageView.addSymbolEffect(.variableColor.iterative)
// Somtime later, remove the effect
imageView.removeSymvolEffect(ofType:.variableColor)
// Change the image, using Replace effect
imageView.setSymbolImage (pauseImage, contentTransition: .replace.offUp)
前提, 使用SF symbols.
字符图片的国际化变体
仍然是sF symbols的特性, 同一个字符在不同国家有不同表示, 可以结合NSLocale使用, 这次来一版OC的:
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"ja_JP"];
UIImageConfiguration *confg = [UIImageConfiguration configurationWithLocale:locale];
[UIImage systemImageNamed:@"character.textbox" withConfiguration:conf];
其中ja是语言JP是地区, 也可以用NSLocale的current属性.()
swift则可以使用Locale:
// Retrieve UIImage by locale
let locale = Locale (languageCode: •japanese)
imageView.image = UIImage (
systemName: "character.textbox",
withConfiguration: UIImage. SymbolConfiguration(locale: locale)
)
PageControl支持自动翻页和跟踪翻页进度
let timerProgress = UIPageControlTimerProgress(preferredDuration: 10)
pageControl progress = timerProgress
timerProgress.resumeTimer ()
标识当前页的圆点会变成一个进度条.
如果你要跟踪轮播图里的视频进度, 或外部定时器, 可以使用ULPagecontrolProgress, 把当前时长与总时长除一下得到一个进度, 传给currentProgress属性即可.:
let progress = ULPagecontrolProgress()
pageControl.progress = progress
myTimer.addPeriodicTimeObserver { timer in
progress.currentProgress = Float(timer.seconds / timer.duration)
// ...
}
SwiftUI ScrollView
colorStack
.aspectRatio(16.0/9.0, contentMode: .fit)
// 自适应内容大小(演示横向)
.containerRelativeFrame(
[.horizontall],
count: sizeClass == .regular ? 2 : 1,
spacing: hSpacing
)
.contentMargins(.horzontal, 20.0) // 内容边距
.safeAreaPadding(.horzontal, 20.0) // 另一种内容边距
.clipShape(.rect(cornerRadius: 20.0))
// 滚动过渡
.scrollTransition(axis: .horizontal) { content, phase in
content
.scaleEffect(
x: phase.isIdentity ? 1.0 : 0.75,
y: phase.isIdentity ? 1.0 : 0.75
)
}
// 分页(基于屏幕)
.scrollTargetBehavior(.paging)
// 分页(基于元素)
.scollTargetBehavior(.viewAligned)