SwiftUI -如何在不移动图像的情况下将文本定位在图像下方?

mf98qq94  于 2023-03-22  发布在  Swift
关注(0)|答案(4)|浏览(227)

我已经附上了一张显示我想要的图像。下面示例中的红色圆圈代表图像:

图像(红色圆圈)必须在其容器中垂直居中。如何使文本水平居中并位于图像下方?如果我使用VStack,VStack将居中而不是图像-图像将向上移动。我不知道图像的大小。

6bc51xsx

6bc51xsx1#

你可以使用offset来设置circle后面的文字。下面的代码可以帮助你:

struct ContentView: View {
    @State private var circleRadius: CGFloat = 0
    var body: some View {
        ZStack {
            LinearGradient(colors: [.blue, .blue], startPoint: .trailing, endPoint: .bottomTrailing)

            VStack(alignment: .center) {
                Circle()
                    .frame(width: 100, height: 100)
                    .foregroundColor(.red)
                    .overlay(GeometryReader { geometry in
                        Color.clear
                        .onAppear {
                        self.circleRadius = geometry.size.width / 2
                    }
                })
            }
            HStack(alignment: .center) {
                Text("Text")
                    .offset(y: circleRadius + 20)
                    .foregroundColor(.white)
            }
        }
    }
}
agxfikkp

agxfikkp2#

这是一个伟大的使用覆盖组合与对准指南。

Circle().fill(Color.red)
        .frame(width: 100, height: 100)
        .overlay(alignment: .bottom) {
            Text("Title")
                .foregroundColor(.white)
                .alignmentGuide(.bottom) { _ in
                    0 // + additiona padding
                }
        }
        //  The last two lines are just the "blue container
        .frame(width: 200, height: 200)
        .background(Color.blue)

请注意,这是一个简单且可扩展的解决方案,不需要任何花哨的代码,只需要一个对齐指南。

w6lpcovy

w6lpcovy3#

SwiftUI带有两个强大的修饰符:overlaybackground。当您希望添加子视图而不影响其他视图的布局时,这些视图特别有用。
您的问题有点不同-您试图将子视图固定到父视图的边界之外的边缘-但overlay仍然可以工作。下面是一个包含GeometryReader的可能解决方案:

extension View {

    /// Pins a child view to the top or bottom of the parent.
    func extendingVStack<Content>(
        edge: VerticalEdge, /// Either .top or .bottom.
        alignment: HorizontalAlignment = .center,
        spacing: CGFloat? = nil,
        @ViewBuilder content: @escaping () -> Content
    ) -> some View where Content: View {
        /// Use an `overlay` to prevent affecting other views in the hierarchy.
        overlay {
            /// This lets you get the size of the parent view.
            GeometryReader { geometry in

                /**
                 GeometryReader's default alignment is finicky — we should override it with our own alignment
                 First, we use`Color.clear`, which expands to fill the geometry reader's space
                 Then, we can add an `overlay` with a custom alignment.
                 */
                Color.clear
                    .overlay(
                        alignment: edge == .top
                            ? .bottom /// If the desired edge is `top`, the content should be pinned to the bottom.
                            : .top /// If the desired edge is `bottom`, the content should be pinned to the top.
                    ) {
                        VStack(alignment: alignment, spacing: spacing) {
                            if edge == .top {
                                content()
                            }

                            Color.clear
                                .frame(height: geometry.size.height) /// Placeholder for positioning — should match the frame of the parent view.

                            if edge == .bottom {
                                content()
                            }
                        }
                    }
            }
        }
    }
}

用法:

struct ContentView: View {
    var body: some View {
        ZStack {
            Circle()
                .fill(Color.red)
                .frame(width: 50, height: 50)
                .extendingVStack(edge: .bottom) { /// here!
                    Text("Text")
                        .foregroundColor(.white)
                }
        }
        .frame(width: 150, height: 150)
        .background(Color.blue)
    }
}

envsm3lx

envsm3lx4#

我不太清楚你到底想达到什么目的,但如果你只是想让文本在图像下居中,这应该可以解决你的问题。然而,如果文本是多行的,文本的y位置将向上移动,除非一切都是固定的,或者文本字体在单行中缩小。

struct CenteredImageView: View {
    let imageSize: CGSize = CGSize(width: 50, height: 50)
    let containerSize: CGSize = CGSize(width: 150, height: 150)
    var body: some View {
        ZStack(alignment: .center) {
            Circle()
                .fill(Color.red)
                .frame(width: imageSize.width, height: imageSize.height)
                .position(x: containerSize.width / 2, y: containerSize.height / 2)
            Text("Text")
                .foregroundColor(.white)
                .multilineTextAlignment(.center)
                .position(x: containerSize.width / 2, y: containerSize.height / 2 + (imageSize.height * 0.70))
        }
        .frame(width: containerSize.width, height: containerSize.height)
        .background(Color.blue)
        .cornerRadius(5)
    }
}

相关问题