如何使用 SwiftUI 制作自定义图像 resizable()

How to make a custom Image resizable() with SwiftUI

我有意见

struct CustomImageView : View {
    var body: some View {
        Image("someImage")
    }
}

当我在外部引用此视图时,无法调整图像大小。 我知道我可以传递参数,但我一直在寻找一种更简洁的方法来通过修饰符来做到这一点?

VStack {
   CustomImageView()
      .resizable()    // This does not work
}

resizable 似乎只能直接处理图像。 有谁知道如何使 CustomImageView 可调整大小?

更新: 我知道我可以使用参数,但是无论如何都可以使用修饰符吗? Resizable 只是一个 属性,但还有其他属性。将它们全部列为独立变量会太多

基于@matteo-pacini 的实施答案 它使用 AlamofireImage 在 ImageView 中加载远程图像。

struct RemoteImage : View {
    var url: URLConvertible
    @ObjectBinding var imageLoader = AlamofireImageLoader()

    private (set) var _resizable: (capInsets: EdgeInsets, resizingMode: Image.ResizingMode) = (EdgeInsets(), .stretch)

    var body: some View {
        Image(uiImage: imageLoader.image)
            .resizable(capInsets: _resizable.capInsets, resizingMode: _resizable.resizingMode)
            .onAppear() {
                self.imageLoader.loadImage(url: self.url)
            }
    }

    func resizable(capInsets: EdgeInsets = EdgeInsets(), resizingMode: Image.ResizingMode = .stretch) -> RemoteImage {
        return RemoteImage(url: url, _resizable: (capInsets, resizingMode))
    }
}

class AlamofireImageLoader: BindableObject {
    var didChange = PassthroughSubject<Void, Never>()
    var image = UIImage() {
        didSet {
            DispatchQueue.main.async {
                self.didChange.send(Void())
            }
        }
    }

    convenience init(url: URLConvertible) {
        self.init()
        loadImage(url: url)
    }

    func loadImage(url: URLConvertible) {
        Alamofire.request(url).responseImage { response in
            if let image = response.result.value {
                self.image = image
            }
        }
    }
}
struct CustomImageView : View {

    private var isResizable = false

    var body: some View {
        let image = Image("someImage")
        return isResizable ? image.resizable() : image
    }

    func resizable() -> CustomImageView {
        return CustomImageView(isResizable: true)
    }
}

然后像这样使用它。


struct ContentView: View {
    var body: some View {
        VStack {
            CustomImageView()
                .resizable()
        }
    }
}

问题是您在 View 类型的 CustomeImageView 上调用 .resizable()。

您需要对图像类型调用 .resizable()。

您的图片嵌套在 body 中,在 CustomImageView 中。

struct CustomImageView : View {
    var body: some View {
        Image("someImage")
            .resizable()
    }
}

CustomImageView()

这样做的原因是,它在 Image() 上调用 .resizable,而不是像以前那样调用 View。希望这对您有所帮助!

参考文献:

https://developer.apple.com/documentation/swiftui/image https://developer.apple.com/documentation/swiftui/view

试试这个:

struct CustomImageView: View {

    @State var isResizeable: Bool = false
    @State var capInsets: EdgeInsets = EdgeInsets()
    @State var resizingMode: Image.ResizingMode = .stretch

    var body : some View {

        ZStack {
            if isResizeable {
                Image("placeholder")
                    .resizable(capInsets: self.capInsets, resizingMode: self.resizingMode)
            }
            else {
                Image("placeholder")
            }
        }
    }

    func resizeable(capInsets: EdgeInsets = EdgeInsets(), resizingMode: Image.ResizingMode = .stretch) -> CustomImageView {
        return CustomImageView(isResizeable: true, capInsets: capInsets, resizingMode: resizingMode)
    }
}

struct ContentView : View {

    var body: some View {
        CustomImageView(isResizeable: true)
    }
}

就像@FlowUI.SimpleUITesting.com 提到的其他答案假设您将只编辑一个 属性 修饰符。如果您要添加其他人呢?

只需在您的 CustomImageView 中添加:

private let modifiers: (Image) -> Image

init(modifiers: @escaping (Image) -> Image = { [=10=] }) {
    self.modifiers = modifiers
}

var body: some View {
    modifiers(Image("someImage"))
}

那就简单的用这个方法吧:

CustomImageView(modifiers : {[=11=].resizable().whateverModiferThatReturnImage().anotherOne()})
  .frame(width: 200)
  .aspectRatio(contentMode: .fit)
  .asUsualModifiersThatReturnViews()