How to hide UItoolbar on segmented click - objective-c

I have create a UIViewController with multiple subviews.. To switch to all subviews i have added a segmented control.. screen looks like this..
On the second view i have added a UIToolbar, using this line of code..
toolbar = [UIToolbar new];
toolbar.barStyle = UIBarStyleDefault;
[toolbar sizeToFit];
toolbar.frame = CGRectMake(0, 0, 800, 40);
UIBarButtonItem *filterByClass = [[UIBarButtonItem alloc] initWithTitle:#"A" style:UIBarButtonItemStyleBordered target:self action:#selector(goToFilteredByClass:)];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
NSArray *buttonItems = [NSArray arrayWithObjects:filterByClass, spacer, nil];
[toolbar setItems:buttonItems animated:NO];
So the screen will look like this..
when i go back to segment A, here's my screen..
then data is covered by the toolbar.. I want to remove it because segment A doesn't have a toolbar.. Is there a way to fix this issue..?
Thanks,
Link

Set up an action in your view controller, and have your segmented control call that action when its "value changed" event fires.
The segments of the control are numbered like an array, from 0 onwards. In your action method, you test for the segment you're interested in (in this case, segment 0) and show or hide the toolbar. You could animate it offscreen too, if you prefer a sliding animation.
If you aren't worried about leaving the toolbar for reuse later, you could use removeFromSuperview in your action method; but you won't get the animation if you use this method.
Quick example for hiding it using Core Animation:
-(IBAction)segmentedControlValueChanged:(UISegmentedControl *)sender
{
switch (sender.selectedSegmentIndex) {
case 0:
// A was pressed, so hide the toolbar
[UIView animateWithDuration:0.2
animations: ^(void) { toolbar.alpha = 0.0; }];
break;
case 1:
// B was pressed so show the toolbar
[UIView animateWithDuration 0.2
animations: ^(void) { toolbar.alpha = 1.0; }];
break;
}
}

Related

Toolbar button unresponsive after iOS 13.4.1 update

I have had a medical calculation app for cardiac ultrasound in the App Store since 2011. At the bottom of each data entry screen is a toolbar with buttons to analyze all data, designate the open calculation as a favorite, and clear all active data from all calculations. After the most recent iOS update to 13.4.1, the Clear button at the bottom right of the screen has become unresponsive. If I put the app in the background, open another app, and then switch back to my app, then the Clear button becomes responsive again. If I move the Clear button to the left side of the toolbar, next to the Analyze button, then it functions without a problem. Since the code that displays these buttons has been the same for years and multiple iOS versions, I am wondering if possibly there is a bug in iOS 13.4.1 causing this issue.
Here is the code used to generate the toolbar:
//Initialize the toolbar
toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleDefault;
//Set the toolbar to fit the width of the app.
[toolbar sizeToFit];
//Caclulate the height of the toolbar
CGFloat toolbarHeight = [toolbar frame].size.height;
//Get the bounds of the parent view
CGRect rootViewBounds = self.parentViewController.view.bounds;
//Get the height of the parent view.
CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);
//Get the width of the parent view,
CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);
//Create a rectangle for the toolbar
CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight - [sharedVariableState g_toolbar_adjuster_for_Home_indicator], rootViewWidth, toolbarHeight);
//Reposition and resize the receiver
[toolbar setFrame:rectArea];
//Create two buttons separated by spacer item.
UIBarButtonItem *analyzeButton = [[UIBarButtonItem alloc] initWithTitle:#"Analyze" style:UIBarButtonItemStylePlain target:self action:#selector(analyze_clicked:)];
UIBarButtonItem *clearButton = [[UIBarButtonItem alloc] initWithTitle:#"Clear" style:UIBarButtonItemStylePlain target:self action:#selector(clear_clicked:)];
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; //Load NSUserDefaults.
NSMutableArray *objectArrayMutable = [[NSMutableArray alloc]init];
objectArrayMutable = [[prefs objectForKey:#"savedFavoritesArray"] mutableCopy];
int favoriteChosenAlready = 0;
if ([objectArrayMutable count] > 0) {
for (int arrayCounter = 0; arrayCounter < [objectArrayMutable count]; arrayCounter++) {
if ([[objectArrayMutable objectAtIndex:arrayCounter] integerValue] == 58) {
favoriteChosenAlready = 1;
}
}
}
UIButton *favButton = [[UIButton alloc] init];
if (favoriteChosenAlready == 0) {
//Display empty star.
[favButton setImage:[UIImage imageNamed:#"Star_button_empty.png"] forState:UIControlStateNormal];
}
else {
//Display filled star.
[favButton setImage:[UIImage imageNamed:#"Star_button_filled.png"] forState:UIControlStateNormal];
}
[favButton addTarget:self action:#selector(favorite_clicked:) forControlEvents:UIControlEventTouchUpInside];
[favButton setFrame:CGRectMake(280, 25, 30, 30)];
UIBarButtonItem *favoriteButton = [[UIBarButtonItem alloc] initWithCustomView:favButton];
[[UIBarButtonItem appearance] setTintColor:[UIColor lightGrayColor]]; //Make toolbar button text lightGrayColor.
[toolbar setItems:[NSArray arrayWithObjects:analyzeButton,flexItem,favoriteButton,flexItem,clearButton,nil]];
//Add the toolbar as a subview to the navigation controller.
[self.navigationController.view addSubview:toolbar];
To clarify, the Clear button here now is unresponsive:
[toolbar setItems:[NSArray arrayWithObjects:analyzeButton,flexItem,favoriteButton,flexItem,clearButton,nil]];
However, just rearranging the sequence of buttons in the toolbar fixes the problem:
[toolbar setItems:[NSArray arrayWithObjects:analyzeButton,clearButton,favoriteButton,flexItem,flexItem,nil]];

Remove subview when touched outside of subview

My situation is a little more complicated than the others listed.
I have a UITableView that takes up most of the screen.
Each row pops up a subview that contains more profile information. When the screen is clicked again this subview disappears. This works perfectly.
In the Navigation Bar I have a button that will display a small menu.
- (IBAction)menuButtonClicked:(UIBarButtonItem *)sender {
//If menuView exists and Menu button is clicked, remove it from view
if (self.menuView) {
self.tableView.userInteractionEnabled = true;
[self.menuView removeFromSuperview];
self.menuView = Nil;
}
//Menu View doesn't exist so create it
else {
// Create the Menu View and add it to the parent view
self.menuView = [[[NSBundle mainBundle] loadNibNamed:#"MenuView" owner:self
options:nil] objectAtIndex:0];
self.menuView.layer.cornerRadius = 20.0f;
self.menuView.layer.borderWidth = 3.0f;
self.menuView.layer.borderColor = [UIColor whiteColor].CGColor;
self.menuView.frame = CGRectMake(0, 64, self.menuView.frame.size.width,
self.menuView.frame.size.height);
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[self.menuView addGestureRecognizer:singleTap];
//Disable Selection of Profiles while Menu is showing
self.tableView.userInteractionEnabled = false;
//Add MenuView to View
[self.view addSubview: self.menuView];
}
}
//Removed Sub Views from View when tapped
-(void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture{
if(self.profileView){
[self.profileView removeFromSuperview];
self.profileView = Nil;
}
if(self.menuView) {
self.tableView.userInteractionEnabled = true;
[self.menuView removeFromSuperview];
self.menuView = Nil;
}
}
Now I want to dismiss this menus if the menu button is clicked again (working in above code) but also when the user touches out of the menu and on the tableView or navbar. If the menu is displayed, I don't want the tableView to display it's profile subview (working in above code) but just remove the menuView. I can't get the menuView to go away if I touch the tableView.
Can anyone point me in the right direction?
Make a new transparent overlay view sized to cover the entire screen. Add your menuView as a subview of the overlay, then add the overlay as a subview of your main window. Put a tap gesture recognizer on the overlay that will dismiss it when tapped.
You may need to set cancelsTouchesInView to NO on your gesture recognizer if buttons on your menu view are not working.
Roughly this (please excuse typos, I haven't compiled this):
- (void)showMenu
{
self.overlay = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
overlay.backgroundColor = [UIColor clearColor];
self.menuView = /* code to load menuView */;
[overlay addSubview:self.menuView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(onSingleTap:)];
tap.cancelsTouchesInView = NO;
[overlay addGestureRecognizer:tap];
[self.tableView.window addSubview:overlay];
}
- (void)handleSingleTap:(UITapGestureRecognizer *)sender
{
[self.overlay removeFromSuperview];
}
You might also want to add a swipe gesture recognizer to also dismiss the overlay, as someone may attempt to scroll the table expecting the menu to be dismissed.
While trying to make my own custom topdown-slide menu using my own custom NIB file, I found that this can be achieved by many techniques. I would like to suggest and share a different solution which is very similar but is created with a custom button on the background.
I've been looking around but could not find answers mentioning this.
This is very similar to the tap recogniser except for one thing - tap recogniser spreads all over the layout (including subviews), while using a layer of custom button allows you to interact with the top view and dismiss/ remove it from superview when clicking on lower layer (when lower layer is the background button). This is how I did it:
You create the layout
You add a UIButton with type UIButtonTypeCustom to the layout
You frame this layout over the view you wish to be responsive to that tap/click
You add your menu view on top of that layout and animate your menu to appear
- (void)showMenuViewWithBackgroundButtonOverlay
{
self.backgroundButton = ({
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = self.view.frame;
[button addTarget:self action:#selector(toggleAppMenu) forControlEvents:UIControlEventTouchUpInside];
button;
});
if (!self.menu) {
self.menu = [self createMenu]; // <-- get your own custom menu UIView
}
if (!self.overlay) {
self.overlay = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.overlay.backgroundColor = [UIColor clearColor];
[self.overlay addSubview:self.backgroundButton];
[self.overlay addSubview:self.menu];
[self.view addSubview:self.overlay];
}
[self toggleAppMenu];
}
And the toggleAppMenu:
- (void)toggleAppMenu
{
CGRect nowFrame = [self.menu frame];
CGRect toBeFrame = nowFrame;
CGFloat navHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
if (self.showingMenu) {
toBeFrame.origin.y = toBeFrame.origin.y-nowFrame.size.height-navHeight-statusBarHeight;
[UIView animateWithDuration:0.5 animations:^{
[self.menu setFrame: toBeFrame];
}completion:^(BOOL finished) {
self.showingMenu = !self.showingMenu;
[self.view endEditing:YES];
[self.overlay removeFromSuperview];
self.overlay = nil;
NSLog(#"menu is NOT showing");
}];
}
else{
toBeFrame.origin.y = navHeight+statusBarHeight;
[UIView animateWithDuration:0.5 animations:^{
[self.menu setFrame: toBeFrame];
}completion:^(BOOL finished) {
self.showingMenu = !self.showingMenu;
NSLog(#"menu is showing");
}];
}
}
I hope this will be helpful for someone.
Works on Swift 5
I create custom view and I want it hide by tap outside subview. Maybe it can help for someone or anybody can suggest a better way :)
// create tap for view
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(animateOut))
self.addGestureRecognizer(tapGesture)
// create tap for subview
let tapGesture2 = UITapGestureRecognizer(target: self, action: nil)
container.addGestureRecognizer(tapGesture2)

Dilemma in toolbaritem

I've been working on my book app, but I have a UIBarButtonItem dilemma. I have set the 3 bar buttons on the toolbar as you can see in the image below. They work fine until I set the single tap recognizer, the last 2 lines in the code. What I want to do is get out of this modal screen by a single tap, not a double tap, not by adding another 'Cancel' button on the toolbar. After I set the single tap recognizer, none of the bar button items work.
How can I get out of this dilemma. Can any one tell me how to get around this? Thank you for your time.
UIToolbar* toolbar = [[UIToolbar alloc] init];
toolbar.barStyle = UIBarStyleDefault;
[toolbar sizeToFit];
toolbar.frame = CGRectMake(0, 410, 320, 50);
toolbar.tintColor = _label.backgroundColor;
self.title = #"Test For Toolbar";
UIBarButtonItem* TofC = [[UIBarButtonItem alloc] initWithTitle:#"T of C"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(showTofC)];
UIBarButtonItem* bookMark =
[[UIBarButtonItem alloc] initWithTitle:#"Book Mark"style:UIBarButtonItemStyleBordered
target:self
action:#selector(bookMarkIt)];
UIBarButtonItem* searchBtn = [[UIBarButtonItem alloc] initWithTitle:#"Search"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(searchIt)];
UIBarButtonItem* spacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
NSArray* buttons =
[NSArray arrayWithObjects:TofC, spacer, bookMark, spacer, searchBtn, nil];
self.navigationController.toolbarHidden = NO;
[toolbar setItems:buttons animated:NO];
[self.view addSubview:toolbar];
/*
// Single Tap
UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTapGesture:)];
[self.view addGestureRecognizer:tapGesture];
*/
// Single Tap
Dum2ViewController* dum2ViewController = [[Dum2ViewController alloc] init];
UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:dum2ViewController
action:#selector(handleTapGesture:)];
[dum2ViewController.view addGestureRecognizer:tapGesture];
You've added the toolbar as a subview of your main view and then attached a gesture recognizer to the main view.
So as soon as you touch the toolbar, the touch goes to the main view first and is intercepted the gesture recognizer before it can be passed down to the toolbar items.
What I'd recommend doing is setting a gesture recognizer on whatever content (another subview?) that is inside your current view. That way a touch in the toolbar will be routed to the toolbar and a touch within the view will go to the (content) subview and be caught by the gesture recognizer.
Makes sense?

How to add swipe gesture on a fullscreen mode MPMoviePlayerController in IOS6

I tried to add a swipe gesture to player.view.subviews[0].
I googled for many times but could not get a working solution.
My code is very normal. just like
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeAction:)];
UIView *subView = player.view.subviews[0];
[subView addGestureRecognizer:swipeLeft];
It works in IOS5 but not in 6 when player is in fullscreen mode.
Any suggestions?
When Mpmovieplaertsontroller enters full-screen mode, it creates an additional window (usually the last in the list of application windows). From this we can test all possible views and subviews and find the necessary controls. Then you can put everything you need.
For example, how to add swipes to the MPMoviePlayer.
- (void)didEnterFullScreen:(NSNotification*)notification {
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:#selector(showFullScreenControls) userInfo:nil repeats:NO];
}
- (void)showFullScreenControls {
NSArray *windows = [[UIApplication sharedApplication] windows];
UIWindow* mpfullscreenwindow = [windows lastObject];
gestureView = mpfullscreenwindow.subviews[0];
testbutton = [UIButton buttonWithType:UIButtonTypeSystem];
[testbutton setTitle:#"Test" forState:UIControlStateNormal];
testbutton.frame = CGRectMake(10, 50, 100, 50);
testbutton.backgroundColor = [UIColor greenColor];
[testbutton addTarget:self action:#selector(alertBtnAction) forControlEvents: UIControlEventTouchUpInside];
[mpfullscreenwindow addSubview:testbutton];
[gestureView addGestureRecognizer:_leftSwipeRecognizer];
[gestureView addGestureRecognizer:_rightSwipeRecognizer];
}
Rather than adding the gesture recognizers to one of the player's views, you could add the recognizers to your own view (the one that contains the player view). Just be sure to clear cancelsTouchesInView to give the underlying views a crack at the touches.
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeAction:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:swipeLeft];
I've successfully used this approach in the same situation.
I was able to add a gesture recognizer to the window when the player goes to full screen mode (first catching that notification event).
func moviePlayerDidEnterFullscreen (notification : NSNotification) {
self.window?.addGestureRecognizer(swipeUpGestureRecognizer)
}

UISearchBar in UIView in UIBarButtonItem does not work as expected

Im trying to add UIsearchBar to my navigation controller. Also i wish to use cancel button of UISearchBar.
UISearchBar* searchBar = [[UISearchBar alloc] init];
searchBar.frame = CGRectMake(0, 0, 300, searchBar.frame.size.height);
searchBar.translucent = NO;
searchBar.barStyle = UIBarStyleBlack;
searchBar.delegate = self;
UIView* myView = [[UIView alloc] initWithFrame:searchBar.frame];
[myView addSubview:searchBar];
UIBarButtonItem* sbItem = [[UIBarButtonItem alloc] initWithCustomView:myView];
[self.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:chart,sbItem,nil]];
trouble that searchBar is inactive. it appears in navigation controller. But when i tap on it it does not response at any way. If i show cancel button it appears but also not clickable.
If i doesnt wrap UIsearchBar at UIView it work fine except it doesnt want to show me a cancel button.
UPD
IF i call
[searchBar becomeFirstResponder]
it goes to edit mode and shows me a cancel button and keyboard, but looks like view in which searchBar wrapped changes it frame params and goes on 10px down from its original appearence. And change its background from trnsparent to blackopaque
Looks like a some kind of Voodoo... So simple action takes so much time...
i think you have mistaken at search bar frame,you took search bar height as searchBar.frame.size.height,but there was no height at that time,just change it like:
UISearchBar* searchBar = [[UISearchBar alloc] init];
searchBar.frame = CGRectMake(0, 0, 300, 40);
searchBar.translucent = NO;
searchBar.barStyle = UIBarStyleBlack;
searchBar.delegate = self;
UIView* myView = [[UIView alloc] initWithFrame:searchBar.frame];
[myView addSubview:searchBar];
UIBarButtonItem* sbItem = [[UIBarButtonItem alloc] initWithCustomView:myView];
[self.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:chart,sbItem,nil]];
i am sorry,i don't know what the chart is here,hope it is what you are looking for.