Reputation: 16730
I have a view
struct CustomImageView : View {
var body: some View {
Image("someImage")
}
}
when i reference this view outside, i cannot make the image resizable. I know i can pass parameters, but i was looking for a neater way to do this through modifiers?
VStack {
CustomImageView()
.resizable() // This does not work
}
resizable seems to only work with the image directly. Does anyone know how to make the CustomImageView resizable?
Update: I understand i can use a parameter, but is there anyway to do it using modifiers? Resizable was only one property, but there are other properties. And listing them all as indvidual variables will be too much
Implemented Answer based on @matteo-pacini It uses AlamofireImage to load a remote image in 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
}
}
}
}
Upvotes: 7
Views: 3999
Reputation: 564
Like @FlowUI.SimpleUITesting.com mentioned the other answers suppose that you will edit only one property modifier. What if you would add others?
Simply in your CustomImageView add :
private let modifiers: (Image) -> Image
init(modifiers: @escaping (Image) -> Image = { $0 }) {
self.modifiers = modifiers
}
var body: some View {
modifiers(Image("someImage"))
}
Then simply use this way :
CustomImageView(modifiers : {$0.resizable().whateverModiferThatReturnImage().anotherOne()})
.frame(width: 200)
.aspectRatio(contentMode: .fit)
.asUsualModifiersThatReturnViews()
Upvotes: 2
Reputation: 911
Try this:
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)
}
}
Upvotes: 1
Reputation: 22866
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)
}
}
And use it like this.
struct ContentView: View {
var body: some View {
VStack {
CustomImageView()
.resizable()
}
}
}
Upvotes: 5
Reputation: 426
The problem is you are calling .resizable() on CustomeImageView, which is of type View.
You need to call .resizable() on an Image type.
Your Image is nested in body, that's within CustomImageView.
struct CustomImageView : View {
var body: some View {
Image("someImage")
.resizable()
}
}
CustomImageView()
The reason this works is, it calls .resizable on Image(), instead of a View, like before. Hope this helps!
References:
https://developer.apple.com/documentation/swiftui/image https://developer.apple.com/documentation/swiftui/view
Upvotes: 1