在 Picker 中对齐视图
Align views in Picker
如何将 Color
视图与侧面的文本对齐成一条直线?
看起来像这样(文本对齐前导):
█ 红
█ 绿
█ 蓝
或者这个(文本居中对齐):
█ 红
█ 绿
█蓝色
当前代码:
struct ContentView: View {
@State private var colorName: Colors = .red
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
}
}
}
}
}
enum Colors: String, CaseIterable, Identifiable {
case red
case green
case blue
var id: String { rawValue }
var asColor: Color {
switch self {
case .red: return .red
case .green: return .green
case .blue: return .blue
}
}
}
结果(未正确对齐):
没有 Picker
,我发现可以使用 alignmentGuide(_:computeValue:)
来实现结果。但是,这需要在 Picker
.
中
尝试:
VStack(alignment: .custom) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
.alignmentGuide(.custom) { d in
d[.leading]
}
Text(color.rawValue)
.frame(maxWidth: .infinity)
.fixedSize()
}
}
.frame(height: 50)
}
/* ... */
extension HorizontalAlignment {
struct CustomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
return context[HorizontalAlignment.leading]
}
}
static let custom = HorizontalAlignment(CustomAlignment.self)
}
尝试结果:
我认为这应该对齐您的文本并解决您的问题。
struct ContentView: View {
@State private var colorName: Colors = .red
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack() {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
.frame(width: 100, height: 30, alignment: .leading)
}
}
}
}
}
一个简单的 .frame
修饰符将解决这些问题,如果您不想在选择器或列表视图方面使事情复杂化,请尝试将您的文本组合在一起或使用 Label
。
如果您继续使用此解决方案,请尝试根据您的要求尝试使用 width
和 height
,看看您是想要 .leading
还是 .trailing
在对齐
可能的解决方案是对使用视图首选项计算的最大值应用的标签使用动态宽度。
这是一个演示。使用 Xcode 13beta / iOS15
测试
注:ViewWidthKey
取自我的另一个回答
struct ContentView: View {
@State private var colorName: Colors = .red
@State private var maxWidth = CGFloat.zero
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
}
.background(GeometryReader {
Color.clear.preference(key: ViewWidthKey.self,
value: [=10=].frame(in: .local).size.width)
})
.onPreferenceChange(ViewWidthKey.self) {
self.maxWidth = max([=10=], maxWidth)
}
.frame(minWidth: maxWidth, alignment: .leading)
}
}
}
}
如何将 Color
视图与侧面的文本对齐成一条直线?
看起来像这样(文本对齐前导):
█ 红
█ 绿
█ 蓝
或者这个(文本居中对齐):
█ 红
█ 绿
█蓝色
当前代码:
struct ContentView: View {
@State private var colorName: Colors = .red
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
}
}
}
}
}
enum Colors: String, CaseIterable, Identifiable {
case red
case green
case blue
var id: String { rawValue }
var asColor: Color {
switch self {
case .red: return .red
case .green: return .green
case .blue: return .blue
}
}
}
结果(未正确对齐):
没有 Picker
,我发现可以使用 alignmentGuide(_:computeValue:)
来实现结果。但是,这需要在 Picker
.
尝试:
VStack(alignment: .custom) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
.alignmentGuide(.custom) { d in
d[.leading]
}
Text(color.rawValue)
.frame(maxWidth: .infinity)
.fixedSize()
}
}
.frame(height: 50)
}
/* ... */
extension HorizontalAlignment {
struct CustomAlignment: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
return context[HorizontalAlignment.leading]
}
}
static let custom = HorizontalAlignment(CustomAlignment.self)
}
尝试结果:
我认为这应该对齐您的文本并解决您的问题。
struct ContentView: View {
@State private var colorName: Colors = .red
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack() {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
.frame(width: 100, height: 30, alignment: .leading)
}
}
}
}
}
一个简单的 .frame
修饰符将解决这些问题,如果您不想在选择器或列表视图方面使事情复杂化,请尝试将您的文本组合在一起或使用 Label
。
如果您继续使用此解决方案,请尝试根据您的要求尝试使用 width
和 height
,看看您是想要 .leading
还是 .trailing
在对齐
可能的解决方案是对使用视图首选项计算的最大值应用的标签使用动态宽度。
这是一个演示。使用 Xcode 13beta / iOS15
测试注:ViewWidthKey
取自我的另一个回答
struct ContentView: View {
@State private var colorName: Colors = .red
@State private var maxWidth = CGFloat.zero
var body: some View {
Picker("Select color", selection: $colorName) {
ForEach(Colors.allCases) { color in
HStack {
color.asColor.aspectRatio(contentMode: .fit)
Text(color.rawValue)
}
.background(GeometryReader {
Color.clear.preference(key: ViewWidthKey.self,
value: [=10=].frame(in: .local).size.width)
})
.onPreferenceChange(ViewWidthKey.self) {
self.maxWidth = max([=10=], maxWidth)
}
.frame(minWidth: maxWidth, alignment: .leading)
}
}
}
}