首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI:内容是图像的ViewModifier

SwiftUI:内容是图像的ViewModifier
EN

Stack Overflow用户
提问于 2019-11-11 23:57:44
回答 2查看 4.9K关注 0票数 21

我得到了一个错误"Type 'PlayButtonModifier' does not conform to protocol 'ViewModifier'“,我不明白为什么,更重要的是,我不明白如何正确地处理它。

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

ViewModifier协议中,定义了一个用于ContentTypealias。我的naiv想法是,这应该是可行的:

代码语言:javascript
复制
struct PlayButtonModifier: ViewModifier {
    typealias Content = Image

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

嗯,不是。太简单了。同样的事情也发生在结构的隐式类型别名上:

代码语言:javascript
复制
struct PlayButtonModifier: ViewModifier {
    func body(content: Image) -> some View {
        content
    }
}

同样的错误。

这里出了什么问题?它怎么会是正确的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-28 18:21:08

在这种情况下,修改是特定于特定视图类型的,Image说,您可以直接在该视图类型上添加扩展:

代码语言:javascript
复制
extension Image {
    func myImageModifier() -> some View {
        self
            .resizable()
            .aspectRatio(1.0, contentMode: .fit)
            .clipShape(Circle())
   }
}

下面是一个完整的游乐场文本示例。如果你在你的游乐场“资源”文件夹中添加一张可爱的水鼠图片,命名为"Otter.png“,你会得到一个更漂亮的结果:)

代码语言:javascript
复制
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())
票数 18
EN

Stack Overflow用户

发布于 2019-12-31 01:04:51

感谢与Asperi的评论和讨论,我最终使用了以下代码片段。基本上,它是ViewModifier的一个实现,专门用于图像。

代码语言:javascript
复制
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)
    }
}

使用它很简单:

代码语言:javascript
复制
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完美集成。

在定义返回ImageImageModifier时,它减少了将图像修改为特定于图像的修饰符(实际上是resizable())的可能性;当定义它返回some View时,我不能链接ImageModifiers,因为第二个修饰符必须是ViewModifier

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58804696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档