【问题标题】:Return Text from a SwiftUI View从 SwiftUI 视图返回文本
【发布时间】:2021-11-25 01:53:07
【问题描述】:

我有一个自定义的View,它基本上用一些附加功能包装了Text。例如。根据环境中的值对文本进行不同的格式化。

我想使用这个自定义视图来代替 Text,即我希望能够在其上使用像 .bold() 这样的修饰符。
是否可以从 View 结构返回 Text

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    这里有两种方法:

    方式 1:您可以在 CustomView 上使用 .bold()

    struct CustomTextView: View {
        
        @Environment(\.font) var environmentFont: Font?
        
        private let boldAllowed: Bool
        let string: String
        
        
        private init(boldAllowed: Bool, string: String) {
            self.boldAllowed = boldAllowed
            self.string = string
            
        }
        
        init(_ string: String) {
            self.init(boldAllowed: false, string: string)
        }
        
        var body: some View {
            
            Text(string)
                .font(boldAllowed ? environmentFont?.bold() : environmentFont)
                .foregroundColor(Color.red)                                      //  <--- :::  some custom work here!  :::
            
        }
        
        func bold() -> CustomTextView {
            
            return CustomTextView(boldAllowed: true, string: string)
            
        }
        
    }
    

    用例:

    struct ContentView: View {
        
        var body: some View {
            
            VStack {
                
                Text("Hello, World!")
                
                CustomTextView("Hello, World!")
                    .bold()
                
                CustomTextView("Hello, World!")
                
            }
            .font(Font.title.italic())
            
        }
        
    }
    

    结果:


    方式 2:您可以在任何您想要的视图上使用.bold()

    我认为这是最好的方法,因为它的代码更少,并且在任何视图上都可用!

    struct CustomBoldTextViewModifier: ViewModifier {
        
        @Environment(\.font) var environmentFont: Font?
    
        func body(content: Content) -> some View {
    
            return content
                .environment(\.font, environmentFont?.bold())
            
        }
        
    }
    
    extension View {
    
        func bold() -> some View {
    
            return self.modifier(CustomBoldTextViewModifier())
            
        }
        
    }
    

    用例:

    struct ContentView: View {
        
        var body: some View {
            
            VStack {
                
                Text("Hello, World!")
      
            }
            .bold()
            .font(Font.title.italic())
        }
        
    }
    

    结果:

    【讨论】:

    • 谢谢!您的第一个解决方案非常有帮助,并为我的用例提供了正确的方向。
    【解决方案2】:

    您可以手动获取视图的body。虽然不推荐这样做,但可能的。然而,更好的解决方案可能是传入一个闭包来修改您的文本,请参阅第二个解决方案。两个答案都达到了同样的效果。

    解决方案 #1(不推荐)

    struct ContentView: View {
        var body: some View {
            CustomText("Custom text")
                .getText()
                .bold()
                .environment(\.font, .largeTitle)
        }
    }
    
    
    struct CustomText: View {
        private let content: String
    
        init(_ content: String) {
            self.content = content
        }
    
        var body: some View {
            // Apply whatever modifiers from environment, etc.
            Text(content)
        }
    
        func getText() -> Text {
            body as! Text
        }
    }
    

    在这里,自定义文本被加粗。

    解决方案 #2(推荐)

    这个例子你只是传入了一个如何修改已经修改的自定义文本的闭包。这是我推荐的,而且看起来更干净。

    struct ContentView: View {
        var body: some View {
            CustomText("Custom text") { text in
                text
                    .bold()
                    .environment(\.font, .largeTitle)
            }
        }
    }
    
    
    struct CustomText<Content: View>: View {
        private let content: String
        private let transform: (Text) -> Content
    
        init(_ content: String, transform: @escaping (Text) -> Content) {
            self.content = content
            self.transform = transform
        }
    
        var body: some View {
            // Apply whatever modifiers from environment, etc.
            let current = Text(content)
                /* ... */
    
            return transform(current)
        }
    }
    

    【讨论】:

    • 嗨@George!谢谢您的回答!第一个解决方案似乎对我不起作用,因为getText() 中似乎没有环境可用。第二种解决方案似乎更好。当传入一个实际的String 作为参数时,我只需要让它工作,但我想我可以处理。我会试试然后回来!
    • @Martin 我已经更新了我的示例,因此您可以传入一个字符串。此外,CustomText 应该仍然可以使用该环境。
    猜你喜欢
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    相关资源
    最近更新 更多