Zelko
Zelko

Reputation: 3961

How do you stroke text using AttributedString in iOS 15?

iOS 15 includes support for AttributedString

Example

struct PlaygroundView: View {
    func attributedString(string: String) -> AttributedString {
        var text = AttributedString(string)
        text.font = .largeTitle.bold()
        text.foregroundColor = .blue
        return text
    }
    
    var body: some View {
        Text(attributedString(string: "Hello"))
    }
}

Attributed text

Documentation mentions Attribute Scopes

The AttributedString API defines keys for common uses, such as text styling, semantically marking up formattable types like dates and numbers, and hyperlinking. You can find these in the AttributeScopes enumeration, which contains attributes for Foundation, SwiftUI, UIKit, and AppKit.

Here's strokeColor for the stroke color attribute, but it appears to do nothing.

struct PlaygroundView: View {
    func attributedString(string: String) -> AttributedString {
        var text = AttributedString(string)
        text.font = .largeTitle.bold()
        text.foregroundColor = .blue
        text.strokeWidth = 5
        text.strokeColor = .red
        return text
    }
    
    var body: some View {
        Text(attributedString(string: "Hello"))
    }
}

Attributed text

Additional docs:

Upvotes: 6

Views: 6327

Answers (2)

rahulrs
rahulrs

Reputation: 300

strokeWidth in AttributedString doesn't work with SwiftUI.

I asked similar question on Twitter after WWDC 2021 and I got a reply from Foundation Engineer at Apple. This was the reply:

.strokeWidth is an AppKit/UIKit defined attribute so it isn’t guaranteed to work with SwiftUI automatically. You can find all of the attributes supported by SwiftUI at https://developer.apple.com/documentation/foundation/attributescopes/swiftuiattributes

If you want to use stroked text with SwiftUI, you will need to use UIViewRepresentable view as a workaround. Create a UILabel and set a NSAttributedString with strokeWidth to attributedText property of UILabel.

Upvotes: 12

Asperi
Asperi

Reputation: 257693

We have to use attributes from SwiftUI AttributeScopes.

Here are all attributes supported now by SwiftUI and (stroke* are not presented in the list, although it replicates some attributes from UIKit scope):

extension AttributeScopes {

    /// A property for accessing the attribute scopes defined by SwiftUI.
    @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
    public var swiftUI: AttributeScopes.SwiftUIAttributes.Type { get }

    /// Attribute scopes defined by SwiftUI.
    @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
    public struct SwiftUIAttributes : AttributeScope {

        /// A property for accessing a font attribute.
        public let font: AttributeScopes.SwiftUIAttributes.FontAttribute

        /// A property for accessing a foreground color attribute.
        public let foregroundColor: AttributeScopes.SwiftUIAttributes.ForegroundColorAttribute

        /// A property for accessing a background color attribute.
        public let backgroundColor: AttributeScopes.SwiftUIAttributes.BackgroundColorAttribute

        /// A property for accessing a strikethrough style attribute.
        public let strikethroughStyle: AttributeScopes.SwiftUIAttributes.StrikethroughStyleAttribute

        /// A property for accessing an underline style attribute.
        public let underlineStyle: AttributeScopes.SwiftUIAttributes.UnderlineStyleAttribute

        /// A property for accessing a kerning attribute.
        public let kern: AttributeScopes.SwiftUIAttributes.KerningAttribute

        /// A property for accessing a tracking attribute.
        public let tracking: AttributeScopes.SwiftUIAttributes.TrackingAttribute

        /// A property for accessing a baseline offset attribute.
        public let baselineOffset: AttributeScopes.SwiftUIAttributes.BaselineOffsetAttribute

        /// A property for accessing attributes defined by the Accessibility framework.
        public let accessibility: AttributeScopes.AccessibilityAttributes

        /// A property for accessing attributes defined by the Foundation framework.
        public let foundation: AttributeScopes.FoundationAttributes

        public typealias DecodingConfiguration = AttributeScopeCodableConfiguration

        public typealias EncodingConfiguration = AttributeScopeCodableConfiguration
    }
}

Upvotes: 2

Related Questions