Adding tool bar on top of the uikeyboard - objective-c

I have a toolbar and i would like to place it on top of the keyboard.
In the keyboardwillshow notification, i tried to add toolbar to the keyboard but no luck, i cant add
Please let me know
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
//Get a reference of the current view
keyboard = [tempWindow.subviews objectAtIndex:i];
//Check to see if the description of the view we have referenced is "UIKeyboard" if so then we found
//the keyboard view that we were looking for
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES)
{
[keyboard addSubview:myToolbar];
}
}

I think, you want an inputAccessoryView.
Basically, you create a view and set it as a text field's or text view's input accessory view.
[textField setInputAccessoryView:inputAccessoryView];

Here is code in case someone else need it.Found on stack overflow
- (void)viewDidLoad
{
[super viewDidLoad];
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.barStyle = UIBarStyleBlackTranslucent;
numberToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithTitle:#"Clear" style:UIBarButtonItemStyleBordered target:self action:#selector(clearNumberPad)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Apply" style:UIBarButtonItemStyleDone target:self action:#selector(doneWithNumberPad)],
nil];
[numberToolbar sizeToFit];
numberTextField.inputAccessoryView = numberToolbar;
}
-(void)clearNumberPad{
[numberTextField resignFirstResponder];
numberTextField.text = #"";
}
-(void)doneWithNumberPad{
NSString *numberFromTheKeyboard = numberTextField.text;
[numberTextField resignFirstResponder];
}

https://github.com/asefnoor/IQKeyboardManager
This is the best keyboard handler I have seen. Very excellent way to manage Text inputs.
Some of its features 1) ZERO LINE OF CODE
2) Works Automatically
3) No More UIScrollView
4) No More Subclasses
5) No More Manual Work
6) No More #imports

Simple solution for iOS 8 and 9.
Init your textField, searchBar etc.
customView - View that will stick at the top of the keyboard. DO not add it as a subview to hierarchy! Do not have to set any constraints or positions.
[searchBar setInputAccessoryView:self.customView];
- (BOOL)canBecomeFirstResponder{
return true;
}
- (UIView *)inputAccessoryView {
return self.customView;
}
If you need to let the customView at the bottom and not hide it after dismissing keyboard, add observer:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:self.view.window];
And method
- (void)keyboardDidHide:(NSNotification *)notification {
[self becomeFirstResponder];
}

if you want to add tool bar on the keyboard, you are right place. You can use BSKeyboard easly. Look at the implementation below;
in .h file
#import "BSKeyboardControls.h"
add delegates
#interface ViewController : UIViewController <BSKeyboardControlsDelegate>
now jump the .m file , go to viewDidLoad. We will add textfield which i want to add tollbar
self.keyboardControls = [[BSKeyboardControls alloc] initWithFields:#[PINTextField]];
[self.keyboardControls addDelegate:self];
we should add activeField just like below,
- (void)textFieldDidBeginEditing:(UIView *)textField {
[self.keyboardControls setActiveField:textField];
}
And last step is delegate metods implemantation,
- (void)keyboardControlsDonePressed:(BSKeyboardControls *)keyboardControls {
[super textFieldShouldReturn:self.keyboardControls.activeField];
}
That's it.
For more info and download the BSKeyboard files, you can move the below link BSKeyboard Githup Link

Related

Pop controller after back bar button is pressed

I have a UINavigationController ans a chain of 3 simple controllers. Each one has a button. When press a button a next controller is Pushed. ViewController1 -> ViewController2 -> ViewController3. When I push a back button on the 3rd view i want to move to the first view. Using of backBarButtonItem is obligatory. Here is the code for second controller:
#import "ViewController2.h"
static BOOL isBackButtonPressed;
#implementation ViewController2
- (void)viewDidLoad {
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"back from 3" style:UIBarButtonItemStyleBordered target:nil action:nil];
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
if (isBackButtonPressed) {
[self.navigationController popViewControllerAnimated:YES];
} else {
isBackButtonPressed = YES;
}
[super viewWillAppear:animated];
}
#end
But when I press back button on the third view I return to the second view instead of the first view. Could you help me to return to the first view pressing back button on the third view.
I tried suggestions from answers but they don't help.
Adding a selector to backBarButtonItem doesn't help because it is never called.
Adding a [self.navigationController popToRootViewControllerAnimated:YES] in viewWillDisappear methos also doesn't work. I don't know why. I think that the actual problem is how backBarButtonItem works.
Any other suggestions?
The behaviour I try to achieve exists in the calendar on iPhone. When you rotate iPhone to landscape you get to the weeek view. Then go to the event details, and rotate to the portrait. When you press back button you will get to a day view not to a week view, so a controller with weekview is skipped.
After countless number of tries my solution was simply not use backBarButtonItem! As whatever i do it always goes to previous viewController instead of calling its selector
Instead I use only leftBarButtonItem for navigation, as it guarantees calling my action.
Here an example
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 27, 22)];
[backButton setImage:[UIImage imageNamed:#"backbutton"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
This certainly calls backButtonPressed action.. This works both for IOS 6 and 7
No need to register a new selector for the back button, just do:
-(void)viewWillDisappear{
if ( [self.navigationController.viewControllers containsObject:self] )
//It means that the view controller was popped (back button pressed or whatever)
//so we'll just pop one more view controller
[self.navigationController popViewControllerAnimated:NO];
}
in your ViewController3 viewWillDisappear method
Try using this in your third view controller, this way you check if you have pressed the back button and directly pop to the root view controller which as you stated is your first view controller.
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
[super viewWillDisappear:animated];
}
I had the same problem as you beofre and fixed it like this:
You can capture the back button on the ViewController3 and before poping the view, remove ViewController2 from the navigation stack like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"back from 3" style:UIBarButtonItemStyleBordered target:self action:#selector(customBackPressed:)];
}
-(void)customBackPressed:(id)sender {
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: navigationController.viewControllers];
for (UIViewController *vc in viewControllers)
{
// If vc is ViewController2 type, remove it
}
navigationController.viewControllers = allViewControllers;
[self.navigationController popViewControllerAnimated:YES];
}
Because ViewController2 is not in the stack anymore, it will jump to ViewController1.
Also, if ViewController1 is the root view controller, you can just do:
[self.navigationController popToRootViewControllerAnimated:YES];

Reading touch events in a QLPreviewController

I've got a QuickLook view that I view some of my app's documents in. It works fine, but I'm having my share of trouble closing the view again. How do I create a touch event / gesture recognizer for which I can detect when the user wants to close the view?
I tried the following, but no events seem to trigger when I test it.
/------------------------ [ TouchPreviewController.h ]---------------------------
#import <Quicklook/Quicklook.h>
#interface TouchPreviewController : QLPreviewController
#end
//------------------------ [ TouchPreviewController.m ]---------------------------
#import "TouchPreviewController.h"
#implementation TouchPreviewController
- (id)init:(CGRect)aRect {
if (self = [super init]) {
// We set it here directly for convenience
// As by default for a UIImageView it is set to NO
UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleDoubleTap:)];
singleFingerDTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:singleFingerDTap];
[self.view setUserInteractionEnabled:YES];
[self.view setMultipleTouchEnabled:YES];
//[singleFingerDTap release];
}
return self;
}
- (IBAction)handleSingleDoubleTap:(UIGestureRecognizer *) sender {
CGPoint tapPoint = [sender locationInView:sender.view.superview];
[UIView beginAnimations:nil context:NULL];
sender.view.center = tapPoint;
[UIView commitAnimations];
NSLog(#"TouchPreviewController tap!" ) ;
}
// I also tried adding this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *) gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*) otherGestureRecognizer {
return YES;
}
#end
Edit: For clarification, this is how I instantiate the controller:
documents = [[NSArray alloc] initWithObjects: filename , nil ] ;
preview = [[TouchPreviewController alloc] init];
preview.dataSource = self;
preview.delegate = self;
//set the frame from the parent view
CGFloat w= backgroundViewHolder.frame.size.width;
CGFloat h= backgroundViewHolder.frame.size.height;
preview.view.frame = CGRectMake(0, 0,w, h);
//refresh the preview controller
[preview reloadData];
[[preview view] setNeedsLayout];
[[preview view] setNeedsDisplay];
[preview refreshCurrentPreviewItem];
//add it
[quickLookView addSubview:preview.view];
Also, I've defined the callback methods as this:
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return [documents count];
}
- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index
{
return [NSURL fileURLWithPath:[documents objectAtIndex:index]];
}
Edit2: One thing i noticed. If I try making swiping gestures, I get the following message. This could shed some light on what is wrong/missing?
Ignoring call to [UIPanGestureRecognizer setTranslation:inView:] since
gesture recognizer is not active.
I think your example code is incomplete. It isn't clear how you are instantiating the TouchPreviewController (storyboard, nib file or loadView.)
I have never used the class so I could be way out in left field.
If you've already instantiated a UITapGestureRecognizer in the parent viewController, it is absorbing the tap events and they aren't passed on to your TouchPreviewController.
I would implement the view hierarchy differently by attaching the UITapGestureRecognizer to the parent viewController and handle presentation and unloading of the QLPreviewController there.
I think you might not have to subclass QLPreviewController by instantiating the viewController from a nib file.
When your parent viewController's UITapGestureRecognizer got an event you would either push the QLPreviewController on the navigation stack or pop it off the navigation stack when done.
Hope this is of some help.

Need a really simple navigation controller with a table view inside a tab bar controller

I have an app with a tab bar controller (2 tabs). In one tab view controller, a button leads to an alert window. I want one button of the alert window to call a table view containing possible answers. I want that table view to have a done button and a title. I think that means a navigation controller has to be used. But most everything I can find on navigation controllers assumes a much more complicated situation. Here's part of the alert window logic:
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 2) {
AnswersViewController *aVC = [[AnswersViewController alloc] init];
[self presentViewController:aVC
animated:YES
completion:NULL];
}
}
And AnswersViewController looks like this:
#interface AnswersViewController : UITableViewController
#end
#implementation AnswersViewController
- (id) init
{
self = [super initWithStyle:UITableViewStylePlain];
return self;
}
- (id) initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self view] setBackgroundColor:[UIColor redColor]];
}
#end
This code all works as expected (an empty red UITableView appears).
Two questions I guess: 1. Is there a simple modification to what I have that can give me a done button and title in my table view? 2. If I have to go to a navigation controller (probably), how can I make a bare-bones navigation controller with a done button and title and embed the table view within it? Oh, and I want to do this programatically. And I think I prefer the done button and title to be in the navigation bar, no tool bar desired. Thanks!
To get what you are looking for, you do need to use a UINavigationController. That will provide the UINavigationBar where you can display a title and also buttons.
To implement this with a UINavigationController, you want to do smoothing like this (assuming you are using ARC, so you don't need to worry about memory management):
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 2) {
AnswersViewController *aVC = [[AnswersViewController alloc] init];
//Make our done button
//Target is this same class, tapping the button will call dismissAnswersViewController:
aVC.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissAnswersViewController:)];
//Set the title of the view controller
aVC.title = #"Answers";
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:aVC];
[self presentViewController:aNavigationController
animated:YES
completion:NULL];
}
}
Then you would also implement - (void)dismissAnswersViewController:(id)sender in the same class as the UIAlertView delegate method (based on the implementation I have here).
Hope this helps!

keyboard resigning reduces popover height

I have a strange issue on ios 4.3.I have one of my screen in landscape mode, a button click presents a popover.My popover has a search bar.Whenever keyboard appears it automatically pushes my popover bit up.When I resign the keyboard , popover reduces in height.This is the issue only on ios 4.3.While in rest of the ios , my popover doesnot reduces in height after keyboard dismissal.
None of the answers above worked for me. Apparently the keyboard scales the view and restores this scaling after the UIKeyboardDidHideNotification notification, making the presentPopoverFromRect method useless when applied handling this notification.
The way I solved it was by delaying the latter call as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
popup = nil; //my ViewController with UITextField
popover = nil; //my UIPopoverController
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(resizePopup:)
name:UIKeyboardDidHideNotification
object:nil];
}
- (void)doDelayedResize
{
[popover presentPopoverFromRect:myButton.bounds inView:myButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (void)resizePopup:(NSNotification*)note
{
[self performSelector:#selector(doDelayedResize) withObject:nil afterDelay:0.01];
}
I answered a very similar question here: UIPopoverController's view controller gets resized after keyboard disappears
The way I got around it was to observe the keyboard disappearing in the controller which controls the UIPopoverController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(presentSearchPopover) name:UIKeyboardDidHideNotification object:nil];
And then in -presentSearchPopover, present the UIPopoverController again (it's quite a seamless transition):
- (void)presentSearchPopover
{
self.searchPopoverController.popoverContentSize = CGSizeMake(width, height));
[self.searchPopoverController presentPopoverFromRect:someRect) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Don't forget to remove the observer in -dealloc or similar too:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[super dealloc];
}
I found an answer for this.It was a bug with the top arrow of popover.If I use the left arrow direction for popover, everything works fine.
I ran into this issue as well - specifically, the popover wasn't growing back to its pre-keyboard size after tapping away from the popover. (The popover would grow back if the user dismissed the keyboard directly or the popover's view controller resigned first responder).
Unfortunately, I have to use the top arrow direction for the popover due to the UI's layout. To solve this, the view controller responsible for the popover implements - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController. For example:
#interface MyController : UIViewController <UIPopoverControllerDelegate>
{
// ...
}
//...
#end
Set that controller as the popover's delegate:
MyPopoverViewController *popoverVC = [[MyPopoverViewController alloc] init];
UIPopoverController *myPopover = [[UIPopoverController alloc] initWithContentViewController:popoverVC];
myPopover.delegate = self;
// Hang on to popoverVC, myPopover or release them as desired...
In addition, my popover's view controller sets its contentSizeForViewInPopover property to the desired size:
#implementation MyPopoverViewController
- (id)init
{
self = [super init];
if (self)
{
// ...
self.contentSizeForViewInPopover = CGSizeMake(320, 400); // desired size
}
return self;
}
When the keyboard causes the popover to shrink, it affects the popover's popoverContentSize and not its view controller's contentSizeForViewInPopover. Therefore, reset popoverContentSize in MyController's delegate method:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
// Check if popoverController is valid, the popover you want, etc
popoverController.popoverContentSize = popoverController.contentViewController.contentSizeForViewInPopover;
}
Here is my solution:
1. Register for keyboard Notifications (UIKeyboardWillShowNotification, UIKeyboardWillHideNotification)
2. Create local variables:
CGSize _currentPopoverContentSize; //if you want to have custom size for popover
UIView *_currentPopoverSender; //to remember from wich view you will present popover
BOOL _keyboardIsShown; //enable in keyboardWillShow, and disable in keyboardWillHide
3. In my presentPopover method:
- (void)presentPopoverControllerWithSize:(CGSize)size fromView:(UIView *)sender{
MyController *controller = [[[MyController alloc] init] autorelease];
if (self.popover)
{
[_popover release];
_popover = nil;
}
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.popoverContentSize = size;
_popover.delegate = self;
//checking if keyboard is shown - if NO, than present popover, if YES - just `resignFirstResponder` for your _`activeTextField`(you can set it in -textFieldDidBeginEditing: and nullify in -textFieldDidEndEditing:)
if (!_keyboardIsShown)
{
[_popover presentPopoverFromRect:[sender bounds]
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
else
{
[_activeTextField resignFirstResponder];
}
_currentPopoverContentSize = size;
_currentPopoverSender = sender;
}
4. Than:
- (void)keyboardWillBeHidden:(NSNotification*)aNotification{
[UIView animateWithDuration:0.3
animations:^{
//do some stuff
[self.scrollView setContentSize:_scrollViewContentSize];
} completion:^(BOOL finished) {
if (_popover && _currentPopoverSender)
{
[_popover presentPopoverFromRect:[_currentPopoverSender bounds]
inView:_currentPopoverSender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}];
_keyboardIsShown = NO;
}
Hi After going through the forum, I don't think it's a bug after playing with frame sizes a lot, working on IOS 4,5,6,7 it's the same behaviour.
The solution for me was to:
1) Go into the designer by
2) Opening the XIB ViewController that is causing the problem (i.e. the PopOver one).
3) Click to select it's VIEW.
4) Uncheck "AutoResizeSubviews"
5) When loading the PopOver in code, make sure you do:
6) Your_Popup_Window.popoverContentSize = Your_ViewController.view.bounds.size;
I hope this helps.
Kind Regards
Heider Sati

TTTableViewController showMenu:forCell: example

I'm looking for an example of how to create an animated row menu like the Facebook & twitter apps for iphone have. I see the TTTableViewController has the showMenu:forCell: method, but I have not been able to find any examples of how to use it. Specifically in the context of a URL Navigator selector, but any example would be great.
Were you able to find an example on this.
I, too, was stuck with the same problem as you did. I couldn't find an example of using TTTableViewController showMenu:forCell: method a week ago. After messing with the code, I came up with this...
Create a subclass of TTTableViewCell and add a UIButton (as a trigger to launch the menu view) to the view.
#interface MyViewCell : TTTableViewCell {
}
- (id) initWithName:(NSString *)name target:(id)target action:(SEL)action {
// ...
UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeCustom];
moreButton.frame = CGRectMake(268.0f, 6.0f, 32.0f, 32.0f);
[moreButton setImage:TTIMAGE(#"bundle://Icon_More.png")
forState:UIControlStateNormal];
[moreButton addTarget:target action:action
forControlEvents:UIControlEventTouchUpInside];
[self moreButton];
// ...
}
Next, create a subclass of TTTableViewController and add custom TTTableViewCells to the data source.
#interface MyTableViewController : TTTableViewController {
}
- (void) createModel {
self.dataSource = [TTListDataSource dataSourceWithObjects:
[[[ContactViewCell alloc] initWithName:#"Cell 1"
target:self
action:#selector(moreButtonDidPress:)]
autorelease],
[[[ContactViewCell alloc] initWithName:#"Cell 2"
target:self
action:#selector(moreButtonDidPress:)]
autorelease],
nil];
}
In the action handler, that's where showMenu:forCell: is called. The trick is to determine which cell the button belongs to and consequently replace that cell with the menu view. This is what I did.
- (void) moreButtonDidPress:(id)sender {
// Load our custom menu view from a nib.
UIView *menuView = [[UIView alloc] initWithFrame:cell.contentView];
UIButton *moreButton = (UIButton *) sender;
// Convert plusButton bounds to the the coordinate system of table view
// and then get the cell containing the button.
CGRect coord = [plusButton convertRect:moreButton.bounds toView:self.tableView];
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:coord.origin];
TTTableViewCell* cell = (TTTableViewCell*) [self.tableView
cellForRowAtIndexPath:path];
// Now call showMenu with the menu to display on the associated cell.
[self showMenu:menuView forCell:cell animated:YES];
}
It's not exactly using a URL Navigator selector, but it's functional.