如何使用 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()
我有意见
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()