Tapping near a button on navigation invokes the button - unexpected iPhone behaviour - iphone

I have a UIViewController class with a navigation bar shown and a button on the rightmost end of the navigation bar. Then right underneath it is my main content area with a UISegmentedControl shown below the navigation bar.
Whenever I click/tap on the navigation bar near the right button but not directly on the button, I am getting an unexpected button press event. Usually, it's when I'm trying tap on the right most segment item that happens to be placed beneath the button. So the tap is on the button instead of the segment. How do I make sure the event is directed to the right receiver?
My UI is created with Interface Builder and the UISegmentedControl is hooked up to my class in the nib file.
My class:
#interface MyViewController : UIViewController
{
IBOutlet UISegmentedControl *segmentedControl;
}
#end
#implementation MyViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
UIBarButtonItem *button = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
target:self action:#selector(onButtonPressed:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
}
- (IBAction)onButtonPressed:(id)sender
{
NSLog(#"onButtonPressed reached!");
}
- (IBAction)onSegmentItemPressed:(id)sender
{
NSLog(#"onSegmentItemPressed for: %d", [segmentedControl selectedSegmentIndex]);
}
#end

This is standard behavior. It is designed to make those small buttons easier to press. You can try it in any app with a navbar and you will get the same result. Without seeing the layout of your app, I would think you are either missing the segment (try tapping more carefully) or the segment is too close to the navbar button (move it slightly).
It may be possible to use the hitTest: methods to determine whether or not the touch was in the segment, and manually activate it, but I would think this is more trouble than it's worth.

You may need to move the segmented control's origin further down, vertically, away from the navigation bar button item, to prevent unexpected taps.

Related

Add button to top UITabBarController

I have an app which has a UITabBarController as rootviewcontroller. The UITabBarController has four items. The four UIViewConotrollers are embedded in UINavigationControllers. I can add a button or image on the UINavigationController. However, I have to repeat 4 times on each UINavigationController for the same button or image. Is it possible I can add a button or image on the top of UITabBarController which is set as rootviewcontroller? Thanks in advance.
Theoretically, you can do it by:
UIButton *button = ; // your button
button.frame = CGRect(...); // position on the screen, where you want to have the button
[rootViewController addSubview:button];
However, this solution is strongly not recommended.
What you can do instead, is to create an abstract class MyViewControllerWithButton : UIViewController which will implement viewDidAppear: creation of UIButton and adding it to the navigationBar.
All the viewControllers that you use in tab bars will be a subclass of MyViewControllerWithButton.

Cannot hide a view inside View controller with CGRectMake

I am using a UIView item on my view controller that contains a picker view and a button, which needs to appear on the screen only when the show button is clicked.
I created a outlet for my UIView with name *pickerView
The default position of this view (on the right properties bar of Xcode) is (0,200,320,261) for (x,y, height and width) which basically makes it appear at the base of the ViewController.
What I did for this view to hide initially when the view controller loads is, in the ViewDidLoad method I put this code:
pickerView.frame=CGRectMake(0,450,320,261);
For the action of show button,
pickerView.frame=CGRectMake(0,200,320,261);
I have a hide button inside this UIView, in its action i have
pickerView.frame=CGRectMake(0,450,320,261);
SO, from what I expect when I run the application, the UIView pickerView should initially hide because of code in viewDidLoad, and show button should bring it on the screen.
My problem is show and hide button works fine, but every time I load this ViewController the View appears on screen by default. Help me hide this UIView when I load the viewController.
Simpley don't set the frame for picker view
i am posting a sample code it makes picker view hide and appear when tapping the button
i am using the property "hide"
hear is the sample code
- (void)viewDidLoad
{
[super viewDidLoad // Do any additional setup after loading the view, typically from a nib.
//as simple dont set frame.
// i am using xib from there i wired up picker view
self.myPickerView.hidden = YES; //just hide it whenever you dont use it.
}
- (IBAction)whenShowHideButtonTapped:(id)sender
{
//when button pressed just show it
if(self.myPickerView.hidden)
{
self.myPickerView.hidden = NO;
}
else
{
self.myPickerView.hidden = YES;
}
}
hope this helps .. :)
You could call the hide code in 'viewWillAppear:' like this:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self hidePicker];
}

how to change uinavigation controller back button action

I have a UINavigationController and I have to keep the the default back button "the back arrow style" I just want to ask if I can change the back button action without build new one and change its style
AFAIK you cannot change the action of the default back button itself but you can place a UIBarButtonItem as leftBarButtonItem there and assign your own action.
If there is a leftBarButtonItem defined then this is shown and not the default back button.
However, keep the GUI guidelines in mind when doing tricks like this.
No. If you want a custom back button, you have to create a custom UIBarButtonItem, then assign it to the appropriate property:
self.navigationItem.backBarButtonItem = myCustomBackItem;
The back button in UINavigationBar is generated automatically as soon as u Push a new UIView. In order for you to customize the Back button is to Create a new UIToolBar + a UIBarButtonItem with custom view.
Code below is the sample to use a custom UIBarButtonItem in UIToolBar.
// create button
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:#selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
// create button item -- possible because UIButton subclasses UIView!
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
// add to toolbar, or to a navbar (you should only have one of these!)
[toolbar setItems:[NSArray arrayWithObject:backItem]];
navItem.leftBarButtonItem = backItem;
Link below is the design of iOS buttons in PSD format for further modifications.
http://www.chrisandtennille.com/pictures/backbutton.psd
You can make custom button and can make action on it but you can not change default backButton action.....
self.navigationItem.leftBarButtonItem = getBackBtn;
The UINavigationController sends a message to it's delegate when it pushes and pops a ViewController.
You can find out when the back button gets pressed by implementing the following and adding <UINavigationControllerDelegate> in your .h file
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.delegate = self;
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
self.navigationController.delegate = nil;
}
-(void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated{
//Test here if the View Controller being shown next is right below the current
// ViewController in the navigation stack
//
//Test by:
// 1. comparing classes, or
// 2. checking for a unique tag that you previously assigned, or
// 3. comparing against the [navigationController viewControllers][n-2]
// where n is the number of items in the array
if ([viewController isKindOfClass:NSClassFromString(#"ViewControllerClassThatGetsPushedOnBACK")){
//back button has been pressed
}
if (viewController.tag == myUniqueTagIdentifier){
//back button has been pressed
}
if ([navigationController.viewControllers[navigationController.viewControllers.count-2]==viewController]){
//back button has been pressed
}
}
Apple Docs UINavigationController Class Reference:
The root view controller is at index 0 in the array, the back view
controller is at index n-2, and the top controller is at index n-1,
where n is the number of items in the array.

iOS App development : View visible but not active

Please help! It seems to simple, but, sorry, I 'have' to ask, as it's not working. I have a main view with a UITableView. On swiping, am adding a subview which has a picker and a button. It works fine: I swipe & the subview appears in front of the main view, but when I click the picker or the button, nothing really happens in the subview; instead the components in the main view (which is beneath the subview) get called! Am saying this for sure, because, in the main view, I have a picture beneath the added-subview (tapping the picture opens a new view). Now, when I tap the picker in the subview (the picture is beneath it in the main view), the picture gets tapped & the new view opens up! How is this possible?
This is the subview (in Interface Builder)
Here's my code snippet:
In my MainViewController.m (viewCtrlrFilter is the subview added when the user swipes in the main view)):
....
self.viewCtrlrFilter = (ViewController_Filter *) [myStoryboard instantiateViewControllerWithIdentifier:kNameViewCtrlrFilter];
...
// This is called when the user pans/swipes
// This does work fine; the subview gets added & is visible
[self.viewCtrlrFilter initializeView];
[self.viewCtrlr.view setFrame:CGRectMake(310.0, 220.0, 243.0, 208.0)];
[self.view addSubview:self.viewCtrlrFilter.view];
...
From ViewController_Filter.h :
...
// This implements the Picker Delegate & DataSource
// which I have wired to the picker in IB
#interface ViewController_FilterPhotographers : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>
...
// This is called when the button in the subview
// (screenshot above) is pressed
// It's wired through the IB
-(IBAction) buttonPressed:(id) sender;
...
From ViewController_Filter.m :
-(void) initializeView {
self.myPicker.delegate = self;
self.myPicker.dataSource = self;
self.myPicker.showsSelectionIndicator = YES;
CGRect rect = self.myPicker.frame;
rect.origin = CGPointMake(0.0, 0.0);
self.myPicker.frame = rect;
self.myPicker.transform = CGAffineTransformMakeScale(0.625,0.625);
[self.myPicker becomeFirstResponder];
}
...
-(IBAction) buttonPressed:(id) sender {
NSLog(#"hi");
}
...
- (void)viewDidLoad
{
[super viewDidLoad];
[self initializeView];
}
...
When the user swipes, the subview does get added (the picker & button are seen), but when I click the button, the IBAction method isn't getting called. Instead, funnily, the component in the main view (beneath the subview) is getting called!
It works now! Looks like setting the datasource & delegate for the picker view from both the code & IB was a problem. I set it from IB & removed it from code. It works fine now!

Use segmented Control to switch between 2 views

I make an iphone application that use a segmented Control to switch between 2 viewControllers that display different informations. So, I defined in the first view Controller a segmented Control that I linked in IB to a Segmented Control that I place on the corresponding view.
#interface FirstViewController : UIViewController{
//NSArray * viewControllers;
//UINavigationController * navigationController;
IBOutlet UISegmentedControl *segment; //->segment linked in the nib of FirstViewController
}
The action related to the segmented control is the following:
-(IBAction)valuechanged:(id)sender{
NSInteger index = [(UISegmentedControl *)sender selectedSegmentIndex];
UIViewController *parking=[[ParkingViewController alloc]
initWithNibName:#"ParkingViewController" bundle:nil] ;
viewControllers= [NSArray arrayWithObjects:self,parking,nil];
if(index==1){
UIViewController * incomingViewController = [viewControllers objectAtIndex:index];
[self presentModalViewController:incomingViewController animated:YES];
}
}
In this Action, I define what to do once user click on segmented control.Here, it's loading a new viewController named ParkingViewController. The problem is that once the new ParkingViewController is loaded the segmentedControl disappear and so I can't come back to the firstViewController.
I don't know how to do to keep the segmentedControl for both views?
Thank u all
Quentin
Generally, the UITabBarController is used to control switching between two or more view controllers. It will stay on the screen and allow switching back and forth.
The segmented controller you have cannot stay on the screen when you present a modal view. A modal view will take over the entire screen. Also, because you are animating it onto the screen, a copy of the segmented view controller in the new view will not appear to be the same segmented control because the user saw it scroll onto the screen.
I can't come back to the firstViewController... ??
You can add a UIButton and call an IBAction
[self dismissModalViewControllerAnimated:NO];