Skip to content

Commit

Permalink
Made HairSpaceJustifiedText public and added example to example app.
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanlintott committed Oct 21, 2024
1 parent 0513afa commit 53792a1
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 10 deletions.
4 changes: 4 additions & 0 deletions Example/FrameUpExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
CF19BC182AA7BC730096876A /* View+IfAvailable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF19BC172AA7BC730096876A /* View+IfAvailable.swift */; };
CF19BC192AA7BC780096876A /* View+IfAvailable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF19BC172AA7BC730096876A /* View+IfAvailable.swift */; };
CF1AB2B22CB5BF530049E553 /* FrameUp in Frameworks */ = {isa = PBXBuildFile; productRef = CF1AB2B12CB5BF530049E553 /* FrameUp */; };
CF1C336B2CC6C1170003069B /* HairSpaceJustifiedTextExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF1C336A2CC6C1170003069B /* HairSpaceJustifiedTextExample.swift */; };
CF1EEF30274D4C4C00987595 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF1EEF2F274D4C4C00987595 /* WidgetKit.framework */; };
CF1EEF32274D4C4C00987595 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF1EEF31274D4C4C00987595 /* SwiftUI.framework */; };
CF1EEF35274D4C4C00987595 /* WidgetFrameWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF1EEF34274D4C4C00987595 /* WidgetFrameWidget.swift */; };
Expand Down Expand Up @@ -173,6 +174,7 @@
CF19BC082AA67CA70096876A /* SharedAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SharedAssets.xcassets; sourceTree = "<group>"; };
CF19BC0B2AA67F6E0096876A /* InlineImageExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineImageExample.swift; sourceTree = "<group>"; };
CF19BC172AA7BC730096876A /* View+IfAvailable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+IfAvailable.swift"; sourceTree = "<group>"; };
CF1C336A2CC6C1170003069B /* HairSpaceJustifiedTextExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HairSpaceJustifiedTextExample.swift; sourceTree = "<group>"; };
CF1EEF2D274D4C4C00987595 /* WidgetFrameWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetFrameWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
CF1EEF2F274D4C4C00987595 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
CF1EEF31274D4C4C00987595 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -509,6 +511,7 @@
children = (
CFE981F72C9DF0F90094A1A8 /* TextExamples.swift */,
CFE981F42C9DF06B0094A1A8 /* UnclippedTextExample.swift */,
CF1C336A2CC6C1170003069B /* HairSpaceJustifiedTextExample.swift */,
);
path = TextExamples;
sourceTree = "<group>";
Expand Down Expand Up @@ -741,6 +744,7 @@
CF2D066C292201BD007D1142 /* DoubleScrollTabView.swift in Sources */,
CFC476572A0C9FC2003B51CF /* HMasonryAspectRatioExample.swift in Sources */,
CFAC14A02885BC99003D4539 /* HFlowExample.swift in Sources */,
CF1C336B2CC6C1170003069B /* HairSpaceJustifiedTextExample.swift in Sources */,
CF48CC9F26F131C200406F4E /* FrameUpExampleApp.swift in Sources */,
CFF9E74F2A0F304900451A65 /* HFlowLayoutExample.swift in Sources */,
CF25F6532901D91C0041FBAF /* HFlowSmartScrollViewExample.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// HairSpaceJustifiedTextExample.swift
// FrameUpExample
//
// Created by Ryan Lintott on 2024-10-21.
//

import FrameUp
import SwiftUI

struct HairSpaceJustifiedTextExample: View {
var body: some View {
VStack {
/// Example of Text with mixed LTR and RTL text.
Text("This ثم كلا ارتكبها إستيلاء البولندي, احداث نتيجة بالرّدأسر بـ.ثموصل جديدة aslkasjdf والكساد. ان مكثّفة العالم الهادي أضف, مما مع انذار")
.font(.system(size: 16).bold())

/// Example of HairSpaceJustified with the same mixed LTR and RTL text.
HairSpaceJustifiedText(
// Arabic for "Hello, World"
"This ثم كلا ارتكبها إستيلاء البولندي, احداث نتيجة بالرّدأسر بـ.ثموصل جديدة aslkasjdf والكساد. ان مكثّفة العالم الهادي أضف, مما مع انذار",
font: .boldSystemFont(ofSize: 16),
justifyLastLine: false
)

HairSpaceJustifiedText(
"""
This is a bunch of text justified by hair spaces. SwiftUI doesn't have a way of justifying text so this view swaps out all spaces with varying numbers of hair spaces to adjust each line and make it appear justified.
The last line of a paragraph is not justified by default but it can be by parameter.
Line breaks continue to work as expected.
Multiple line breaks remain but multiple spaces are condensed into a single space or line break.
If you have a veryLongWordThatWillNotFitOnASingleLineItWillBeBrokenAtTheLastCharacterThatFits
Words are not hyphenated.
UIFont must be used as that is how the text width is calculated.
""",
font: .boldSystemFont(ofSize: 16),
justifyLastLine: false
)
}
.padding()
}
}

#Preview {
HairSpaceJustifiedTextExample()
}
14 changes: 7 additions & 7 deletions Example/FrameUpExample/TextExamples/TextExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import SwiftUI
struct TextExamples: View {
var body: some View {
Section {
NavigationLink(destination: HairSpaceJustifiedTextExample()) {
Label("HairSpaceJustifiedText", systemImage: "character.textbox")
}

/// This check ensures this code only builds in Xcode 16+
#if compiler(>=6)
if #available(iOS 18, macOS 15, watchOS 11, tvOS 18, visionOS 2, *) {
/// This check ensures this code only builds in Xcode 16+
#if compiler(>=6)
NavigationLink(destination: UnclippedTextExample()) {
Label("Unclipped Text", systemImage: "character.textbox")
}
#else
UnavailableView(availableInLaterVersion: true)
#endif
} else {
UnavailableView(availableInLaterVersion: true)
}
#endif
} header: {
Text("Text")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Created by Ryan Lintott on 2022-11-15.
//

import SwiftUI

#if os(iOS)
Expand Down Expand Up @@ -136,18 +137,18 @@ extension StringProtocol {
}

/// A SwiftUI-only method for efficiently presenting justifying text. This is particularly useful in a widget or other SwiftUI-only setting.
struct HairSpaceJustifiedText: View {
public struct HairSpaceJustifiedText: View {
let text: String
let font: UIFont
let justifyLastLine: Bool

init(_ text: String, font: UIFont, justifyLastLine: Bool = false) {
public init(_ text: String, font: UIFont, justifyLastLine: Bool = false) {
self.font = font
self.text = text
self.justifyLastLine = justifyLastLine
}

var body: some View {
public var body: some View {
WidthReader { width in
Text(text.justifiedByHairSpaces(font: font, maxWidth: width, justifyLastLine: justifyLastLine))
.font(Font(font))
Expand Down

0 comments on commit 53792a1

Please sign in to comment.