#swiftui
Вопрос:
Поэтому у меня есть такая точка зрения:
struct AlignmentTest: View { @State var op:Double = 1 var body: some View { VStack { HStack { Circle() .fill(.green) .opacity(op) .frame(width: 50, height: 50) Rectangle() .fill(.red) .frame(width:150, height: 50) } } } }
Он рисует это:
Учитывая один из комментариев, я делаю это редактирование:
Вопрос:
Как я могу сделать так, чтобы красный прямоугольник был центрирован (горизонтально) в VStack, а зеленый круг был прикреплен к левому краю красного прямоугольника?
Можно ли это сделать без жесткого кодирования чисел? Может быть, с направляющими для выравнивания?
Комментарии:
1. «Можно ли это сделать без жестких кодирующих чисел?» — У вас уже есть числа, жестко закодированные по ширине круга и прямоугольника. Вы думаете, что у вас там может быть что-то динамического размера? Я могу обновить свой ответ, чтобы использовать a
GeometryReader
, чтобы при необходимости ничего не было жестко закодировано, но если вы планируете уже иметь дочерние элементы, жестко закодированные по размеру, похоже, что вы также можете жестко закодировать выравнивание.2. Я планирую, вероятно, применить масштабную анимацию к кругу…. и, в общем, я пытался понять, как сделать это без цифр, поэтому, если возможно, используйте направляющие для выравнивания. Мне кажется, это самый чистый способ. Во всяком случае, именно об этом я и думал.
3. Хорошо. Я обновил свой ответ-сейчас он немного надуман, потому что рамки явно заданы, но он будет вести себя так же и с динамическим контентом.
4. Но почему, как только вы зададите вопрос с жесткими значениями кода, затем измените цель на что-то другое? Мы потратили время на этот вопрос правильно? @zumzum
Ответ №1:
- Чтобы заставить круг прилипнуть к краю прямоугольника, явно объявите
spacing
значение0
наHStack
. - Поскольку вам не нужны были жестко закодированные числа, я использовал PreferenceKeys для передачи значений ширины родителю.
Обратите внимание, что я не использую offset
, потому что это может повлиять на взаимодействие дочерних элементов с пользователем (поскольку система считает, что они расположены по-разному).
(Я добавил фон и рамку, чтобы легко визуально увидеть центрирование-их, очевидно, можно было удалить)
struct ContentView: View { @State var op:Double = 1 @State private var rectangleWidth : CGFloat = 0 @State private var circleWidth : CGFloat = 0 var body: some View { ZStack { HStack(spacing: 0) { Color.black Color.white } VStack { HStack(spacing: 0) { Circle() .fill(.green) .opacity(op) .frame(width: 50, height: 50) .background(GeometryReader { Color.clear.preference(key: CircleWidthPreferenceKey.self, value: $0.frame(in: .local).size.width) }) Rectangle() .fill(.red) .frame(width:150, height: 50) .background(GeometryReader { Color.clear.preference(key: RectangleWidthPreferenceKey.self, value: $0.frame(in: .local).size.width) }) } .onPreferenceChange(RectangleWidthPreferenceKey.self) { pref in self.rectangleWidth = pref } .onPreferenceChange(CircleWidthPreferenceKey.self) { pref in self.circleWidth = pref } .border(Color.blue) .alignmentGuide(HorizontalAlignment.center) { d in circleWidth rectangleWidth / 2 } } } } } struct CircleWidthPreferenceKey : PreferenceKey { static var defaultValue: CGFloat { 0 } static func reduce(value: inout Value, nextValue: () -gt; Value) { value = nextValue() } } struct RectangleWidthPreferenceKey : PreferenceKey { static var defaultValue: CGFloat { 0 } static func reduce(value: inout Value, nextValue: () -gt; Value) { value = nextValue() } }
Ответ №2:
Вот способ для вас:
struct AlignmentTest: View { @State var op:Double = 1 private let rectangleSize: CGSize = CGSize(width: 150.0, height: 50.0) private let circleSize: CGSize = CGSize(width: 50.0, height: 50.0) private let padding: CGFloat = 10.0 var body: some View { VStack { HStack { Rectangle() .fill(Color.red) .frame(width: rectangleSize.width, height: rectangleSize.height) .overlay( Circle() .fill(Color.green) .opacity(op) .frame(width: circleSize.width, height: circleSize.height) .offset(x: -(rectangleSize.width circleSize.width)/2.0 - padding) ) } } } }
Результат:
Ответ №3:
Думаю, вы могли бы поместить что-нибудь такой же ширины, как круг справа от прямоугольника:
VStack { HStack { Circle() .fill(.green) .opacity(op) .frame(width: 50, height: 50) Rectangle() .fill(.red) .frame(width:150, height: 50) Rectangle() .frame(width: 50, height: 0) } }