代码之家  ›  专栏  ›  技术社区  ›  Damiano Miazzi

“如何在SwiftUI中将文本置于黑色覆盖的中间?”

  •  0
  • Damiano Miazzi  · 技术社区  · 1 年前

    我在SwiftUI中难以将文本定位在黑色覆盖层的中心。我希望白色文本在我在下图中用红线标记的黑色框的中间对齐。尽管尝试了不同的对齐和填充,但我似乎无法让文本显示在我想要的地方。

    这是显示我想要文本位置的图像:

    
      image
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: customSize.width, height: customSize.height)
                                .clipped()
                                .overlay(
                                    VStack(alignment: .leading) {
                                        Spacer()
                                        HStack {
                                            VStack(alignment: .leading) {
                                                if let name = channel.tvgName {
                                                    Text(formatTitle(name))
                                                        .font(.title3.bold()) // Adjust the font size and style
                                                        .foregroundColor(.white)
                                                        .lineLimit(1)
                                                        .shadow(radius: 5) // Add shadow for better contrast
                                                        .padding(.all, 0)
                                                } else {
                                                    Text(formatTitle(channel.tvgId ?? ""))
                                                        .font(.title3.bold()) // Adjust the font size and style
                                                        .foregroundColor(.white)
                                                        .lineLimit(1)
                                                        .shadow(radius: 5) // Add shadow for better contrast
                                                        .padding(.all, 0)
                                                }
                                            }
                                            
                                            Spacer()
                                        }
                                        .padding([.leading, .bottom, .trailing], 50)
                                        .background(LinearGradient(
                                            gradient: Gradient(colors: [Color.blue, Color.blue.opacity(0.1)]),
                                            startPoint: .bottom,
                                            endPoint: .top
                                        ))
                                    }
                                )
                                
                                .cornerRadius(10)
                                .shadow(radius: 5)
                                
    
    

    全视图代码:

    import SwiftUI
    import CachedAsyncImage
    
    struct ChannelDetailsView: View {
        var channel: PlaylistItem
        var reader: GeometryProxy
        @State var customSize: CGSize = CGSize(width: 256, height: 418) // Updated size
        @State private var showByGroup = UserDefaults.standard.bool(forKey: "showByGroup")
    
        var body: some View {
            VStack(spacing: 0) {
                if let logo = channel.tvgLogo {
                    CachedAsyncImage(url: URL(string: logo)) { phase in
                        switch phase {
                        case .empty:
                            ProgressView()
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                                .background(Color.gray.opacity(0.3))
                                .cornerRadius(10)
                                .frame(width: customSize.width,
                                       height: customSize.height)
                        case .success(let image):
                            image
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: customSize.width, height: customSize.height)
                                .clipped()
                                .overlay(
                                    VStack(alignment: .leading) {
                                        Spacer()
                                        HStack {
                                            VStack(alignment: .leading) {
                                                if let name = channel.tvgName {
                                                    Text(formatTitle(name))
                                                        .font(.title3.bold()) // Adjust the font size and style
                                                        .foregroundColor(.white)
                                                        .lineLimit(1)
                                                        .shadow(radius: 5) // Add shadow for better contrast
                                                        .padding(.all, 0)
                                                } else {
                                                    Text(formatTitle(channel.tvgId ?? ""))
                                                        .font(.title3.bold()) // Adjust the font size and style
                                                        .foregroundColor(.white)
                                                        .lineLimit(1)
                                                        .shadow(radius: 5) // Add shadow for better contrast
                                                        .padding(.all, 0)
                                                }
                                            }
                                            
                                            Spacer()
                                        }
                                        .padding([.leading, .bottom, .trailing], 50)
                                        .background(LinearGradient(
                                            gradient: Gradient(colors: [Color.blue, Color.blue.opacity(0.1)]),
                                            startPoint: .bottom,
                                            endPoint: .top
                                        ))
                                    }
                                )
                                
                                .cornerRadius(10)
                                .shadow(radius: 5)
                                
                        case .failure:
                            Image(systemName: "play.display")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 50, height: 50)
                                .padding()
                                .background(Color.gray.opacity(0.3))
                                .cornerRadius(10)
                                .frame(width: customSize.width,
                                       height: customSize.height)
                        @unknown default:
                            EmptyView()
                        }
                    }
                }
            }
            .onAppear(perform: {
                customSize = reader.size
            })
            .frame(width: customSize.width, height: customSize.height)
            .background(Color.black.opacity(0.2))
            .cornerRadius(10)
            .shadow(radius: 5)
            .onAppear {
                print("width: \(reader.size.width)")
                print("height: \(reader.size.height)")
            }
            .onChange(of: reader.size) { oldValue, newValue in
                customSize = newValue
            }
        }
    
        // Function to format the title
        func formatTitle(_ title: String) -> String {
            var formattedTitle = title
            
            // Remove "4K"
            formattedTitle = formattedTitle.replacingOccurrences(of: "4K", with: "", options: .caseInsensitive)
            
            // Remove year in parentheses, e.g., "(2021)"
            let regex = try! NSRegularExpression(pattern: "\\(\\d{4}\\)", options: [])
            formattedTitle = regex.stringByReplacingMatches(in: formattedTitle, options: [], range: NSRange(location: 0, length: formattedTitle.count), withTemplate: "")
            
            // Remove any extra spaces
            formattedTitle = formattedTitle.trimmingCharacters(in: .whitespacesAndNewlines)
            
            return formattedTitle
        }
    }
    
    // Extension to apply corner radius to specific corners
    extension View {
        func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
            clipShape(RoundedCorner(radius: radius, corners: corners))
        }
    }
    
    struct RoundedCorner: Shape {
        var radius: CGFloat = .infinity
        var corners: UIRectCorner = .allCorners
    
        func path(in rect: CGRect) -> Path {
            let path = UIBezierPath(
                roundedRect: rect,
                byRoundingCorners: corners,
                cornerRadii: CGSize(width: radius, height: radius)
            )
            return Path(path.cgPath)
        }
    }
    
    

    image

    1 回复  |  直到 1 年前
        1
  •  1
  •   Sweeper    1 年前

    您可以直接将对齐传递给 overlay 改性剂。这个 Text 将自动放置在图像的底部中心。

    然后,您需要做的就是在 文本 ,并做 .frame(maxWidth: .infinity) 从而占据图像的整个宽度。最后,添加渐变背景,文本将居中显示在背景中。

    Image("some image")
        .resizable()
        .scaledToFit()
        .overlay(alignment: .bottom) {
            Text("The Instigators")
                .font(.title3.bold())
                .foregroundStyle(.white)
                .lineLimit(1)
                .shadow(radius: 5)
                .padding(.vertical, 20)
                .frame(maxWidth: .infinity)
                .background(.linearGradient(
                    colors: [.blue, .blue.opacity(0.1)],
                    startPoint: .bottom,
                    endPoint: .top
                ))
        }
        .padding()
    

    我看到您使用了很多已弃用的视图修饰符。如果您需要支持iOS 15以下的版本 alignment: 论点 覆盖层 这是iOS 15之前的第二个论点。

    .overlay(
        Text("The Instigators")
            .font(.title3.bold())
            .foregroundColor(.white)
            // ...
            ,
        alignment: .bottom
    )
    

    最后但同样重要的是,考虑更换 if let 声明-你可以这样做:

    Text(formatTitle(channel.tvgName ?? channel.tvgId ?? ""))