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

时间:2019-06-15 12:10:42

标签: ios swift swiftui

我有一个看法

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

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

VStack {
   CustomImageView()
      .resizable()    // This does not work
}
可调整大小的

似乎只能直接与图像一起使用。 有谁知道如何使CustomImageView可调整大小?

更新:我知道我可以使用参数,但是仍然可以使用修饰符吗?可调整大小只是一个属性,但还有其他属性。并将它们全部列为单个变量将太多

基于@ 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
            }
        }
    }
}

4 个答案:

答案 0 :(得分:1)

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()
        }
    }
}

答案 1 :(得分:1)

类似于@ FlowUI.SimpleUITesting.com提到了其他答案,假设您将仅编辑一个属性修饰符。如果您要添加其他人怎么办?

只需在您的CustomImageView中添加:

private let modifiers: (Image) -> Image

init(modifiers: @escaping (Image) -> Image = { $0 }) {
    self.modifiers = modifiers
}

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

然后只需使用这种方式:

CustomImageView(modifiers : {$0.resizable().whateverModiferThatReturnImage().anotherOne()})
  .frame(width: 200)
  .aspectRatio(contentMode: .fit)
  .asUsualModifiersThatReturnViews()

答案 2 :(得分:0)

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

您需要在Image类型上调用.resizable()。

您的图片嵌套在主体中,位于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

答案 3 :(得分:0)

尝试一下:

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()
            .resizeable()
    }
}