mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Create UIViewRepresentable / UITextView for iOS post title editor
This commit is contained in:
parent
aa51935482
commit
86cf0e976d
@ -1,20 +1,95 @@
|
||||
//
|
||||
// PostTitleTextView.swift
|
||||
// WriteFreely-MultiPlatform (iOS)
|
||||
//
|
||||
// Created by Angelo Stavrow on 2020-10-27.
|
||||
//
|
||||
// Based on https://lostmoa.com/blog/DynamicHeightForTextFieldInSwiftUI/
|
||||
// and https://stackoverflow.com/a/56508132/1234545
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PostTitleTextView: View {
|
||||
var body: some View {
|
||||
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
|
||||
class Coordinator: NSObject, UITextViewDelegate, NSLayoutManagerDelegate {
|
||||
@Binding var text: String
|
||||
@Binding var isFirstResponder: Bool
|
||||
var didBecomeFirstResponder: Bool = false
|
||||
var postTitleTextView: PostTitleTextView
|
||||
|
||||
weak var textView: UITextView?
|
||||
|
||||
init(_ textView: PostTitleTextView, text: Binding<String>, isFirstResponder: Binding<Bool>) {
|
||||
self.postTitleTextView = textView
|
||||
_text = text
|
||||
_isFirstResponder = isFirstResponder
|
||||
}
|
||||
|
||||
func textViewDidChangeSelection(_ textView: UITextView) {
|
||||
DispatchQueue.main.async {
|
||||
self.postTitleTextView.text = textView.text ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
if (text == "\n") {
|
||||
self.isFirstResponder.toggle()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func layoutManager(
|
||||
_ layoutManager: NSLayoutManager,
|
||||
didCompleteLayoutFor textContainer: NSTextContainer?,
|
||||
atEnd layoutFinishedFlag: Bool
|
||||
) {
|
||||
DispatchQueue.main.async {
|
||||
guard let view = self.textView else {
|
||||
return
|
||||
}
|
||||
let size = view.sizeThatFits(view.bounds.size)
|
||||
if self.postTitleTextView.height != size.height {
|
||||
self.postTitleTextView.height = size.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PostTitleTextView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
PostTitleTextView()
|
||||
struct PostTitleTextView: UIViewRepresentable {
|
||||
@Binding var text: String
|
||||
@Binding var textStyle: UIFont
|
||||
@Binding var height: CGFloat
|
||||
@Binding var isFirstResponder: Bool
|
||||
|
||||
func makeUIView(context: UIViewRepresentableContext<PostTitleTextView>) -> UITextView {
|
||||
let textView = UITextView()
|
||||
|
||||
textView.isEditable = true
|
||||
textView.isUserInteractionEnabled = true
|
||||
textView.isScrollEnabled = true
|
||||
textView.alwaysBounceVertical = false
|
||||
|
||||
context.coordinator.textView = textView
|
||||
textView.delegate = context.coordinator
|
||||
textView.layoutManager.delegate = context.coordinator
|
||||
|
||||
let font = textStyle
|
||||
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
|
||||
textView.font = fontMetrics.scaledFont(for: font)
|
||||
|
||||
textView.backgroundColor = UIColor.clear
|
||||
|
||||
return textView
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
return Coordinator(self, text: $text, isFirstResponder: $isFirstResponder)
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<PostTitleTextView>) {
|
||||
uiView.text = text
|
||||
|
||||
let font = textStyle
|
||||
let fontMetrics = UIFontMetrics(forTextStyle: .largeTitle)
|
||||
uiView.font = fontMetrics.scaledFont(for: font)
|
||||
|
||||
// We don't want the text field to become first responder every time SwiftUI refreshes the view.
|
||||
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
|
||||
uiView.becomeFirstResponder()
|
||||
context.coordinator.didBecomeFirstResponder = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user