这一篇文章我们简单实现一个有图片展示,有按钮事件的小页面。
1.Image
官方推荐我们的本地图片都放在Assets
中,然后使用Image直接用图片名称进行加载,那有些开发者喜欢将图片放在自己的文件夹中,如何来进行展示,可以封装一个loadImage
方法:
func loadImage() -> UIImage? {
if let imagePath = Bundle.main.path(forResource: "top@3x", ofType: "png", inDirectory: nil) {
return UIImage(contentsOfFile: imagePath)
}
return nil
}
可以使用Image(uiImage:)初始化器将UIImage转换为SwiftUI的Image视图,确保加载的路径一定是准确的即可。
if let image = loadImage() {
Image(uiImage: image)
.resizable()
.scaledToFit()
}
整个效果如下图所示:
如果这个图片是放在
Assets
中使用起来就非常方便的:
Image("top")
.resizable()
.scaledToFit()
2.Button
Button最基本的初始化方法public init(_ titleKey: LocalizedStringKey, action: @escaping () -> Void)
,非常的方便,我们就赋值一个文字,填写方法事件就可以了:
Button("显示文字") {
//事件方法体
}
还有一种更丰富的初始化方法,这个方法中label
的返回体是一个任意组装的View
,比如下面的代码,我们构造出一个左图右文的展示按钮:
Button {
// 事件
} label: {
HStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.blue)
Text("哈哈")
}
}
3.@State
在开发中经常会遇到修改某个值后然后刷新UI,理想的办法就是监听这个值,有变化就自动刷新UI,在SwiftUI中提供了@State
这个属性包装器非常方便,允许我们绕过结构体的限制:我们知道不能更改它们的属性,因为结构是固定的,但是@State允许SwiftUI将该值单独存储在可以修改的地方。
struct ContentView: View {
let arr = ["选项1","选项2","选项3","选项4","选项5","选项6"]
@State private var selectedItem:String?
var body: some View {
VStack {
Image("top")
.resizable()
.scaledToFit()
if (selectedItem != nil) {
Text(selectedItem ?? "")
.font(.largeTitle)
}
Button("随机一个") {
print("选择了")
selectedItem = arr.shuffled().filter{$0 != selectedItem}.first
}
.font(.title)
.buttonStyle(.borderedProminent)
.padding(.top, 5)
Button("重置") {
selectedItem = nil
}
.font(.title)
.buttonStyle(.borderless)
.padding(.top, 20)
}
}
}
以上代码就是当用户选择随机一个后,会从arr
中随机取出一个和当前不一样的选项显示出来,重置后,显示项目直接隐藏掉,效果比较突兀:
在SwiftUI中,系统提供了方便的动画效果:
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {
/// Applies the given animation to this view when the specified value
/// changes.
///
/// - Parameters:
/// - animation: The animation to apply. If `animation` is `nil`, the view
/// doesn't animate.
/// - value: A value to monitor for changes.
///
/// - Returns: A view that applies `animation` to this view whenever `value`
/// changes.
@inlinable public func animation<V>(_ animation: Animation?, value: V) -> some View where V : Equatable
}
直接在VStack
中加入动画效果,监听selectedItem
值的变化,当该值变化就开始动画效果,就不会那么生硬突兀了:
.animation(.easeOut(duration: 0.24),value: selectedItem)
UI在布局的时候,比如在同一个容器中我们如果使用同样的字体大小,不用在内部每个View设置,直接在父View中.font
来设置就行,如果内部某个不同,只需要针对某个控件再单独设置,其他属性同样的道理。
网友评论