文本对齐将无法使用 AttributedString SwiftUI 3

Text alignment won't work using AttributedString SwiftUI 3

我尝试在 SwiftUI 3

中使用新的 AttributedString

我想更改对齐方式,但行不通。 其他任何事情都工作正常,例如我尝试使用 attributedString 更改颜色它确实有效!。但是我不能用 paragraphStyle

做任何事情
struct ContentView: View {
    var body: some View {
       
        ZStack {
            
            Color(uiColor: UIColor(red: 0.92, green: 0.92, blue: 0.92, alpha: 1.00)).ignoresSafeArea()
                        
            VStack {
                
                Text("""
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
""" ) { string in
                    let paragraphStyle = NSMutableParagraphStyle()
                    paragraphStyle.alignment = .right

                    string.paragraphStyle = paragraphStyle
                    
                    string.foregroundColor = .blue
                }
                    .padding()
                    .textSelection(.enabled)
                

                Spacer()
                
            }
            
        }
        
    }

}

extension Text {
init(_ string: String, configure: ((inout AttributedString) -> Void)) {
    var attributedString = AttributedString(string) /// create an `AttributedString`
    configure(&attributedString) /// configure using the closure
    self.init(attributedString) /// initialize a `Text`
}
}

paragraphStyle 属性在 UIKit scope 中定义但未在 SwiftUI 中定义,因此您不能指望它起作用。

替代方法是使用修饰符 .multilineTextAlignment(.trailing)

如你所说。 AttributedString 不适用于 SwiftUI 。实际上 Text 满足 AttributedString 所能做的一切。

paragraphStyle 在文本超过 1 行时很有用。 SwiftUI 说。如果你有 1 行使用

  Text("bla bla").frame(maxWidth: .infinity, alignment: .trailing)

如果您的文本超过 1 行,请使用

 var body: some View {
   
    ZStack {
        
        Color(UIColor(red: 0.92, green: 0.92, blue: 0.92, alpha: 1.00)).ignoresSafeArea()
                    
        VStack{
          
            
            Text("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
           .frame(maxWidth: .infinity, alignment: .trailing)
           .multilineTextAlignment(textAlignment)
            

            Spacer()
            
        }
        
    }
    
}

let textAlignment: TextAlignment = {
    var textAlign = TextAlignment.trailing
    
    
    if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
        textAlign = TextAlignment.trailing
       } else {
        textAlign = TextAlignment.leading
       }
    return textAlign
    
}()

首先谢谢你Omer Tekbiyik 你告诉我如何让它发挥作用。

TextAlignment 的问题是它取决于 trailingleading 不是 leftright ,这意味着如果您的设备使用 LTR 语言 leading 将是 left 并且 trailing 将是 right 但在 RTL 上,它将是相反的 leading 将是 righttrailing离开.

所以我添加了什么,首先我检查文本语言本身是 RTL 还是 LTR 取决于 NaturalLanguage ,然后我使用 layoutDirection 检查设备布局,就像使用 UIApplication.shared.userInterfaceLayoutDirection 但是在 SwiftUI 代码上。

注意,如果文本内容为一行文本.

,此行将起作用

.frame(maxWidth: .infinity, alignment: naturalAlignment)

但是这一行将处理连续多行文本的文本。

.multilineTextAlignment(naturalTextAlignment)

import SwiftUI
import NaturalLanguage

struct NaturalText: View {
    @Environment(\.layoutDirection) private var layoutDirection
    var text : String
    var body: some View {
            Text(text)
           .frame(maxWidth: .infinity, alignment: naturalAlignment)
            .multilineTextAlignment(naturalTextAlignment)
    }
    private var naturalAlignment: Alignment {
        guard let dominantLanguage = dominantLanguage else {
            // If we can't identify the strings language, use the system language's natural alignment
            return .leading
        }
        switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
        case .leftToRight:
            if layoutDirection == .rightToLeft {
                return .trailing
            } else {
                return .leading
            }
        case .rightToLeft:
            if layoutDirection == .leftToRight {
                return .trailing
            } else {
                return .leading
            }
        case .natural:
            return .leading
        @unknown default:
            return .leading
        }
    }

    private var naturalTextAlignment: TextAlignment {
        guard let dominantLanguage = dominantLanguage else {
            // If we can't identify the strings language, use the system language's natural alignment
            return .leading
        }
        switch NSParagraphStyle.defaultWritingDirection(forLanguage: dominantLanguage) {
        case .leftToRight:
            if layoutDirection == .rightToLeft {
                return .trailing
            } else {
                return .leading
            }
        case .rightToLeft:
            if layoutDirection == .leftToRight {
                return .trailing
            } else {
                return .leading
            }
        case .natural:
            return .leading
        @unknown default:
            return .leading
        }
    }
    private var dominantLanguage: String? {
        let firstChar = "\(text.first ?? " ")"
           return NLLanguageRecognizer.dominantLanguage(for: firstChar)?.rawValue
    }
}

如何使用

struct ContentView: View {
    
    
    var body: some View {
        
        VStack {
        
            NaturalTextView(text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
                .padding()

            
            NaturalTextView(text: "هذا النص هو مثال لنص يمكن أن يستبدل في نفس المساحة، لقد تم توليد هذا النص من مولد النص العربى، حيث يمكنك أن تولد مثل هذا النص أو العديد من النصوص الأخرى إضافة إلى زيادة عدد الحروف التى يولدها التطبيق.إذا كنت تحتاج إلى عدد أكبر من الفقرات يتيح لك مولد النص العربى زيادة عدد الفقرات كما تريد، النص لن يبدو مقسما ولا يحوي أخطاء لغوية، مولد النص العربى مفيد لمصممي المواقع على وجه الخصوص، حيث يحتاج العميل فى كثير من الأحيان أن يطلع على صورة حقيقية لتصميم الموقع.ومن هنا وجب على المصمم أن يضع نصوصا مؤقتة على التصميم ليظهر للعميل الشكل كاملاً،دور مولد النص العربى أن يوفر على المصمم عناء البحث عن نص بديل لا علاقة له بالموضوع الذى يتحدث عنه التصميم فيظهر بشكل لا يليق. هذا النص يمكن أن يتم تركيبه على أي تصميم دون مشكلة فلن يبدو وكأنه نص منسوخ، غير منظم، غير منسق، أو حتى غير مفهوم. لأنه مازال نصاً بديلاً ومؤقتاً.")
                .padding()

         
            Spacer()
        }
        
    }

}

结果

你可以使用

.environment(\.layoutDirection, .rightToLeft)

强制布局为 RTL,您会注意到它不会改变,因为它取决于文本语言本身