SwiftUI:如何将视图与HStack的子视图对齐?

时间:2020-01-18 23:57:14

标签: view swiftui ios13

我想将圆对齐到TileView“ 1”的左上方中心。还有其他类似UIView的中心约束吗?

enter image description here

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))

        }
    }
}

2 个答案:

答案 0 :(得分:1)

在这里可以使用自定义对齐指南

SwiftUI center dependent shapes

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] }

        }
    }
}

答案 1 :(得分:0)

使用 GeometryReader 首选项

portrait mode

landscape mode

GeometryReader -让我们获取视图的geometryProxy(根据父视图/父提供的空间)

注意:-子视图保持不变(父母不能强迫其位置或大小)

.preference(key:,value:)-使用此修饰符,我们可以从视图中获取一些值(geometryProxy)。这样我们也可以从父级访问子级的几何代理。

以下是

有关这些主题的任何问题的评论。

这是代码, (加点-您可以轻松地为圈子的位置设置动画。(添加 .animation()修饰符。例如,如果您希望用户触摸标题时圈子移动)

完整代码


rowList = tlist[0]

代码说明->

我想从子视图中获取的

数据模型

x = np.array(rowList)

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()
    }   
}

defaultValue-当未设置显式值时,SwiftUI使用此选项 reduce()-当SwiftUI要提供值时可以调用(我们可以在具有相同键的许多视图上使用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() } } 修饰符