繁体   English   中英

SwiftUI:内容是图像的 ViewModifier

[英]SwiftUI: ViewModifier where content is an Image

我收到一个错误“ Type 'PlayButtonModifier' does not conform to protocol 'ViewModifier' ”,我不明白为什么,更重要的是 - 如何正确地做到这一点。

我只是尝试为Image创建一个ViewModifier ,以便可以在其上使用例如.resizable() ,它仅在Image中定义

ViewModifier协议中,定义了ContentTypealias 我的天真想法是这应该有效:

struct PlayButtonModifier: ViewModifier {
    typealias Content = Image

    func body(content: Content) -> some View {
        content
    }
}

嗯,不。 太容易了。 结构的隐式类型别名也会发生同样的事情:

struct PlayButtonModifier: ViewModifier {
    func body(content: Image) -> some View {
        content
    }
}

同样的错误。

这里有什么问题? 怎么会是正确的?

在这种修改特定于特定视图类型的情况下, 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())

感谢与Asperi的评论和讨论,我终于使用了以下代码片段。 基本上,它是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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM