Post

Replies

Boosts

Views

Activity

Reply to Expand UITextView upwards from keyboard
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!
Dec ’19
Reply to Place UITextField behind SKNode
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!
Feb ’20
Reply to know that skspritenode has completely moved over another skspritenode
What do you mean by "iterated"? If I understand your subject correctly... This can be used when node 1 is just partially within the boundary of the second node:if node1.intersects(node2) { }If you want to know, whether your first node is entirely within the boundaries of the second node, this should work:// Node 1 intersects HEIGHT of Node2 if ( node1BottomY <= node2TopY && node1TopY >= node2BottomY ) || ( node1TopY >= node2BottomY && node1BottomY <= node2TopY ) { intersectsHeight = true } // Node 1 intersects WIDTH of Node 2 if ( node1LeftX <=node2RightX && node1RightX >= node2LeftX ) || ( node1RightX >= node2LeftX && node1LeftX <= node2RightX ) { intersectsWidth = true } // If Node1 intersects both height and width of Node 2, it is completely withoin its boundaries: if intersectsHeight == true && intersectsWidth == true { }This is how you may check if half of the first node intesects the second node:if node2.contains(CGPoint(x: node1.frame.midX, y: node1.frame.midY))
Feb ’20
Reply to Authenticate game Center
You can authenticate by using a method along the following lines (in the GameCenterHelp that will be a singleton): func authenticatePlayer() {         GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in             &#9;&#9;&#9;&#9;// In your delegate, implement method `didChangeAuthStatus`, for example to enable a Game Center button &#9;&#9;&#9;&#9;self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated) &#9;&#9;&#9;&#9;// This is called if the local player gets authenticated. Nothing happens, GKLocalPlayer gets registered &#9;&#9;&#9;&#9;if GKLocalPlayer.local.isAuthenticated {                 GKLocalPlayer.local.register(self)         }          // This is called, when a player opens your app and he|she is not authenticated. &#9;&#9;&#9;&#9; // It opens a viewController with sign-in info &#9;&#9;&#9;&#9;else if let vc = gcAuthVC {                 self.delegate?.presentGameCenterAuth(viewController: vc)         } &#9;&#9;&#9;&#9;// Handing an error while authenticating &#9;&#9;&#9;&#9;else {                 print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<") &#9;&#9;&#9;&#9;} } So, in your GameScene class you may have something like: override func didMove(to view: SKView) { &#9;&#9; GameCenterHelper.sharedInstance.delegate = self      GameCenterManager.sharedInstance.authenticatePlayer()  } @objc func didChangeAuthStatus(isAuthenticated: Bool) {        ... For example, stop spinning activity indicator      &#9;if indicator != nil {             indicator!.stop()             indicator!.removeFromSuperview()             indicator = nil         }         ... Or enable the *PLAY ON GAMECENTER* button         if GKLocalPlayer.local.isAuthenticated {             btnPlayGameCenter.setButtonLabel(title: btnPlayGameCenterTitle(), font: "Noteworthy-Bold", fontSize: 40) } &#9;&#9; &#9;&#9;/** Present the view controller with the Sign-in info */ &#9;&#9;func presentGameCenterAuth(viewController: UIViewController?) {         guard let vc = viewController else {return}         self.view!.window?.rootViewController?.present(vc, animated: true)  }
Dec ’20