[英]SwiftUI: How to align view to HStack's subview?
I want to align the circle to the TileView "1"'s center at top left.我想将圆圈与左上角的 TileView“1”的中心对齐。 Is there any other like centre constraint of UIView?
UIView还有其他类似的中心约束吗?
struct BoardView: View {
var body: some View {
ZStack {
VStack {
HStack {
TileView(number: 1)
TileView(number: 2)
}
HStack {
TileView(number: 3)
TileView(number: 4)
}
}
Circle()
.frame(width: 30, height: 30)
.foregroundColor(Color.red.opacity(0.8))
}
}
}
Here is possible approach using custom alignment guides这是使用自定义对齐指南的可能方法
extension VerticalAlignment {
private enum VCenterAlignment: AlignmentID {
static func defaultValue(in dimensions: ViewDimensions) -> CGFloat {
return dimensions[VerticalAlignment.center]
}
}
static let vCenterred = VerticalAlignment(VCenterAlignment.self)
}
extension HorizontalAlignment {
private enum HCenterAlignment: AlignmentID {
static func defaultValue(in dimensions: ViewDimensions) -> CGFloat {
return dimensions[HorizontalAlignment.center]
}
}
static let hCenterred = HorizontalAlignment(HCenterAlignment.self)
}
struct BoardView: View {
var body: some View {
ZStack(alignment: Alignment(horizontal: .hCenterred, vertical: .vCenterred)) {
VStack {
HStack {
TileView(number: 1)
.alignmentGuide(.vCenterred) { $0[VerticalAlignment.center] }
.alignmentGuide(.hCenterred) { $0[HorizontalAlignment.center] }
TileView(number: 2)
}
HStack {
TileView(number: 3)
TileView(number: 4)
}
}
Circle()
.frame(width: 30, height: 30)
.foregroundColor(Color.red.opacity(0.8))
.alignmentGuide(.vCenterred) { $0[VerticalAlignment.center] }
.alignmentGuide(.hCenterred) { $0[HorizontalAlignment.center] }
}
}
}
Using GeometryReader and preference使用GeometryReader和偏好
GeometryReader - let us to get geometryProxy of a view ( according to the parent view / space provide by parent ) GeometryReader - 让我们获取一个视图的geometryProxy(根据父视图/父提供的空间)
Note:- child view stays at their own (parent cant force them position or size)注意:- 子视图保持在自己的位置(父母不能强迫他们的位置或大小)
.preference(key:,value:) - this modifier let us get some values( geometryProxy ) out of the view. .preference(key:,value:) - 这个修饰符让我们从视图中获取一些值(geometryProxy)。 so that we can access child's geometry proxy from parent as well.
这样我们也可以从父级访问子级的几何代理。
comment below for any question about these topics.关于这些主题的任何问题,请在下方评论。
here is the code, (plus point - you can animate your circle's position easily.(by adding .animation() modifier. Ex- if you want your circle move when user touch on a title)这是代码,(加分 - 您可以轻松地为圆圈的位置设置动画。(通过添加.animation()修饰符。例如,如果您希望在用户触摸标题时移动圆圈)
complete code完整代码
import SwiftUI
struct ContentView: View {
@State var centerCoordinateOfRectangele: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
var body: some View {
ZStack {
VStack {
HStack {
GeometryReader { (geometry) in
TileView(number: 1)
.preference(key: MyPreferenceKey.self, value: MyPreferenceData(x: geometry.frame(in: .named("spaceIWantToMoveMyView")).midX, y: geometry.frame(in: .named("spaceIWantToMoveMyView")).midY))
}
TileView(number: 2)
}.onPreferenceChange(MyPreferenceKey.self) { (value) in
self.centerCoordinateOfRectangele = value
}
HStack {
TileView(number: 3)
TileView(number: 4)
}
}
Circle()
.frame(width: 30, height: 30)
.foregroundColor(Color.red.opacity(0.8))
.position(x: centerCoordinateOfRectangele.x, y: centerCoordinateOfRectangele.y)
}
.coordinateSpace(name: "spaceIWantToMoveMyView") //to get values relative to this layout
// watch where i have use this name
}
}
struct TileView: View{
let number: Int
var body: some View{
GeometryReader { (geometry) in
RoundedRectangle(cornerRadius: 30)
}
}
}
struct MyPreferenceData:Equatable {
let x: CGFloat
let y: CGFloat
}
struct MyPreferenceKey: PreferenceKey {
typealias Value = MyPreferenceData
static var defaultValue: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
static func reduce(value: inout MyPreferenceData, nextValue: () -> MyPreferenceData) {
value = nextValue()
}
}
Code explanation ->代码解释->
data model which I want to grab from the child view我想从子视图中获取的数据模型
struct MyPreferenceData:Equatable {
let x: CGFloat
let y: CGFloat
}
Key钥匙
struct MyPreferenceKey: PreferenceKey {
typealias Value = MyPreferenceData
static var defaultValue: MyPreferenceData = MyPreferenceData(x: 0, y: 0)
static func reduce(value: inout MyPreferenceData, nextValue: () -> MyPreferenceData) {
value = nextValue()
}
}
defaultValue - SwiftUI use this, when there are no explicit value set reduce() - getCalled when SwiftUI want to give values (we can use .preference()
modifier on many views with the same key) defaultValue - SwiftUI 使用这个,当没有明确的值集时 reduce() - getCalled 当 SwiftUI 想要给出值时(我们可以在具有相同键的许多视图上使用
.preference()
修饰符)
we add the .preference()
modifier which we want to get values我们添加我们想要获取值的
.preference()
修饰符
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.