我们之前有解释过,SwiftUI中,有public protocol Layout : Animatable
,我们可以通过这个协议来自定义。
其实,我们在UIKit
中如何定义三个拥有同等宽度的按钮呢?我们的思路会是:
- 获取每个Button中的文案
- 然后计算出这个字体下,这些文案的宽度
- 缓存最大的按钮宽度,然后赋予其他的按钮,并设定为他们的宽。
但是,到了SwiftUI的话,我们只需要自定义Layout
,然后在里面去实现我们的规则。具体思路如下:
- 获取每个子视图的宽度,然后得到最宽的子视图的大小。
- 当然我们还需要获取每个子视图之间的spacing。
- 最后通过
placeSubviews
, 将所有的子视图的size都替换为最大的button。
代码如下:
struct MyEqualWidthHStack: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let maxSize = self.maxSize(from: subviews)
let totalSpacing = spacing(by: subviews).reduce(0) { $0 + $1 }
return CGSize(
width: maxSize.width * CGFloat(subviews.count) + totalSpacing,
height: maxSize.height
)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let maxSize = self.maxSize(from: subviews)
let spacings = self.spacing(by: subviews)
let placementProposal = ProposedViewSize(width: maxSize.width, height: maxSize.height)
var x: CGFloat = bounds.minX + maxSize.width / 2
for index in subviews.indices {
subviews[index].place(
at: CGPoint(x: x, y: bounds.minY),
anchor: .center,
proposal: placementProposal
)
x += maxSize.width + spacings[index]
}
}
}
extension MyEqualWidthHStack {
func maxSize(from subviews: Subviews) -> CGSize {
let subViewSizes = subviews.map { $0.sizeThatFits(.unspecified) }
return subViewSizes.reduce(CGSize.zero) { currentMax, subViewSize in
return CGSize(
width: max(currentMax.width, subViewSize.width),
height: max(currentMax.height, subViewSize.height)
)
}
}
func spacing(by subviews: Subviews) -> [CGFloat] {
subviews.indices.compactMap { index in
guard index < subviews.count - 1 else { return 0 }
return subviews[index].spacing.distance(to: subviews[index + 1].spacing, along: .horizontal)
}
}
}
值得一提的是,当我们调用如上的MyEqualWidthHStack
的时候,会发现不生效,如下:
import SwiftUI
struct ButtonStack: View {
let titles = ["Cat", "Goldfish", "Dog"]
var body: some View {
MyEqualWidthHStack {
ForEach(titles.indices, id: .self) { index in
Button {
} label: {
Text(titles[index])
// .frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
}
}
}
}
当注释掉.frame(maxWidth: .infinity)
modifier的时候,我们会发现button还是按照文本内容进行填充的。这个是因为,如果我们不设定frame的话,SwiftUI会进行默认布局,即按照内容进行填充。只有设定了frame之后,SwiftUI才会真的按照我们的自定义Layout进行布局。
如果有理解不到位的地方,欢迎解答。
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=20230,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=20230,转载请注明出处。
评论0