I'm running this code within a ViewController class that contains UIViewController and SettingsViewDelegate. The View Controller scene contains a text view that has a scroll bar.
#IBOutlet weak var tvEditor: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Hide keyboard via swipeDownGestureRecognizer.
let swipeGesture: UISwipeGestureRecognizer = UISwipeGestureRecognizer (target: self, action: "hideKeyboard")
swipeGesture.cancelsTouchesInView = false
UISwipeGestureRecognizerDirection.Down
}
func hideKeyboard() {
tvEditor.resignFirstResponder()
}
When I run my project in the iOS Simulator/device, the keyboard does not respond to a downward swipe. I change the orientation of my device to landscape, and then back to portrait, which is when the keyboard disappears. Can someone please tell me where I'm going wrong?
First, Please add swipeGesture to your viewcontroller.
And...
func hideKeyboard() {
self.view.endEditing(true)
}
It'll works fine for your project.
Hope it'll help you.
Related
i used default keyboard and custom keyboard
if textview touch event when custom keyboard is showing, change to default keyboard
class ReplyPage: UIViewController ,UITextViewDelegate,EmojiKeyboardDelegate,UIGestureRecognizerDelegate{
#IBOutlet weak var replyArea: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
replyArea.delegate=self
emojiView.delegate = self
replyPage = self
let tapTerm = UITapGestureRecognizer(target: self, action: #selector(textViewTouch))
tapTerm.delegate = self
replyArea.addGestureRecognizer(tapTerm)
more code...
}
#objc func textViewTouch(){
if isEmoji{
replyArea.inputView = nil
replyArea.reloadInputViews()
isEmoji = false
emojiButton.setImage(UIImage(named:"emoji"), for: UIControlState.normal)
}else{
replyArea.reloadInputViews()
replyArea.becomeFirstResponder()
}
}
}
this code is worked
but can't move cursor in textview
default tab is move cursor
but UITapGesture override this so can't work
how to use Both default tab and UITapGesture
Can i Listen Textview Touch without UITapGesture?
can't textViewDidBeginEditing()
TextView Tap do not call textViewDidBeginEditing after first open custom keyboard.
because First Custom Keyboard Open already call textViewDidBeginEditing
Please add protocol TextViewDelegate in your viewController .
And add
self.replyArea.delegate = self
I have a viewController EditMessage which has two UITextFields (UITextView) which use the keyboard and they work great. This part is basic standard stuff. When the keyboard is displayed, I register a tag gesture for the entire view, so that if the user clicks anywhere else, I dismiss the keyboard:
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self,
action: #selector(dismissKeyboard)))
In dismissKeyboard, this all works fine:
#objc func dismissKeyboard(sender: Any) {
self.view.endEditing(true)
}
However, I have a menu button(thumbnail image) implemented as a child view controller (UIViewController) on the same EditMessage view, which hijacks the screen via UIApplication.shared.keyWindow() to display an overlay and menu on the bottom of the screen. Built using the model/code from Brian Voong's YouTube channel to replicate a YouTube style slide in menu from the bottom. However, the keyboard is in the way. Since the child is a different view controller "endEditing" doesn't work (or maybe I am referencing the wrong view?).
class ButtonPickerController : UIViewController,
UIGestureRecognizerDelegate, UINavigationControllerDelegate {
var maxSize = CGFloat(60)
let thumbnail: UIImageView = {
let thumbnail = UIImageView()
thumbnail.backgroundColor = UIColor.lightGray
return thumbnail
}()
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.buttonTapped(sender:)))
tap.delegate = self
view.addGestureRecognizer(tap)
//view.backgroundColor = .yellow
view.contentMode = .scaleAspectFit
thumbnail.frame = CGRect(x: 0, y: 0, width: self.maxSize, height: self.maxSize)
setupSubviews()
}
Can someone point me in a good direction? This is my first question so hopefully I am asking properly.
I figured it out in the end. Thank you for the help. In my child view controller I did used the following statement when the button was tapped:
#objc func buttonTapped(sender: UITapGestureRecognizer? = nil) {
self.parent!.view.endEditing(true)
}
First, its not a good way to present overlays as UIViewController.
But a solution good be, to give the second viewcontroller a reference to the first one before viewDidLoad is called. Do you use Segues ? So in prepare would be the right place. In the second viewcontroller you create a property for the first one and then use this property as target when you create the UITapGestureRecognizer.
Another way is using a protocol and delegation.
I see that there are a ton of these questions, and I think I'm following the accepted Swift 3 methodology, but I'm still getting nothing. I can see that the UITapGestureRecognizer has been attached. Here's my code:
let tileClick = UITapGestureRecognizer(target: self, action: #selector(GameManagement.initiateTileClick(_:)))
newView.addGestureRecognizer(tileClick)
newView.isUserInteractionEnabled = true
func initiateTileClick(_ sender: UITapGestureRecognizer) {
print("initiate tile click")
}
A few things to note:
1) The view that I'm attaching the gesture recognizer to has a two views and a label within it that each cover the entire frame of the view, however, I tried attaching the recognizer to the label, which is the topmost child item and it still doesn't work.
2) Both the function that adds the recognizer and the function that is called on the tap are contained in an NSObject file. I have a variety of interconnected functions that I want to be able to call from multiple view controllers and would prefer to keep this in the separate NSObject file. The process worked when I had everything in a UIViewController file and stopped working when I moved the functions to the NSObject file.
3) I've tried changing GameManagement.initiateTileClick to self.initiateTileClick or just initiateTileClick and none of those worked.
If you are putting your views inside NSObject subclass then these views will lose their behaviors for UIResponder which manages the UI interactions as I am not able to see how you are adding these views to interface.
As you said, it was working inside ViewController because it manages view hierarchy and responder chain.
The solution would be to write extensions to separate code or better abstractions.
extension YourViewController {
newView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(GameManagement.initiateTileClick(_:))))
newView.isUserInteractionEnabled = true
func initiateTileClick(_ sender: UITapGestureRecognizer) {
print("initiate tile click")
}
}
Giving you an idea how the tap recogniser works.
Firstly add Tap gesture recogniser to your view controller. You have to put the object here as shown in the image.
Then control+drag the tap gesture object to your view and select delegate.
Then control+drag the recogniser to your swift file and action will be like this.
#IBAction func tapGesture(_ sender: UITapGestureRecognizer) {
}
Now you must have seen when you give some input to a text field, the keyboard appears. But if you press outside the text field, that is anywhere in the view, the keyboard hides. This is because of the tap gesture recogniser.
Consider you have a text field such that if you click in that text field, keyboard is appeared. But when you tap outside the textfield, the keyboard must hide.
Add this delegate
UITextFieldDelegate
Implement this:
#IBOutlet var phoneText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
exampleText.delegate = self
}
#IBAction func tapGesture(_ sender: UITapGestureRecognizer) {
exampleText.endEditing(true)
}
Obviously,this function is instance method.
func initiateTileClick(_ sender: UITapGestureRecognizer) {
print("initiate tile click")
}
-
UITapGestureRecognizer(target: self, action:#selector(GameManagement.initiateTileClick(_:)))
but thisGameManagement.initiateTileClick(_:) looks like a class is calling a class method!The target should be the caller of method.self can't call GameManagement.initiateTileClick(_:).
I'm trying to add a UIView subview into a UIViewController, and that UIView has a UISwitch that I want the user to be able to toggle. Based on the state, a UITextField's value will toggle back and forth. Here is the subview (InitialView):
import UIKit
class InitialView: UIView {
// All UI elements.
var yourZipCodeSwitch: UISwitch = UISwitch(frame: CGRectMake(UIScreen.mainScreen().bounds.width/2 + 90, UIScreen.mainScreen().bounds.height/2-115, 0, 0))
override func didMoveToSuperview() {
self.backgroundColor = UIColor.whiteColor()
yourZipCodeSwitch.setOn(true, animated: true)
yourZipCodeSwitch.addTarget(ViewController(), action: "yourZipCodeSwitchPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.addSubview(yourZipCodeSwitch)
}
}
If I want to have it's target properly pointing at the below function, where should I either set the target or include this function? I tried:
Setting the target in the UIViewController instead of the UIView
Keeping the function in the UIView
Here's the function:
// Enable/disable "Current Location" feature for Your Location.
func yourZipCodeSwitchPressed(sender: AnyObject) {
if yourZipCodeSwitch.on
{
yourTemp = yourZipCode.text
yourZipCode.text = "Current Location"
yourZipCode.enabled = false
}
else
{
yourZipCode.text = yourTemp
yourZipCode.enabled = true
}
}
And here is where I'm loading it into the UIViewController:
// add initial view
var initView : InitialView = InitialView()
// Execute on view load
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.addSubview(initView)
}
Any help is much appreciated - thanks!
Yeah, the didMoveToSuperView() placement doesn't make much sense. So you're creating a random, totally unconnected ViewController instance to make the compiler happy but your project sad. Control code goes in controllers, view code goes in views.
You need in your real ViewController:
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(initView)
// Note 'self' is the UIViewController here, so we got the scoping right
initView.yourZipCodeSwitch.addTarget(self, action: "yourZipCodeSwitchPressed:", forControlEvents: .ValueChanged)
}
Also, .TouchUpInside is for UIButtons. Toggle switches are much more complicated, so their events are different. Touching up inside on a toggle switch's current setting can and should do nothing, whereas touchup inside on the opposite setting triggers the control event above. iOS does all the internal hit detection for you.
I have a webview inside view controller "A", is it possible to tap on web view and seaque to view controller "B"?
I have tried do following
#IBOutlet weak var mainWebView: UIWebView!
let tapUIWebView = UITapGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
tapUIWebView.addTarget(self, action: "webViewTapped")
mainWebView.userInteractionEnabled = true
mainWebView.addGestureRecognizer(tapUIWebView)
func webViewTapped(){
println("Tapped")
}
}
Thank you
1) Use a UITapGestureRecognizer, create the instance.
2) Attach it to the webview.
3) Implement the action method that handles the gesture.
4) SinceUIWebView already recognises a touch, you need to also take care that your recognizer does the job first. And you decide what to do with the touch.
5) If it suits you, you can disable handling the tap in the built-in recogniser completely.