how to give action to UIImageView using the objective-c [duplicate] - ios

I want to call my button click event while touching the uiimageview named as(image1).Imageview placed in uiview(view1).
This is my code:
- (IBAction)buttonClicked:(id)sender
{
myTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(alphabutt:) userInfo:nil repeats:NO];
}
-(IBAction)alphabutt:(id)sender
{
NSLog(#"alphabutt!");
if(i==1)
{
NSLog(#"i==1");
[image1 setImage:[UIImage imageNamed:#"appleimg.jpg"]];
[view1 addSubview:image1];
transition1 = [CATransition animation];
transition1.duration = 0.75;
transition1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition1.type=kCATransitionReveal;
transition1.subtype=kCATransitionFromRight;
transitioning = YES;
transition1.delegate = self;
[image1.layer addAnimation:transition1 forKey:nil];
}
if(i==2)
{
NSLog(#"i==2");
[image1 setImage:[UIImage imageNamed:#"boatimg.jpg"]];
[view1 addSubview:image1];
transition2 = [CATransition animation];
transition2.duration = 0.75;
transition2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition2.type=kCATransitionFade;
transition2.subtype=kCATransitionFromRight;
transitioning = YES;
transition2.delegate = self;
[image1.layer addAnimation:transition2 forKey:nil];
i=0;
}
i++;
}
The above is my code while clicking the button the buttonclicked event is called.Inside buttonclick event the timer is working to call the alphabutt(Button click event)with the time interval of 2.0.alphabutt is called with every 2.0.I want to do this animation when i'm touch the uiimageview(image1) then only it calls the button click event (alphabutt).
how can I write the touch event for imageview...
Please explain briefly with some code to perform uiimageview touch event...

you can use UITapGestureRecognizer added to the UIImageView via addGestureRecognizer
snippets:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(bannerTapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[iv addGestureRecognizer:singleTap];
[iv setUserInteractionEnabled:YES];
and
- (void)bannerTapped:(UIGestureRecognizer *)gestureRecognizer {
NSLog(#"%#", [gestureRecognizer view]);
}

Make your image view user interaction enabled in the xib (or through the code if you are adding it programmatically) and use the UIResponder methods touchesBegan, touchesMoved, touchesEnded etc to detect the touch on the image view:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch view] == yourImageView)
{
//add your code for image touch here
}
}

Here I show you two possibilities for achieving that in Swift:
First Possibility
import UIKit
class ViewController: UIViewController {
#IBOutlet var myUIImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// You can also manually set it through IB
// selecting the UIImageView in the storyboard
// and checking "User Interaction Enabled" checkbox
// in the Attributes Inspector panel.
self.myUIImageView.userInteractionEnabled = true
}
// You can choose to use one of the UIResponder methods:
// touchesBegan, touchesMoved, touchesEnded etc, in order to detect the touch
// on the UIImageView.
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch? = touches.first
if touch?.view == myUIImageView {
println("myUIImageView has been tapped by the user.")
}
super.touchesEnded(touches, withEvent: event)
}
}
Second Possibility
import UIKit
class ViewController: UIViewController {
#IBOutlet var myUIImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(target: self, action: "myUIImageViewTapped:")
singleTap.numberOfTapsRequired = 1 // Initialized to 1 by default
singleTap.numberOfTouchesRequired = 1 // Initialized to 1 by default
self.myUIImageView.addGestureRecognizer(singleTap)
self.myUIImageView.userInteractionEnabled = true
}
func myUIImageViewTapped(recognizer: UITapGestureRecognizer) {
if(recognizer.state == UIGestureRecognizerState.Ended){
println("myUIImageView has been tapped by the user.")
}
}
}

You can also drag and drop a UIButton object over the UIImageView. Then in the storyboard editor, just make the UIButton of Custom type, rendering the UIButton invisible. Then handle the click event just like you would for any button.

Related

How do I prevent taps on a subview from triggering a UITapGestureRecognizer on a parent view?

I added a tap recognizer to a view:
UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector( onTap )];
[view addGestureRecognizer: tgr];
The problem is that taps on subviews of view trigger onTap. How do I prevent that?
Suppose your parentView has a subView. You implement the following UIGestureRecognizerDelegate method, if the touch is inside the bounds of subView, you return no.
tgr.delegate = self;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint locationInView = [touch locationInView:self.parentView];
if (CGRectContainsPoint(self.subView.frame, locationInView) ) {
return NO;
} else {
return YES;
}
}
Add subview to the background of the view, and attach tap gesture recogniser to the subview:
UIView* subview = [[UIView alloc] initWithFrame:view.bounds];
subview.backgroundColor = [UIColor clearColor];//or view.backgroundColor
[view addSubview:subview];
[view sendSubviewToBack:subview];
[subview addGestureRecognizer:tapRecognizer];
Swift 4.2 answer for an AlertView
Add the gesture recogniser and set the delegate:
let backgroundViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismiss))
backgroundViewTapGesture.delegate = self
self.backgroundView.addGestureRecognizer(backgroundViewTapGesture)
self.backgroundViewTapGesture = backgroundViewTapGesture
Then add the extension to handle the tap
extension AlertView: UIGestureRecognizerDelegate {
// Only handle this for the background tap gesture
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
guard gestureRecognizer == backgroundViewTapGesture, let backgroundView = gestureRecognizer.view, let alertView = self.alertContentView else {
return true
}
let touchLocation = touch.location(in: backgroundView)
return !alertView.frame.contains(touchLocation)
}
}
In Swift:
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let locationInView = touch.location(in: mainView)
if debugOptionsView.isHidden {
return true
}
return !debugOptionsView.frame.contains(locationInView)
}

Change label color with UITapGestureRecognizer

I have a label with UITapGestureRecognizer and longgestureRecognizer:
let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("labelPressed:"))
let longgestureRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longLabelPressed:"))
label.addGestureRecognizer(gestureRecognizer)
label.addGestureRecognizer(longgestureRecognizer)
I want to change color like in UIButton, when it pressed:
func longLabelPressed(recognizer:UILongPressGestureRecognizer){
if let label = recognizer.view as? UILabel {
if recognizer.state == .Began {
label.textColor = UIColor.redColor()
}
if recognizer.state == .Ended {
label.textColor = UIColor.blackColor()
}
}
}
But how to detect tap end event ?
func labelPressed(recognizer:UITapGestureRecognizer) {
if let label = recognizer.view as? UILabel {
}
}
My goal is create label like UIButton with touch events.
UserInteractionEnabled for label is by default false . so if you are using its label outlet then enable it from (XIB/ storyboard)
Now to make label same like button using UILongPressGestureRecognizer
and then you event called successfully but you write label color change code in UILongPressGestureRecognizer so its take some time(default time) to detect touch event. recognizer.state == .Began so change minimum time for long pressGesture
longgestureRecognizer.minimumPressDuration = 0.001
using that recognizer.state == .Began will call quickly .
Make a new subclass of UILabel and implement this :
Objective-C
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.textColor = [UIColor blueColor];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.textColor = [UIColor whiteColor];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.textColor = [UIColor blackColor];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.textColor = [UIColor redColor];
}
Swift 4
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textColor = UIColor.blue
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
textColor = UIColor.white
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
textColor = UIColor.black
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
textColor = UIColor.red
}
Don't forget to set :
Objective-C
label.userInteractionEnabled = YES;
Swift 4
label.isUserInteractionEnabled = true
Add the custom class to your label in your xib and enjoy :)
Reference : UILabel + touchDown
Like the docs mentoined you should enable unser interaction.
let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("labelPressed:"))
let longgestureRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longLabelPressed:"))
label.userInteractionEnabled = YES;
label.addGestureRecognizer(gestureRecognizer)
label.addGestureRecognizer(longgestureRecognizer)
Two things:
You should set userInteractionEnabled property on the label to true (as someone mentioned earlier)
Using UITapGestureRecognizer will only give you information when the gesture is finished. If you want to know when it begins I would suggest using UILongPressGestureRecognizer and setting its minimumPressDuration property to 0.

Remove view when tapped outside

I have a UIView, that I have appear when a button is tapped, I am using it as a custom alert view essentially. Now when the user taps outside the custom UIView that I added to the main view, I want to hide the cusomt view, I can easily do this with customView.hidden = YES; but how can I check for the tap outside the view?
Thanks for the help
There are 2 approaches
First approach
You can set a tag for your custom view:
customview.tag=99;
An then in your viewcontroller, use the touchesBegan:withEvent: delegate
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if(touch.view.tag!=99){
customview.hidden=YES;
}
}
Second approach
It's more likely that every time you want to popup a custom view, there's an overlay behind it, which will fill your screen (e.g. a black view with alpha ~0.4). In these cases, you can add an UITapGestureRecognizer to it, and add it to your view every time you want your custom view to show up. Here's an example:
UIView *overlay;
-(void)addOverlay{
overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height)];
[overlay setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]];
UITapGestureRecognizer *overlayTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(onOverlayTapped)];
[overlay addGestureRecognizer:overlayTap];
[self.view addSubview:overlay];
}
- (void)onOverlayTapped
{
NSLog(#"Overlay tapped");
//Animate the hide effect, you can also simply use customview.hidden=YES;
[UIView animateWithDuration:0.2f animations:^{
overlay.alpha=0;
customview.alpha=0;
}completion:^(BOOL finished) {
[overlay removeFromSuperview];
}];
}
Like in the answer of FlySoFast, I tried first approach and it worked I just shared to swift version of it. You can tag it of your custom view and the check the that view touched or not so we achieved our solution I guess.In the below I assign tag value of my custom view to 900.
customview.tag = 900
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
if touch.view?.tag != 900 {
resetMenu()
}
}
I hope this answer will help to you
When you presenting custom alert view, add that custom alert view in to another full screen view, make that view clear by setting its backgroundColor clear. Add full screen view in main view, and add tapGesture in fullScreen invisible view, when ever it gets tap remove this view.
But if you will do this it will dismiss view even when you touch custom alert view for that you need to set delegate of tapGesture and implement this method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isDescendantOfView:self.customAlertView])
{
return NO;
}
return YES;
}
with using function pointInside in Swift:
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
if let view = customView {
//if UIView is open open
let newPoint = self.convertPoint(point, toView: view)
let pointIsInsideGenius = view.pointInside(newPoint, withEvent: event)
// tapping inside of UIView
if pointIsInsideGenius {
return true
} else {
// if tapped outside then remove UIView
view.removeFromSuperview()
view = nil
}
}
}
return false
}
You can use this library: https://github.com/huynguyencong/EzPopup
Init a PopUpController the view that you want to dismiss it when tap outside
let popup = PopupViewController(contentView: viewNeedToRemoveWhenTapOutside, position: .bottomLeft(position))
present(popup, animated: true, completion: nil)
You can make this by the way. The main tricks are a button that wraps the full screen behind your custom view. When you click on the button you simply dismiss your custom view. Here is the complete code.
Here is the complete custom uiview class
import Foundation
import UIKit
class CustomAlartView: UIView {
static let instance = CustomAlartView()
#IBOutlet var parentView: UIView!
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var userInput: UITextField!
override init(frame: CGRect) {
super.init(frame: frame)
Bundle.main.loadNibNamed("CustomAlartView", owner: self, options: nil)
setupView()
}
//initWithCode to init view from xib or storyboard
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// setupView()
}
#IBAction func tappedCancel(_ sender: Any) {
parentView.removeFromSuperview()
}
#IBAction func tappedOk(_ sender: Any) {
if userInput.text == "" {
print("\(userInput.text)")
}
else{
parentView.removeFromSuperview()
}
}
#IBAction func tappedOutside(_ sender: Any) {
print("click outside")
parentView.removeFromSuperview()
}
//common func to init our view
private func setupView() {
parentView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
parentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
mainView.layer.shadowColor = UIColor.gray.cgColor
mainView.layer.shadowOpacity = 1
mainView.layer.shadowOffset = CGSize(width: 10, height: 10)
mainView.layer.shadowRadius = 10
mainView.layer.cornerRadius = 15
mainView.layer.masksToBounds = true
}
enum alartType {
case success
case failed
}
func showAlart() {
UIApplication.shared.keyWindow?.addSubview(parentView)
}
}

iOS7 Sprite Kit how to get long press or other gestures on SKSpriteNode?

I'm building a sprite kit based game, and the lack of "right click" is really making it hard to convey some important information to my users. As a solution, I'm thinking about gestures like long press, two finger tap, etc.
How can one implement gestures on a SKSpriteNode?
Here's what I'm currently using to get a button-like behavior when an SKSpriteNode is touched.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self selectSkill:YES];
}
Before UIGestureRecognizer, you kept state variables that tracked where touches where and when they started. Here's a swift solution where buttonTouched: is a method that checks whether the UITouch was on the button you're checking.
var touchStarted: NSTimeInterval?
let longTapTime: NSTimeInterval = 0.5
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as? UITouch {
if buttonTouched(touch) {
touchStarted = touch.timestamp
}
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as? UITouch {
if buttonTouched(touch) && touchStarted != nil {
let timeEnded = touch.timestamp
if timeEnded - touchStarted! >= longTapTime {
handleLongTap()
} else {
handleShortTap()
}
}
}
touchStarted = nil
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
touchStarted = nil
}
Here is a good component that can help https://github.com/buddingmonkey/SpriteKit-Components
There is no easy way to do it, but one way I can think of would be to add a sub SKView to your SKScene and place an UIImageView as the only thing inside that SKView. Then you can add a gesture recognizer like normal to the SKView.
Here's an example of what I'm talking about:
UIImageView *button = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ButtonSprite"]];
SKView *spriteNodeButtonView = [[SKView alloc] initWithFrame:CGRectMake(100, 100, button.frame.size.width, button.frame.size.height)];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(someMethod:)];
[spriteNodeButtonView addGestureRecognizer:tap];
[spriteNodeButtonView addSubview:button];
You can put the SKView wherever you want and use any of the gesture recognizers on an SKView: UITapGestureRecognizer, UILongPressGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UIPanGestureRecognizer, or UIScreenEdgePanGestureRecognizer.
Then for your method implementation do something like this:
-(void)someMethod:(UITapGestureRecognizer *)recognizer {
CGPoint touchLoc = [recognizer locationInView:self.view];
NSLog(#"You tapped the button at - x: %f y: %f", touchLoc.x, touchLoc.y);
}

How to dismiss keyboard when user tap other area outside textfield?

today I tried to run my code on my iPod (iOS 6.1.3) and I found something interesting here...
first, when I tap on textfield the keyboard shows up but it won't hide when I tap somewhere else outside textfield.
so I decided to Googling and found this solution :
_fieldEmail.delegate = self;
_fieldEmail.returnKeyType = UIReturnKeyDone;
_fieldPassword.delegate = self;
_fieldPassword.returnKeyType = UIReturnKeyDone;
_fieldRegisterName.delegate = self;
_fieldRegisterName.returnKeyType = UIReturnKeyDone;
_fieldRegisterEmail.delegate = self;
_fieldRegisterEmail.returnKeyType = UIReturnKeyDone;
_fieldRegisterPassword.delegate = self;
_fieldRegisterPassword.returnKeyType = UIReturnKeyDone;
it works... it gives a 'DONE' button on the bottom of keyboard and now the keyboard can be hidden by pressing it.
but I have 2 problems here :
the keyboard only hide when 'DONE' button is tapped. not by tapping other area outside text field. I don't know if this normal on iOS world, but usually I see lot of apps don't act like this.
is there any way to loop this process so I don't have manually add that delegate one by one of all textfield that I have? how to do that?
that's all I need to know
The below code will work on all the components in the UIView for all the UITextField
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UIView * txt in self.view.subviews){
if ([txt isKindOfClass:[UITextField class]] && [txt isFirstResponder]) {
[txt resignFirstResponder];
}
}
}
OR
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
Simply add an UITapGestureRecogniser to your view that will lead to calling resignFirstResponder
In viewDidLoad :
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(hideKeyBoard)];
[self.view addGestureRecognizer:tapGesture];
And then :
-(void)hideKeyBoard {
[yourTextField resignFirstResponder];
}
2.You could subclass UITextField but unless you have 1000 textFields it is ok to do like you currently do.
This is regards to Swift programming for Xcode 6.0.1
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let tapRecognizer = UITapGestureRecognizer(target: self, action: "handleSingleTap:")
tapRecognizer.numberOfTapsRequired = 1
self.view.addGestureRecognizer(tapRecognizer)
}
func handleSingleTap(recognizer: UITapGestureRecognizer) {
self.view.endEditing(true)
}
Use Either
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];
and code of method
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
[self.TextFiledName resignFirstResponder];
}
OR _ And The best Other option is
Just add
[self.view endEditing:YES];
And key board will hide when you tapped anywhere from view:)
Dismissing the keyboard
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
[super touchesBegan:touches withEvent:event];
}
Simple,
Use IQKeyboardManager and put this line of code in AppDelegate.m
[[IQKeyboardManager sharedManager] setShouldResignOnTouchOutside:YES];
What I usually do is call
[field resignFirstResponder];
from an invisible button over the view. I'm sure theres a nicer way to do it. It's been a while since I've done this in an app.
Here's how I do it:
In the myView's .h file:
#property (strong) UITextField * savedTextField;
In the myView's .m file:
#implementation myView
#synthesize savedTextField;
In the myView's init routine:
[self setSavedTextField: nil];
In the myView's textField delegate area I save the id of whichever textField is currently activating:
- (BOOL) textFieldShouldBeginEditing: (UITextField *) textField
{
[self setSavedTextField: textField];
.
.
.
return( YES );
}
And in the myView's routine that routes all the traffic for the other controls when they are accessed, I have code that looks to see if a textField was active and, if one was, it calls on it to resign its FirstResponder status and then drops a nil into the savedTextField property:
- (void) handleCtrlEvents: (UIControl *) aCtrl
{
if ( [self savedTextField] != nil )
{
[[self savedTextField] resignFirstResponder];
[self setSavedTextField: nil];
}
.
.
.
}
This works cleanly for me.
I ran into the exact same problem. Usually what you want is, that wherever you click inside your App (which is displayed in your main / current UIView) but not on the keyboard to close it. After searching the web for a smart solution and testing several, I think it is the best to extend/subclass/implement the UIGestureRecognizerDelegate
Since many controls such as UITableView etc. can respond to gestures (select, scrolling etc.) and if you simply add a UITapGestureRecognizer to the whole (main-)ViewController's view to close the keyboard, the user experience is not the best, since the user needs to tap twice if he didn't intend to close the keyboard but e.g. select a row from a UITableView inside the App's current "main" View.
Since I am quite new to the whole iOS and swift thing and swift code examples are rare, here's my full keyboard control snipped:
class ViewController: UIViewController, UIGestureRecognizerDelegate {
override func viewDidLoad(){
self.initializeCloseKeyboardTap()
}
func initializeCloseKeyboardTap() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboardOpen:", name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "onKeyboardClose:", name: UIKeyboardDidHideNotification, object: nil)
let tapRecognizer = UITapGestureRecognizer(target: self, action: "handleOnTapAnywhereButKeyboard:")
tapRecognizer.delegate = self //delegate event notifications to this class
self.view.addGestureRecognizer(tapRecognizer)
}
func onKeyboardClose(notification: NSNotification) {
println("keyboardClosed")
}
func onKeyboardOpen(notification: NSNotification) {
println("keyboardOpen")
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
self.view.endEditing(true)
return false
}
you can nest it inside the ViewController and call initiallizeCloseKeyboardTa() in viewDidLoad implementation... It also implements a norfication observer to receive events as soon as the keyboard (finished to be) opened or closed via NSNotificationCenter UIKeyboardDidShowNotification and UIKeyboardDidHideNotification
Hope that save's other people some time :-)
|*| Dismissing the UITextField’s Keyboard : override the method touchesBegan:withEvent: for the ViewController
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
|OR|
override func viewDidLoad()
{
super.viewDidLoad()
// For tapping outside text box
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(DismisKeyPadFnc)))
}
// For tapping outside text box
func DismisKeyPadFnc()
{
view.endEditing(true)
}
|*| Dismissing the UITextField’s Keyboard on induvidual textbox :
class NamVcc: UIViewController, UITextFieldDelegate
{
#IBOutlet var NamTxtBoxVid: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// For hitting return key
NamTxtBoxVid.delegate = self
// For tapping outside text box
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(DismisKeyPadFnc)))
}
/* For hitting return key */
func textFieldShouldReturn(NamTxtBoxPsgVid: UITextField) -> Bool
{
NamTxtBoxPsgVid.resignFirstResponder()
return true
}
/* For tapping outside text box */
func DismisKeyPadFnc()
{
view.endEditing(true)
}
}
|*| Implementing Next button Click :
1) You will be needing to set the tags in the incremental sequence of the textfields in xib/Storyboard or in code.
2) Set the delegate for each of the textfields.
3) Then paste the following code in your view controller to have the desired effect:
func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
{
let NxtTxtBoxTagVal : Int = TxtBoxPsgVar.tag + 1
let NxtTxtBoxVal: UIResponder? = TxtBoxPsgVar.superview?.superview?.viewWithTag(NxtTxtBoxTagVal)
if let TxtBoxVal = NxtTxtBoxVal
{
// Found next responder, so set it.
TxtBoxVal.becomeFirstResponder()
}
else
{
// Not found, so remove keyboard.
TxtBoxPsgVar.resignFirstResponder()
}
return true
}
I prefer IQKeyboardManager. You can simply handle keyboard in any state. To active IQKeyboard just add one line in AppDelegate and to dismiss keyboard on outside touch add code as below,
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
return true
}
I think
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
is convenient but not the best solution.
and the TapGestureRecongnizer is better but hard to use,you have to set delegates and add and remove the Recongnizer.
So I wrote a simple subclass which can be easily used:
class TapHideTextField: UITextField {
override func awakeFromNib() {
super.awakeFromNib()
tapGr = UITapGestureRecognizer(target: self, action:"tap")
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didBeginEditing", name:UITextFieldTextDidBeginEditingNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didEndEditing", name:UITextFieldTextDidEndEditingNotification, object: nil)
}
deinit{
NSNotificationCenter.defaultCenter().removeObserver(self)
}
var tapGr:UITapGestureRecognizer!
func tap(){
self.endEditing(true)
}
func didBeginEditing(){
self.superview!.addGestureRecognizer(tapGr)
}
func didEndEditing(){
self.superview!.removeGestureRecognizer(tapGr)
}
}
you should concern about the superview and the cancelTouchesInView property.
or in GitHub:https://github.com/lilidan/TapHideText/blob/master/TapHideTextField.swift
If you're using scroll view (or table view) controller, add these lines there:
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
view.endEditing(true)
}
-(void) textFieldDidBeginEditing: (UITextField *) textField{
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(DismissKeyboard:)]];
}
-(void) DismissKeyboard:(UITapGestureRecognizer *) sender{
[self.view endEditing:YES];
[self.view removeGestureRecognizer:sender];
}

Resources