SwiftUI:内容是图像的 ViewModifier
Posted
技术标签:
【中文标题】SwiftUI:内容是图像的 ViewModifier【英文标题】:SwiftUI: ViewModifier where content is an Image 【发布时间】:2019-11-11 15:57:44 【问题描述】:我收到错误“Type 'PlayButtonModifier' does not conform to protocol 'ViewModifier'
”,我不明白为什么,更重要的是,如何正确处理。
我只是尝试为Image
创建一个ViewModifier
,以便我可以在其上使用例如.resizable()
,它仅在Image
中定义
在ViewModifier
协议中,为Content
定义了一个Typealias
。我的天真想法是这应该可行:
struct PlayButtonModifier: ViewModifier
typealias Content = Image
func body(content: Content) -> some View
content
嗯,不。太容易了。结构的隐式类型别名也会发生同样的事情:
struct PlayButtonModifier: ViewModifier
func body(content: Image) -> some View
content
同样的错误。
这里有什么问题?怎么会是正确的?
【问题讨论】:
Content is opaque typealias here...this post 将帮助您澄清该区域。 嗨@Asperi,您的链接背后的答案很好地解释了幕后发生的事情。这次真是万分感谢。现在 1 Mio $ 问题:我该如何使用它? Apple 付出了所有努力,甚至包括 Swift 中的语法更改,只是为了能够修改标准的普通视图?甚至没有图像或文本?我仍然相信,其中有一些我还没有发现的东西。 所有修饰符实际上都是一个函数,即。 .resizable()。 ViewModifier 是通用视图修改的通用机制。对于特定的修改,您可以创建特定的功能、可计算的属性、专用的视图等。唯一的要求 - 那些应该生成一些视图作为输出。 【参考方案1】:在这种修改特定于特定视图类型的情况下,例如Image
,您可以直接在该视图类型上添加扩展:
extension Image
func myImageModifier() -> some View
self
.resizable()
.aspectRatio(1.0, contentMode: .fit)
.clipShape(Circle())
下面是完整的游乐场文本示例。如果您在游乐场“资源”文件夹中添加一张名为“Otter.png”的可爱水獭图片,您会得到更漂亮的结果:)
import PlaygroundSupport
import SwiftUI
let image = (UIImage(named: "Otter.png") ?? UIImage(systemName: "exclamationmark.square")!)
struct ContentView: View
var body: some View
VStack
Text("hello world")
Image(uiImage: image)
.myImageModifier()
extension Image
func myImageModifier() -> some View
self
.resizable()
.aspectRatio(1.0, contentMode: .fit)
.clipShape(Circle())
PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
【讨论】:
【参考方案2】:感谢cmets和Asperi的讨论,我终于用了下面的代码sn-p。基本上,它是 ViewModifier
的实现,专门用于图像。
protocol ImageModifier
/// `Body` is derived from `View`
associatedtype Body : View
/// Modify an image by applying any modifications into `some View`
func body(image: Image) -> Self.Body
extension Image
func modifier<M>(_ modifier: M) -> some View where M: ImageModifier
modifier.body(image: self)
使用很简单:
struct MyImageModifier: ImageModifier
func body(image: Image) -> some View
image.resizable().scaledToFit()
struct MyView: View
var body: some View
Image(systemName: "play").modifier(MyImageModifier())
我不是 100% 满意,因为必须将修饰符定义为返回 some View
或返回 Image
。这两种情况都有缺点,不能与 SwiftUI 完美集成。
当定义 ImageModifier
以返回 Image
时,它减少了将图像修改为仅特定于图像的修饰符(实际上是 resizable()
)的可能性,并且在将其定义为返回 some View
时,我无法链接ImageModifier
s 作为第二个修饰符必须是 ViewModifier
。
【讨论】:
以上是关于SwiftUI:内容是图像的 ViewModifier的主要内容,如果未能解决你的问题,请参考以下文章
如何向 swiftUI ScrollView 指示内容大小已更改?