SwiftUI Text неожиданные отступы снизу и сверху
Мне нужен точный контроль над областью, занимаемой текстом. Я создал самую простую программу, которая показывает неожиданные верхние и нижние интервалы, добавляемые к тексту. Откуда эта дополнительная набивка? Как от этого избавиться?
@mainstruct myApp: App {
init() { }
var body: some Scene {
WindowGroup {
Text("80")
.font(.system(size: 30, weight: .bold, design: .default))
.background(Color.red)
}
}
}
3 ответа
Кажется, что у текста есть отступы по умолчанию, как показано здесь
Вы можете обойти это, настроив отступ на отрицательное значение.
Замените свой код этим
Text("80")
.font(.system(size: 30, weight: .bold, design: .default))
.padding(.vertical, -6)
.background(Color.red)
Вот решение, если вы хотите сделать его динамичным
struct TestView: View {
var fontSize: CGFloat = 110
var paddingSize: CGFloat {
-(fontSize * 0.23)
}
var body: some View {
Text("80")
.font(.system(size: fontSize, weight: .bold, design: .default))
.padding(.vertical, paddingSize)
.background(Color.red)
Text("Hello")
}
}
Таким образом, даже с большим размером шрифта 110, как на картинке, вы можете отобразить его так, как вам нравится.
Вам нужно будет настроить множитель по своему усмотрению.
Оказывается, обивки сверху и снизу на самом деле нет вообще. В моем примере с числами это выглядит как потраченное впустую пространство, но на самом деле некоторым персонажам действительно нужна эта комната, как видно на этой картинке:
Поскольку я собираюсь показывать только числа, я использовал решение @Sergio, чтобы исправить это превышение.
Для всех, кто все еще борется с этим, позвольте мне добавить свой подход в список. Я знаю, что это не пустая трата места, учитывая такие символы, как Ö и g, но при разработке с сеткой вы обычно хотите использовать высоту прописной буквы шрифта.
Мой подход все еще немного хакерский, но я не хотел использовать магические числа. Хитрость заключается в том, что с помощьюboundingRect
Строковая функция, вы можете получить точную высоту одной строки текста, включая отступы:
let uiFont = UIFont.systemFont(ofSize: 40, weight: .semibold)
let heightOfOneLine = "X".boundingRect(
with: CGSize(width: CGFloat(10), height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: uiFont],
context: nil
).size.height
Вы можете использовать это, чтобы затем вычислить вертикальный отступ на основе высоты шапки шрифта:
let padding = (heightOfOneLine - uiFont.capHeight) / 2
Это вертикальный отступ, который вам нужно вычесть, чтобы получить область с точно такой же высотой:
.padding(.vertical, -padding)
Убедитесь, что либо используете для своего текста, преобразовав его в a, либо создайте с теми же свойствами. Жаль, что до сих пор нет возможности выбраться изFont
и что вы можете использовать толькоUIFont
для этих вычислений.
Вы можете протестировать все это, используя следующий вид:
struct TestView: View {
private let uiFont = UIFont.systemFont(ofSize: 200, weight: .semibold)
var body: some View {
Text("X")
.font(Font(uiFont))
.padding(.vertical, -getPadding())
.background(.red)
}
private func getPadding() -> CGFloat {
let heightOfOneLine = "X".boundingRect(
with: CGSize(width: CGFloat(10), height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: uiFont],
context: nil
).size.height
return (heightOfOneLine - uiFont.capHeight) / 2
}
}