【问题标题】:How can I vertically align an image to the center of the first line of some text?如何将图像垂直对齐到某些文本第一行的中心?
【发布时间】:2020-07-23 08:09:25
【问题描述】:

我有一个要点和一些长的多行文本。我希望项目符号点与第一行文本的中心对齐。显然,如果字符串足够短且一行长,那么两个视图会自动居中对齐。我对文本长度超过一行的情况感兴趣。

var body: some View {
    HStack {
        Image(systemName: "circle.fill")
            .font(.system(size: 8))
        Text("Insert really long multiline string that wraps.")
    }
}

这可能吗?

更新 1:

将 HStack 对齐设置为 top 将图像的顶部与文本的顶部对齐,像这样...

var body: some View {
    HStack(alignment: .top) {
        Image(systemName: "circle.fill")
            .font(.system(size: 8))
        Text("This is really really really really really really really really really really really really really really really really really really really really really really really really long string.")
    }
}

更新 2:

我能想到的唯一选择是this,除了这是 UIKit...

// Aligns the icon to the center of a capital letter in the first line
let offset = label.font.capHeight / 2.0

// Aligns the icon to the center of the whole line, which is different
// than above. Especially with big fonts this makes a visible difference.
let offset = (label.font.ascender + label.font.descender) / 2.0

let constraints: [NSLayoutConstraint] = [
  imageView.centerYAnchor.constraint(equalTo: label.firstBaselineAnchor, constant: -offset),
  imageView.trailingAnchor.constraint(equalTo: label.leadingAnchor, constant: -10)
]
NSLayoutConstraint.activate(constraints)

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    这是一个基于自定义对齐的解决方案。使用 Xcode 11.4 / iOS 13.4 测试

    extension VerticalAlignment {
        private enum XAlignment : AlignmentID {
            static func defaultValue(in d: ViewDimensions) -> CGFloat {
                return d[VerticalAlignment.top]
            }
        }
        static let xAlignment = VerticalAlignment(XAlignment.self)
    }
    
    struct DemoAlignFirstLine: View {
    
        var body: some View {
            HStack(alignment: .xAlignment) {
                Image(systemName: "circle.fill")
                    .font(.system(size: 8))
                    .alignmentGuide(.xAlignment) { $0.height / 2.0 }
    
                ZStack(alignment: .topLeading) {
                    // invisible anchor, should be of same font as text
                    Text("X").foregroundColor(.clear)  
                        .alignmentGuide(.xAlignment) { $0.height / 2.0 }
    
                    // main text
                    Text("This is really really really really really really really really really really really really really really really really really really really really really really really really long string.")
                }
            }
        }
    }
    

    【讨论】:

    • 谢谢。这与文本基线对齐,而不是中心。
    【解决方案2】:

    假设所有文本行的基线之间的高度/距离都相同,我们可以受益于提供给.alignmentGuide 的尺寸具有第一个和最后一个基线,并获得第一个的高度(实际上, any) 线,只需从视图高度中减去最后一条基线和第一条基线之间的距离即可。

    重用@Asperi提供的答案条款,这是不需要引入ZStack/fake view的解决方案:

    extension VerticalAlignment {
        private enum XAlignment : AlignmentID {
            static func defaultValue(in d: ViewDimensions) -> CGFloat {
                return d[VerticalAlignment.top]
            }
        }
        static let xAlignment = VerticalAlignment(XAlignment.self)
    }
    
    struct DemoAlignFirstLine: View {
        
        var body: some View {
            HStack(alignment: .xAlignment) {
                Image(systemName: "circle.fill")
                    .font(.system(size: 8))
                    .alignmentGuide(.xAlignment) { $0.height / 2.0 }
    
                // main text
                Text("This is really really really really really really really really really really really really really really really really really really really really really really really really long string.")
                    .alignmentGuide(.xAlignment) {
                         ($0.height - ($0[.lastTextBaseline] - $0[.firstTextBaseline])) / 2
                    }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      iOS 14 你可以使用Label

      Label {
          Text("This is really really really really really really really really really really really really really really really really really really really really really really really really long string.")
      } icon: {
          Image(systemName: "circle.fill")
                      .font(.system(size: 8))
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-14
        • 2013-05-19
        • 2020-11-23
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        • 2019-01-04
        • 2017-02-02
        • 1970-01-01
        相关资源
        最近更新 更多