Skip to content

Commit

Permalink
Added placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
kenmueller committed Feb 26, 2020
1 parent cb641ab commit 155e003
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 46 deletions.
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ let package = Package(
name: "TextView",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13)
],
products: [
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
- `isEditing: Binding<Bool>`
- The `TextView` will modify the value when it is selected and deselected
- You can also modify this value to automatically select and deselect the `TextView`
- `placeholder: String? = nil`
- `textAlignment: TextView.TextAlignment = .left`
- `placeholderAlignment: Alignment = .topLeading`
- `placeholderHorizontalPadding: CGFloat = 4.5`
- `placeholderVerticalPadding: CGFloat = 7`
- `font: UIFont = .preferredFont(forTextStyle: .body)`
- By default, the font is a body-style font
- `textColor: UIColor = .black`
- `placeholderColor: Color = .gray`
- `backgroundColor: UIColor = .white`
- `contentType: TextView.ContentType? = nil`
- For semantic purposes only
Expand Down Expand Up @@ -48,7 +53,11 @@ struct ContentView: View {
}) {
Text("\(isEditing ? "Stop" : "Start") editing")
}
TextView(text: $input, isEditing: $isEditing)
TextView(
text: $input,
isEditing: $isEditing,
placeholder: "Enter text here"
)
}
}
}
Expand Down
204 changes: 160 additions & 44 deletions Sources/TextView/TextView.swift
Original file line number Diff line number Diff line change
@@ -1,46 +1,134 @@
#if !os(macOS)

import SwiftUI

@available(iOS 13.0, *)
public struct TextView: UIViewRepresentable {
public typealias TextAlignment = NSTextAlignment
public typealias ContentType = UITextContentType
public typealias Autocorrection = UITextAutocorrectionType
public typealias Autocapitalization = UITextAutocapitalizationType

public final class Coordinator: NSObject, UITextViewDelegate {
private let parent: TextView

public init(_ parent: TextView) {
self.parent = parent
public struct TextView: View {
public struct Representable: UIViewRepresentable {
public final class Coordinator: NSObject, UITextViewDelegate {
private let parent: Representable

public init(_ parent: Representable) {
self.parent = parent
}

private func setIsEditing(to value: Bool) {
DispatchQueue.main.async {
self.parent.isEditing = value
}
}

public func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
}

public func textViewDidBeginEditing(_: UITextView) {
setIsEditing(to: true)
}

public func textViewDidEndEditing(_: UITextView) {
setIsEditing(to: false)
}
}

private func setIsEditing(to value: Bool) {
DispatchQueue.main.async {
self.parent.isEditing = value
}
@Binding private var text: String
@Binding private var isEditing: Bool

private let textAlignment: TextAlignment
private let font: UIFont
private let textColor: UIColor
private let backgroundColor: UIColor
private let contentType: ContentType?
private let autocorrection: Autocorrection
private let autocapitalization: Autocapitalization
private let isSecure: Bool
private let isEditable: Bool
private let isSelectable: Bool
private let isScrollingEnabled: Bool
private let isUserInteractionEnabled: Bool

public init(
text: Binding<String>,
isEditing: Binding<Bool>,
textAlignment: TextAlignment,
font: UIFont,
textColor: UIColor,
backgroundColor: UIColor,
contentType: ContentType?,
autocorrection: Autocorrection,
autocapitalization: Autocapitalization,
isSecure: Bool,
isEditable: Bool,
isSelectable: Bool,
isScrollingEnabled: Bool,
isUserInteractionEnabled: Bool
) {
_text = text
_isEditing = isEditing

self.textAlignment = textAlignment
self.font = font
self.textColor = textColor
self.backgroundColor = backgroundColor
self.contentType = contentType
self.autocorrection = autocorrection
self.autocapitalization = autocapitalization
self.isSecure = isSecure
self.isEditable = isEditable
self.isSelectable = isSelectable
self.isScrollingEnabled = isScrollingEnabled
self.isUserInteractionEnabled = isUserInteractionEnabled
}

public func textViewDidChange(_ textView: UITextView) {
parent.text = textView.text
public func makeCoordinator() -> Coordinator {
.init(self)
}

public func textViewDidBeginEditing(_: UITextView) {
setIsEditing(to: true)
public func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
return textView
}

public func textViewDidEndEditing(_: UITextView) {
setIsEditing(to: false)
public func updateUIView(_ textView: UITextView, context _: Context) {
textView.text = text
textView.textAlignment = textAlignment
textView.font = font
textView.textColor = textColor
textView.backgroundColor = backgroundColor
textView.textContentType = contentType
textView.autocorrectionType = autocorrection
textView.autocapitalizationType = autocapitalization
textView.isSecureTextEntry = isSecure
textView.isEditable = isEditable
textView.isSelectable = isSelectable
textView.isScrollEnabled = isScrollingEnabled
textView.isUserInteractionEnabled = isUserInteractionEnabled

_ = isEditing
? textView.becomeFirstResponder()
: textView.resignFirstResponder()
}
}

public typealias TextAlignment = NSTextAlignment
public typealias ContentType = UITextContentType
public typealias Autocorrection = UITextAutocorrectionType
public typealias Autocapitalization = UITextAutocapitalizationType

public static let defaultFont = UIFont.preferredFont(forTextStyle: .body)

@Binding private var text: String
@Binding private var isEditing: Bool

private let placeholder: String?
private let textAlignment: TextAlignment
private let placeholderAlignment: Alignment
private let placeholderHorizontalPadding: CGFloat
private let placeholderVerticalPadding: CGFloat
private let font: UIFont
private let textColor: UIColor
private let placeholderColor: Color
private let backgroundColor: UIColor
private let contentType: ContentType?
private let autocorrection: Autocorrection
Expand All @@ -54,9 +142,14 @@ public struct TextView: UIViewRepresentable {
public init(
text: Binding<String>,
isEditing: Binding<Bool>,
placeholder: String? = nil,
textAlignment: TextAlignment = .left,
placeholderAlignment: Alignment = .topLeading,
placeholderHorizontalPadding: CGFloat = 4.5,
placeholderVerticalPadding: CGFloat = 7,
font: UIFont = Self.defaultFont,
textColor: UIColor = .black,
placeholderColor: Color = .gray,
backgroundColor: UIColor = .white,
contentType: ContentType? = nil,
autocorrection: Autocorrection = .default,
Expand All @@ -69,9 +162,15 @@ public struct TextView: UIViewRepresentable {
) {
_text = text
_isEditing = isEditing

self.placeholder = placeholder
self.textAlignment = textAlignment
self.placeholderAlignment = placeholderAlignment
self.placeholderHorizontalPadding = placeholderHorizontalPadding
self.placeholderVerticalPadding = placeholderVerticalPadding
self.font = font
self.textColor = textColor
self.placeholderColor = placeholderColor
self.backgroundColor = backgroundColor
self.contentType = contentType
self.autocorrection = autocorrection
Expand All @@ -83,32 +182,49 @@ public struct TextView: UIViewRepresentable {
self.isUserInteractionEnabled = isUserInteractionEnabled
}

public func makeCoordinator() -> Coordinator {
.init(self)
private var _placeholder: String? {
text.isEmpty ? placeholder : nil
}

public func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.delegate = context.coordinator
textView.textAlignment = textAlignment
textView.font = font
textView.textColor = textColor
textView.backgroundColor = backgroundColor
textView.textContentType = contentType
textView.autocorrectionType = autocorrection
textView.autocapitalizationType = autocapitalization
textView.isSecureTextEntry = isSecure
textView.isEditable = isEditable
textView.isSelectable = isSelectable
textView.isScrollEnabled = isScrollingEnabled
textView.isUserInteractionEnabled = isUserInteractionEnabled
return textView
private var representable: Representable {
.init(
text: $text,
isEditing: $isEditing,
textAlignment: textAlignment,
font: font,
textColor: textColor,
backgroundColor: backgroundColor,
contentType: contentType,
autocorrection: autocorrection,
autocapitalization: autocapitalization,
isSecure: isSecure,
isEditable: isEditable,
isSelectable: isSelectable,
isScrollingEnabled: isScrollingEnabled,
isUserInteractionEnabled: isUserInteractionEnabled
)
}

public func updateUIView(_ textView: UITextView, context _: Context) {
textView.text = text
_ = isEditing
? textView.becomeFirstResponder()
: textView.resignFirstResponder()
public var body: some View {
GeometryReader { geometry in
ZStack {
self.representable
self._placeholder.map { placeholder in
Text(placeholder)
.font(.init(self.font))
.foregroundColor(self.placeholderColor)
.padding(.horizontal, self.placeholderHorizontalPadding)
.padding(.vertical, self.placeholderVerticalPadding)
.frame(
width: geometry.size.width,
height: geometry.size.height,
alignment: self.placeholderAlignment
)
.allowsHitTesting(false)
}
}
}
}
}

#endif

0 comments on commit 155e003

Please sign in to comment.