At the end, I abandoned this approach. Takes so much memory to the extent that my daughter's old iPad would crash with an out of memory warning...
Post
Replies
Boosts
Views
Activity
iniitamo.Thank you for the response.Is it possible to use SKLabelNode to enter text a-la UITextField?I have read a lot of negative stuff about SKShapeNodes. Thought, many issues had already been solved. I am trying to use rectangulars with rounded corners. How would I do that with SKSpriteNode? Just create a rounded png image and use it as a node texture? The main problem with this approach occurs when my node size changes, e.g. when the height is much smaller than width, the texture image gets disproprtionally squeezed/stretched. Something I do not have with SKShapeNode.Cheers!
Good observation, Claude31.Replaced with:textView.frame = CGRect(origin: newOrigin, size: CGSize(width: newFrame.width, height: newFrame.height))If you notice any other issues, this would be greatly appreciated!Thanks a lot!Igor
Hello.I think, I know why I had issues with my code. Looks like the textViewDidChange method was also influenced by didChangeSize(oldSize:) method which was also called every time I typed in a character and which I needed to handle rotation of my device.Anyways, I think I have come up with a solution how to handle expanding a textView which also gets adjusted with a rotation. Here is the code for the peer review.import UIKit
class ViewController: UIViewController, UITextViewDelegate
{
var textView: UITextView!
var btn: UIButton!
var btnSend: UIButton!
var keyboardHeight : CGFloat = 0
var isKeyboardShown = false
var textViewHeight : CGFloat = 0
var textView_inset : CGFloat = 10
var textView_insetBottom : CGFloat = 5
let btnSendWidth : CGFloat = 50
let btnSendHeight : CGFloat = 50
override func viewDidLoad()
{
super.viewDidLoad()
textViewHeight = 35
textView = UITextView(frame: CGRect(x: textView_inset+self.view.safeAreaInsets.left,
y: self.view!.bounds.height,
width: self.view.frame.width-textView_inset*3-self.view.safeAreaInsets.left-self.view.safeAreaInsets.right-btnSendWidth,
height: textViewHeight))
textView.textAlignment = NSTextAlignment.justified
textView.backgroundColor = UIColor.lightGray
// Use RGB colour
textView.backgroundColor = UIColor(red: 39/255, green: 53/255, blue: 182/255, alpha: 1)
// Update UITextView font size and colour
textView.font = UIFont(name: "Verdana", size: 17)
textView.textColor = UIColor.white
// Make UITextView web links clickable
textView.isSelectable = true
textView.isEditable = true
textView.dataDetectorTypes = UIDataDetectorTypes.link
textView.isScrollEnabled = false
// Make UITextView corners rounded
textView.layer.cornerRadius = 10
// Enable auto-correction and Spellcheck
textView.autocorrectionType = UITextAutocorrectionType.yes
textView.spellCheckingType = UITextSpellCheckingType.yes
// myTextView.autocapitalizationType = UITextAutocapitalizationType.None
self.view.addSubview(textView)
textView.delegate = self
registerForKeyboardNotifications()
btn = UIButton()
btn.setTitle("PRESS", for: .normal)
btn.setTitleColor(.red, for: .normal)
btn.frame = CGRect(x: 50, y: 150, width: 100, height: 50)
btn.addTarget(self, action: #selector(self.showTextView(sender:)), for: .touchUpInside)
self.view.addSubview(btn)
btnSend = UIButton()
btnSend.setTitle("SEND", for: .normal)
btnSend.setTitleColor(.white, for: .normal)
btnSend.backgroundColor = .red
btnSend.frame = CGRect(x: self.view.frame.width-self.view.safeAreaInsets.right-btnSendWidth-textView_inset,
y: self.view!.bounds.height,
width: btnSendWidth,
height: btnSendHeight)
btnSend.addTarget(self, action: #selector(self.sendMessage(sender:)), for: .touchUpInside)
self.view.addSubview(btnSend)
}
override func viewWillLayoutSubviews()
{
var textView_y : CGFloat = 0
var btnSend_y : CGFloat = 0
// Required to ensure that the TextView's height is changed dynamically!
if isKeyboardShown
{
textView_y = self.view!.bounds.height-keyboardHeight-textView.frame.height-textView_insetBottom
btnSend_y = self.view!.bounds.height-keyboardHeight-btnSendHeight-textView_insetBottom
}
else
{
textView_y = self.view!.bounds.height
btnSend_y = self.view!.bounds.height
}
textView.frame = CGRect(x: textView_inset+self.view.safeAreaInsets.left,
y: textView_y,
width: self.view.frame.width-textView_inset*3-self.view.safeAreaInsets.left-self.view.safeAreaInsets.right-btnSendWidth,
height: textViewHeight)
btnSend.frame = CGRect(x: self.view.frame.width-self.view.safeAreaInsets.right-self.btnSendWidth-textView_inset,
y: btnSend_y,
width: btnSendWidth,
height: btnSendHeight)
}
@objc func showTextView(sender: UIButton!)
{
textView.becomeFirstResponder()
}
@objc func sendMessage(sender: UIButton!)
{
print("------SEND MESSAGE-------")
}
func textViewDidChange(_ textView: UITextView)
{
let fixedWidth = textView.frame.size.width
// Changing height of the message UITextView
var newSize = textView.sizeThatFits(CGSize.init(width: fixedWidth, height: CGFloat(MAXFLOAT)))
// Limit the height to 100
if newSize.height > 100
{
newSize.height = 100
textView.isScrollEnabled = true
}
else
{
textView.isScrollEnabled = false
}
var newFrame = textView.frame
newFrame.size = CGSize.init(width: CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), height: newSize.height)
textViewHeight = newFrame.height
var newOrigin = textView.frame.origin
newOrigin.y -= (newSize.height - newFrame.size.height)
textView.frame = CGRect(origin: textView.frame.origin, size: CGSize(width: newFrame.width, height: newFrame.height))
}
func registerForKeyboardNotifications()
{
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver( self,
selector: #selector(ViewController.keyboardWillShow(_:)),
name: UIResponder.keyboardWillShowNotification,
object: nil )
notificationCenter.addObserver( self,
selector: #selector(ViewController.keyboardWillBeHidden(_:)),
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
func unregisterForKeyboardNotifications()
{
let notificationCenter = NotificationCenter.default
notificationCenter.removeObserver( self,
name: UIResponder.keyboardWillShowNotification,
object: nil)
notificationCenter.removeObserver( self,
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
@objc func keyboardWillShow(_ notification: Notification)
{
isKeyboardShown = true
// Reset the position of the textview to the bottom of the screen
textView.frame = CGRect(x: textView_inset+self.view.safeAreaInsets.left,
y: self.view!.bounds.height,
width: self.view.frame.width-textView_inset*3-self.view.safeAreaInsets.left-self.view.safeAreaInsets.right-btnSendWidth,
height: textViewHeight)
btnSend.frame = CGRect(x: self.view.frame.width-self.view.safeAreaInsets.right-btnSendWidth-textView_inset,
y: self.view!.bounds.height,
width: btnSendWidth,
height: btnSendHeight)
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
{
keyboardHeight = keyboardFrame.cgRectValue.height
// Place the TextView above the keyboard
self.textView.frame.origin.y -= (keyboardHeight+self.textView.frame.height+textView_insetBottom)
// Determine a new TextView height dynamically
let fixedWidth = textView.frame.size.width // Width never changes
var newSize = textView.sizeThatFits(CGSize.init(width: fixedWidth, height: CGFloat(MAXFLOAT))) // Height is based on the number of characters
// Limit the height to 100
if newSize.height > 100
{
newSize.height = 100
textView.isScrollEnabled = true
}
else
{
textView.isScrollEnabled = false
}
var newFrame = textView.frame // A new frame: Fixed width; Dynamically changed height
newFrame.size = CGSize.init(width: CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), height: newSize.height)
textViewHeight = newFrame.height // Assign the height value to the object property
textView.frame = CGRect(origin: textView.frame.origin, size: CGSize(width: newFrame.width, height: newFrame.height))
self.textView.layoutIfNeeded()
self.btnSend.frame.origin.y -= (keyboardHeight+self.btnSend.frame.height+textView_insetBottom)
btnSend.frame = CGRect(origin: btnSend.frame.origin, size: CGSize(width: btnSendWidth, height: btnSendHeight))
}
}
@objc func keyboardWillBeHidden(_ notification : NSNotification)
{
isKeyboardShown = false
if let _: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
{
//let newHeight: CGFloat
let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
keyboardHeight = 0
UIView.animate(withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: {
self.textView.frame.origin.y = self.view!.bounds.height
self.textView.layoutIfNeeded()
self.btnSend.frame.origin.y = self.view!.bounds.height
},
completion: nil)
}
}
func textViewDidBeginEditing(_ textView: UITextView)
{
textView.becomeFirstResponder()
let tapRecognizer = UITapGestureRecognizer(target: self,
action: #selector(tapDetected(_:)))
if self.view != nil {self.view!.addGestureRecognizer(tapRecognizer)}
}
func textViewDidEndEditing(_ textView: UITextView)
{
// Make the active field nil to hide the keyboard
//self.activeField = nil;
}
@objc func tapDetected(_ tapRecognizer: UITapGestureRecognizer)
{
textView?.resignFirstResponder()
if self.view != nil {self.view!.removeGestureRecognizer(tapRecognizer)}
}
}Thanks!
Thanks, Claude31, but nope. This does not address the issue. Exactly the same behavior. Cheers.
Thanks eskimo!NWConnection looks nice but I need to come up with something quick at the moment.I tried your second approach extending OutputStream, but, as you expected, get error "Ambiguous use of 'write'". Unfortunately, attempts to fix it are not successful yet.EDIT: Hm, copying and pasting the code does not work, but typing it in does. Weird!!Thank you so much for your help, eskimo!