SwiftUI中如何居中异步加载的KFImage?
解决Kingfisher网络图片居中问题
方案一:利用SwiftUI布局系统自动居中(推荐)
你之前用VStack+Spacer无效,大概率是父容器未占满全屏。只要让图片所在的父容器铺满屏幕,SwiftUI会自动帮你居中图片,无需手动计算偏移量:
// 方法1:用ZStack包裹,背景占满屏幕 ZStack { Color.clear // 占位背景,确保ZStack占满整个屏幕 KFImage(URL(string: image)) .resizable() .aspectRatio(contentMode: .fit) } // 方法2:直接给图片设置全屏frame并指定对齐方式 KFImage(URL(string: image)) .resizable() .aspectRatio(contentMode: .fit) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
如果一定要用VStack,只需给VStack加上全屏frame即可:
VStack { Spacer() KFImage(URL(string: image)) .resizable() .aspectRatio(contentMode: .fit) Spacer() } .frame(maxWidth: .infinity, maxHeight: .infinity)
方案二:监听图片加载完成后的尺寸(精确控制)
利用Kingfisher的onSuccess回调,在图片加载完成后获取原始尺寸,再计算适配屏幕后的显示尺寸,最后调整偏移量:
@State private var displaySize: CGSize = .zero var body: some View { let screenSize = UIScreen.main.bounds.size KFImage(URL(string: image)) .resizable() .aspectRatio(contentMode: .fit) .offset( x: (screenSize.width - displaySize.width) / 2, y: (screenSize.height - displaySize.height) / 2 ) .onSuccess { result in let image = result.image let scale = UIScreen.main.scale let originalSize = CGSize(width: image.size.width / scale, height: image.size.height / scale) // 计算.fit模式下的实际显示尺寸 let widthRatio = screenSize.width / originalSize.width let heightRatio = screenSize.height / originalSize.height let fitScale = min(widthRatio, heightRatio) displaySize = CGSize(width: originalSize.width * fitScale, height: originalSize.height * fitScale) } }
方案三:修改原有代码,监听尺寸变化
针对你当前的实现,把onAppear替换为监听GeometryReader的尺寸变化,这样图片加载完成后尺寸更新时会自动触发偏移量计算:
@State private var imageWidth: CGFloat = 0 @State private var imageHeight: CGFloat = 0 var body: some View { let screenSize = UIScreen.main.bounds.size KFImage(URL(string: image)) .resizable() .aspectRatio(contentMode: .fit) .offset( x: (screenSize.width - imageWidth) / 2, y: (screenSize.height - imageHeight) / 2 ) .background( GeometryReader { proxy in Color.clear .onChange(of: proxy.size) { newSize in imageWidth = newSize.width imageHeight = newSize.height } } ) }
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

