From 931c8175514a052e2133333e87dd1eb3369b3398 Mon Sep 17 00:00:00 2001 From: LeeUngjae <73557895+NuPlay@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:07:26 +0900 Subject: [PATCH 1/4] Fix button issue, add Animation option Fixed the problem in which the button disappears And added animation options. --- Sources/ExpandableText/ExpandableText.swift | 63 +++++++++++++-------- Sources/ExpandableText/Extensions.swift | 10 +++- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/Sources/ExpandableText/ExpandableText.swift b/Sources/ExpandableText/ExpandableText.swift index c5edd4a..4d03a52 100644 --- a/Sources/ExpandableText/ExpandableText.swift +++ b/Sources/ExpandableText/ExpandableText.swift @@ -11,17 +11,17 @@ public struct ExpandableText: View { var text : String var font: Font = .body - var lineLimit : Int = 3 - var foregroundColor : Color = .primary - - var expandButtonText : String = "more" - var expandButtonColor : Color = .blue - + var lineLimit: Int = 3 + var foregroundColor: Color = .primary + + var expandButtonText: String = "more" + var expandButtonColor: Color = .blue var uiFont: UIFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body) + var animation: Animation? = .none + @State private var expand : Bool = false @State private var truncated : Bool = false - @State private var size : CGFloat = 0 - + @State private var fullSize: CGFloat = 0 public init(text: String) { self.text = text @@ -32,6 +32,7 @@ public struct ExpandableText: View { .font(font) .foregroundColor(foregroundColor) .lineLimit(expand == true ? nil : lineLimit) + .animation(animation, value: expand) .mask( VStack(spacing: 0){ Rectangle() @@ -71,24 +72,36 @@ public struct ExpandableText: View { } } .background( - Text(text) - .lineLimit(lineLimit) - .background(GeometryReader { geo in - Color.clear.onAppear() { - let size = CGSize(width: geo.size.width, height: .greatestFiniteMagnitude) - - let attributes:[NSAttributedString.Key:Any] = [NSAttributedString.Key.font: uiFont] - let attributedText = NSAttributedString(string: text, attributes: attributes) - - let textSize = attributedText.boundingRect(with: size, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil) - - if textSize.size.height > geo.size.height { - truncated = true - - self.size = textSize.size.height - } + ZStack{ + if !truncated { + if fullSize != 0 { + Text(text) + .lineLimit(lineLimit) + .background( + GeometryReader { geo in + Color.clear + .onAppear { + if fullSize > geo.size.height { + self.truncated = true + print(geo.size.height) + + } + } + } + ) } - }) + + Text(text) + .lineLimit(999) + .fixedSize(horizontal: false, vertical: true) + .background(GeometryReader { geo in + Color.clear + .onAppear() { + self.fullSize = geo.size.height + } + }) + } + } .hidden() ) } diff --git a/Sources/ExpandableText/Extensions.swift b/Sources/ExpandableText/Extensions.swift index 79cda07..5fb0855 100644 --- a/Sources/ExpandableText/Extensions.swift +++ b/Sources/ExpandableText/Extensions.swift @@ -10,7 +10,6 @@ import SwiftUI extension ExpandableText { public func font(_ font: Font) -> ExpandableText { var result = self - if #available(iOS 14.0, *) { switch font { case .largeTitle: @@ -66,8 +65,9 @@ extension ExpandableText { result.uiFont = UIFont.preferredFont(forTextStyle: .body) } } - result.font = font + result.font = font + return result } public func lineLimit(_ lineLimit: Int) -> ExpandableText { @@ -96,6 +96,12 @@ extension ExpandableText { result.expandButtonColor = color return result } + public func expandAnimation(_ animation: Animation?) -> ExpandableText { + var result = self + + result.animation = animation + return result + } } extension String { From 355950cb0d09567f21e59c03e1160c567b87d329 Mon Sep 17 00:00:00 2001 From: NuPlay <73557895+NuPlay@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:08:05 +0900 Subject: [PATCH 2/4] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e7d93f5..fa11974 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ struct ExpandableText_Test: View { .font(.body)//optional .foregroundColor(.primary)//optional .lineLimit(3)//optional - .animation(.easeOut)//optional + .expandAnimation(.easeOut)//optional .padding(.horizontal, 24)//optional } } @@ -45,5 +45,6 @@ Modifier | Default `.foregroundColor(_ color: Color)` | `.primary` `.expandButtonText(_ text: String)` | `"more"` `.expandButtonColor(_ color: Color)` | `.blue` +`.expandAnimation(_ animation: Animation?)` | `.none` From 8514d34e9fc97a82d4b9441a19d4f3174d2a8f6d Mon Sep 17 00:00:00 2001 From: LeeUngjae <73557895+NuPlay@users.noreply.github.com> Date: Sun, 6 Feb 2022 12:49:29 +0900 Subject: [PATCH 3/4] Some error corrections, add function(collapseButton) Some error corrections, Add the expandButton option, Add collapseButton. --- Sources/ExpandableText/ExpandableText.swift | 85 ++++++++----- Sources/ExpandableText/Extensions.swift | 131 +++++++++++--------- 2 files changed, 128 insertions(+), 88 deletions(-) diff --git a/Sources/ExpandableText/ExpandableText.swift b/Sources/ExpandableText/ExpandableText.swift index 4d03a52..b39a733 100644 --- a/Sources/ExpandableText/ExpandableText.swift +++ b/Sources/ExpandableText/ExpandableText.swift @@ -13,10 +13,10 @@ public struct ExpandableText: View { var font: Font = .body var lineLimit: Int = 3 var foregroundColor: Color = .primary - - var expandButtonText: String = "more" - var expandButtonColor: Color = .blue - var uiFont: UIFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body) + + var expandButton: TextSet = TextSet(text: "more", font: .body, color: .blue) + var collapseButton: TextSet? = nil + var animation: Animation? = .none @State private var expand : Bool = false @@ -41,41 +41,70 @@ public struct ExpandableText: View { HStack(spacing: 0){ Rectangle() .foregroundColor(.black) - if !expand && truncated{ - HStack(alignment: .bottom,spacing: 0){ - LinearGradient( - gradient: Gradient(stops: [ - Gradient.Stop(color: .black, location: 0), - Gradient.Stop(color: .clear, location: 0.8)]), - startPoint: .leading, - endPoint: .trailing) - .frame(width: 32, height: expandButtonText.heightOfString(usingFont: uiFont)) - - Rectangle() - .foregroundColor(.clear) - .frame(width: expandButtonText.widthOfString(usingFont: uiFont), alignment: .center) + if truncated{ + if !expand { + HStack(alignment: .bottom,spacing: 0){ + LinearGradient( + gradient: Gradient(stops: [ + Gradient.Stop(color: .black, location: 0), + Gradient.Stop(color: .clear, location: 0.8)]), + startPoint: .leading, + endPoint: .trailing) + .frame(width: 32, height: expandButton.text.heightOfString(usingFont: fontToUIFont(font: expandButton.font))) + + Rectangle() + .foregroundColor(.clear) + .frame(width: expandButton.text.widthOfString(usingFont: fontToUIFont(font: expandButton.font)), alignment: .center) + } + } + else if let collapseButton = collapseButton { + HStack(alignment: .bottom,spacing: 0){ + LinearGradient( + gradient: Gradient(stops: [ + Gradient.Stop(color: .black, location: 0), + Gradient.Stop(color: .clear, location: 0.8)]), + startPoint: .leading, + endPoint: .trailing) + .frame(width: 32, height: collapseButton.text.heightOfString(usingFont: fontToUIFont(font: collapseButton.font))) + + Rectangle() + .foregroundColor(.clear) + .frame(width: collapseButton.text.widthOfString(usingFont: fontToUIFont(font: collapseButton.font)), alignment: .center) + } } } } - .frame(height: expandButtonText.heightOfString(usingFont: uiFont)) + .frame(height: expandButton.text.heightOfString(usingFont: fontToUIFont(font: font))) } ) - if truncated && !expand { - Button(action: { - self.expand = true - }, label: { - Text(expandButtonText) - .font(font) - .foregroundColor(expandButtonColor) - }) + if truncated { + if let collapseButton = collapseButton { + Button(action: { + self.expand.toggle() + }, label: { + Text(expand == false ? expandButton.text : collapseButton.text) + .font(expand == false ? expandButton.font : collapseButton.font) + .foregroundColor(expand == false ? expandButton.color : collapseButton.color) + }) + } + else if !expand { + Button(action: { + self.expand = true + }, label: { + Text(expandButton.text) + .font(expandButton.font) + .foregroundColor(expandButton.color) + }) + } } } .background( ZStack{ - if !truncated { + if !truncated { if fullSize != 0 { Text(text) + .font(font) .lineLimit(lineLimit) .background( GeometryReader { geo in @@ -84,7 +113,6 @@ public struct ExpandableText: View { if fullSize > geo.size.height { self.truncated = true print(geo.size.height) - } } } @@ -92,6 +120,7 @@ public struct ExpandableText: View { } Text(text) + .font(font) .lineLimit(999) .fixedSize(horizontal: false, vertical: true) .background(GeometryReader { geo in diff --git a/Sources/ExpandableText/Extensions.swift b/Sources/ExpandableText/Extensions.swift index 5fb0855..184a2cb 100644 --- a/Sources/ExpandableText/Extensions.swift +++ b/Sources/ExpandableText/Extensions.swift @@ -10,64 +10,9 @@ import SwiftUI extension ExpandableText { public func font(_ font: Font) -> ExpandableText { var result = self - if #available(iOS 14.0, *) { - switch font { - case .largeTitle: - result.uiFont = UIFont.preferredFont(forTextStyle: .largeTitle) - case .title: - result.uiFont = UIFont.preferredFont(forTextStyle: .title1) - case .title2: - result.uiFont = UIFont.preferredFont(forTextStyle: .title2) - case .title3: - result.uiFont = UIFont.preferredFont(forTextStyle: .title3) - case .headline: - result.uiFont = UIFont.preferredFont(forTextStyle: .headline) - case .subheadline: - result.uiFont = UIFont.preferredFont(forTextStyle: .subheadline) - case .callout: - result.uiFont = UIFont.preferredFont(forTextStyle: .callout) - case .caption: - result.uiFont = UIFont.preferredFont(forTextStyle: .caption1) - case .caption2: - result.uiFont = UIFont.preferredFont(forTextStyle: .caption2) - case .footnote: - result.uiFont = UIFont.preferredFont(forTextStyle: .footnote) - case .body: - result.uiFont = UIFont.preferredFont(forTextStyle: .body) - default: - result.uiFont = UIFont.preferredFont(forTextStyle: .body) - } - } else { - switch font { - case .largeTitle: - result.uiFont = UIFont.preferredFont(forTextStyle: .largeTitle) - case .title: - result.uiFont = UIFont.preferredFont(forTextStyle: .title1) -// case .title2: -// result.uiFont = UIFont.preferredFont(forTextStyle: .title2) -// case .title3: -// result.uiFont = UIFont.preferredFont(forTextStyle: .title3) - case .headline: - result.uiFont = UIFont.preferredFont(forTextStyle: .headline) - case .subheadline: - result.uiFont = UIFont.preferredFont(forTextStyle: .subheadline) - case .callout: - result.uiFont = UIFont.preferredFont(forTextStyle: .callout) - case .caption: - result.uiFont = UIFont.preferredFont(forTextStyle: .caption1) -// case .caption2: -// result.uiFont = UIFont.preferredFont(forTextStyle: .caption2) - case .footnote: - result.uiFont = UIFont.preferredFont(forTextStyle: .footnote) - case .body: - result.uiFont = UIFont.preferredFont(forTextStyle: .body) - default: - result.uiFont = UIFont.preferredFont(forTextStyle: .body) - } - } result.font = font - + return result } public func lineLimit(_ lineLimit: Int) -> ExpandableText { @@ -84,18 +29,20 @@ extension ExpandableText { return result } - public func expandButtonText(_ text: String) -> ExpandableText { + public func expandButton(_ expandButton: TextSet) -> ExpandableText { var result = self - result.expandButtonText = text + result.expandButton = expandButton return result } - public func expandButtonColor(_ color: Color) -> ExpandableText { + + public func collapseButton(_ collapseButton: TextSet) -> ExpandableText { var result = self - result.expandButtonColor = color + result.collapseButton = collapseButton return result } + public func expandAnimation(_ animation: Animation?) -> ExpandableText { var result = self @@ -117,3 +64,67 @@ extension String { return size.width } } + +public struct TextSet { + var text: String + var font: Font + var color: Color +} + +func fontToUIFont(font: Font) -> UIFont { + if #available(iOS 14.0, *) { + switch font { + case .largeTitle: + return UIFont.preferredFont(forTextStyle: .largeTitle) + case .title: + return UIFont.preferredFont(forTextStyle: .title1) + case .title2: + return UIFont.preferredFont(forTextStyle: .title2) + case .title3: + return UIFont.preferredFont(forTextStyle: .title3) + case .headline: + return UIFont.preferredFont(forTextStyle: .headline) + case .subheadline: + return UIFont.preferredFont(forTextStyle: .subheadline) + case .callout: + return UIFont.preferredFont(forTextStyle: .callout) + case .caption: + return UIFont.preferredFont(forTextStyle: .caption1) + case .caption2: + return UIFont.preferredFont(forTextStyle: .caption2) + case .footnote: + return UIFont.preferredFont(forTextStyle: .footnote) + case .body: + return UIFont.preferredFont(forTextStyle: .body) + default: + return UIFont.preferredFont(forTextStyle: .body) + } + } else { + switch font { + case .largeTitle: + return UIFont.preferredFont(forTextStyle: .largeTitle) + case .title: + return UIFont.preferredFont(forTextStyle: .title1) + // case .title2: + // return UIFont.preferredFont(forTextStyle: .title2) + // case .title3: + // return UIFont.preferredFont(forTextStyle: .title3) + case .headline: + return UIFont.preferredFont(forTextStyle: .headline) + case .subheadline: + return UIFont.preferredFont(forTextStyle: .subheadline) + case .callout: + return UIFont.preferredFont(forTextStyle: .callout) + case .caption: + return UIFont.preferredFont(forTextStyle: .caption1) + // case .caption2: + // return UIFont.preferredFont(forTextStyle: .caption2) + case .footnote: + return UIFont.preferredFont(forTextStyle: .footnote) + case .body: + return UIFont.preferredFont(forTextStyle: .body) + default: + return UIFont.preferredFont(forTextStyle: .body) + } + } +} From 2dd3b922ced5497c33b821853be763a0fe5145a7 Mon Sep 17 00:00:00 2001 From: NuPlay <73557895+NuPlay@users.noreply.github.com> Date: Sun, 6 Feb 2022 12:54:30 +0900 Subject: [PATCH 4/4] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa11974..e3e0006 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ struct ExpandableText_Test: View { .font(.body)//optional .foregroundColor(.primary)//optional .lineLimit(3)//optional + .expandButton(TextSet(text: "more", font: .body, color: .blue)) + .collapseButton(TextSet(text: "less", font: .body, color: .blue)) .expandAnimation(.easeOut)//optional .padding(.horizontal, 24)//optional } @@ -43,8 +45,8 @@ Modifier | Default `.font(_ font: Font)` | `.body` `.lineLimit(_ lineLimit: Int)` | `3` `.foregroundColor(_ color: Color)` | `.primary` -`.expandButtonText(_ text: String)` | `"more"` -`.expandButtonColor(_ color: Color)` | `.blue` +`.expandButton(_ expandButton: TextSet)` | `TextSet(text: "more", font: .body, color: .blue)` +`.collapseButton(_ collapseButton: TextSet)` | `nil(If it's nil, it doesn't show)` `.expandAnimation(_ animation: Animation?)` | `.none`