Change items in navigation bar on device rotation - ios

I have custom UIBarButton items added to UINavigationBar as rightbarbuttonitems. I add two more items in UIBarButton when device goes to landscape mode. I am getting rotation call and I am correctly removing items from UIBarbuttons array based on device orientation, but my navigationbar item set never gets updates.
If i start with portrait mode, it shows what it suppose to. When I rotate to landscape new items are not added to navigation bar and vice versa extra item won't go when device go to portrait.
I am not sure how I can change navigationbaritems on device rotation. Per me I am doing all things correct.
-(void)setUpOnRotation:(BOOL)toPortrait{
_searchMessage = [[UILabel alloc] initWithFrame:CGRectMake(3.0, 0, 110, 20)];
_searchMessage.numberOfLines = 2;
_searchMessage.textColor = [UIColor blackColor];
_searchMessage.font = [UIFont systemFontOfSize:8.0];
_searchMessage.text = #"";
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 15, 130, 25)];
_searchBar.delegate = self;
_searchBar.showsCancelButton = NO;
UIBarButtonItem* doneButton = [BarButtons doneButtonWithTarget:self action:#selector(cancel)];
UIBarButtonItem *searchActivityItem = [[UIBarButtonItem alloc] initWithCustomView:_searchMessage];
UIBarButtonItem *searchItem = [[UIBarButtonItem alloc] initWithCustomView:_searchBar];
UIBarButtonItem *in = [BarButtons nativeButtonNamed:#"In"
title:#"In"
target:self
action:#selector(In)];
UIBarButtonItem *out = [BarButtons nativeButtonNamed:#"Out"
title:#"Out"
target:self
action:#selector(Out)];
NSMutableArray *itemsSet;
itemsSet = [NSMutableArray arrayWithObjects:in,
out,
searchItem,
searchActivityItem,
doneButton, nil];
if (toPortrait) {
if ([itemsSet containsObject:searchItem] || [itemsSet containsObject:searchActivityItem]) {
[itemsSet removeObject:searchActivityItem];
[itemsSet removeObject:searchItem];
}
}
[_searchBar release];
[searchItem release];
[_searchActivity release];
[_searchMessage release];
[searchActivityView release];
self.navigationItem.rightBarButtonItems = itemsSet;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self setUpOnRotation:UIInterfaceOrientationIsPortrait(toInterfaceOrientation)];
} -(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
[self setUpOnRotation:UIInterfaceOrientationIsPortrait(self.interfaceOrientation)];}
Note: setUpOnRotaion method is called from willAnimateRotationToInterfaceOrientation and viewWillAppear with UIInterfaceOrientationIsPortrait(self.intefaceOrientation) and it does give me correct result. I have debugged.

In willAnimateRotationToInterfaceOrientation change cehck for orientation
if([uidevice orientaiton]statusbarorientation]){
self.naviogationite.rightbarbuttonitems = #[btn1,btn2,btn3];
}
else{
self.naviogationite.rightbarbuttonitems = #[abtn1,abtn2,abnt3];
}
u can do like this
can u do like this
NSMutableArray *itemsSet;
if(!toPortrait){
itemsSet = [NSMutableArray arrayWithObjects:in,
out,
searchItem,
searchActivityItem,
doneButton, nil];
}
if (toPortrait) {
itemsSet = [NSMutableArray arrayWithObjects:in,
out,
doneButton, nil];
}

Related

The navigation bar and bottom toolbar is not working(not respond to tap/click)

I have a problem in ios7(ipad), that is, the navigation bar and the bottom toolbar can not catch the tap event. The same code works fine in the ios 8 (iphone/ipad). Here is my code, I have a slideView which is a UIView, and I push another UIView singleCamView into it. The first time I load into the singleCamView, the navigation and the toolbar isn't working, but when I go back to slideView and get into the singleCamView again, everything is fine.
In slideView:
(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self changeUILayout];
[serverMgr disableTalkFunc];
if (eLayoutType == eLayout_1X1 && !backFrom1x1) {
[self changeLayout_1x1];
}
}
(void)changeLayout_1x1 {
if ([self.navigationController.visibleViewController isKindOfClass:[SlideView class]]) {
int camInArray = 0;//iPageIdx * [self getPreviewNum] + singleCamPos;
SinglePageViewController_Base *firstPage = [viewControllers objectAtIndex:0];
SingleCamViewController * mCam = [[SingleCamViewController alloc] initWithServerManager:serverMgr CurrentCam:camInArray];
[mCam setParent:firstPage];
[mCam setTitle:[serverMgr getDeviceNameByChIndex:0]];
mCam.changeLayoutDelegate = self;
int ch_index = 0;//iPageIdx * [self getPreviewNum] + pos;
[serverMgr updateAudioAndPtzDeviceByChIndex:ch_index];
[mCam setPtzCap:[serverMgr isSupportPTZ:ch_index]];
[mCam setAudioCap:[serverMgr isSupportAudio:ch_index]];
[mCam setTalkCap:[serverMgr isSupportTalk:ch_index]];
[firstPage setSingleCam:mCam];
[serverMgr setPlaybackDelegate:mCam];
[self.navigationController pushViewController:mCam animated:YES];
//clear to default picture
[firstPage setDefaultPic];
[serverMgr disconnectAllCam];
[serverMgr connectToCamWithHighResolution:ch_index];
[mCam release];
eLayoutType = eLayout_1X1;
[serverMgr setLayoutType:eLayout_1X1];
[parent save];
}
else {
return;
}
}
In singleCamView:
....
UIImage *backImage;
UIButton *bButton = [UIButton buttonWithType:UIButtonTypeCustom];
if (IS_IPAD)
backImage = [UIImage imageNamed:#"Back_48x48_nor.png"];
else
backImage = [UIImage imageNamed:#"Back_32x32_nor.png"];
bButton.bounds = CGRectMake(0, 0, backImage.size.width, backImage.size.height);
[bButton setImage:backImage forState:UIControlStateNormal];
[bButton addTarget:self action:#selector(onBackBtnTap) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * backButton = [[UIBarButtonItem alloc] initWithCustomView:bButton];
UIBarButtonItem * backButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Back", nil) style:UIBarButtonItemStylePlain target:self action:#selector(onBackBtnTap)];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[backButton setTintColor:COLOR_NAVBUTTONTINT];
}
else {
[backButton setTintColor:COLOR_NAVBUTTONTINTIOS6];
}
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];
The important thing is, it works fine in ios8, I can't figure out the reason. Thank you.
Finally I solve my own problem, here is the solution, the key point is that the second view is pushed right after the main view is created, the controller (maybe) is not fully initialized yet. So I add a delay between main view and second, everything works fine.
This post gives me the solution. Adding delay between execution of two following lines

Multiple pickerviews and retrieving data from Parse

I have 4 pickerview in a view controller and, I need that after 2 of them have been selected with the desired user preference I want the third to retrieve data from Parse based on the user's selection of the other two, any way I can implement this? Now I've each picker view with a tag but I can't implement a PFQuery inside the pickerview methods.
Thank you.
This is what I have, trying to do a custom pickerview but I would like to use the UIPickerView class methods.
#pragma mark - Select Schedule
-(void)selectSchedule:(NSString *)horari :(NSString *)origen :(NSString *)direccio{
PFQuery *queryParada = [PFQuery queryWithClassName:#"EixBusParades"];
[queryParada whereKey:#"Parada" equalTo:origen];
PFQuery *queryHours = [PFQuery queryWithClassName:#"EixBusParades"];
[queryHours whereKey:#"hSetmana" equalTo:horari];
PFQuery *queryDireccio = [PFQuery queryWithClassName:#"EixBusParades"];
[queryDireccio whereKey:#"direccio" equalTo:direccio];
PFQuery *querySchedule = [PFQuery orQueryWithSubqueries:#[queryHours,queryParada,queryDireccio]];
NSArray *objects = [querySchedule findObjects];
NSArray *depHours = [[objects objectAtIndex:0]objectForKey:#"Horaris"];
// Copy each object from the array depHours to the pickerview array in order to show it
/*int i;
int j = 0;
for (i = 0; i < [depHours count]; i++) {
[self.hores objectAtIndex:j] = [depHours objectAtIndex:i];
j++;
}*/
}
- (IBAction)tfButton:(id)sender {
[self.tfHora becomeFirstResponder];
// Retrieve correct hour data from Parse
[self selectSchedule:self.tf.text :self.tfOrigen.text :self.tfDireccio.text];
}
- (void)cancelTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.tfHora resignFirstResponder];
}
- (void)doneTouched:(UIBarButtonItem *)sender{
// hide the picker view
[self.tfHora resignFirstResponder];
}
Initialitzation of the picker view in viewdidload.
self.tfHora = [[UITextField alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tfHora];
UIPickerView *pickerHora = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];
pickerHora.showsSelectionIndicator = YES;
pickerHora.dataSource = self; // Server
pickerHora.delegate = self;
self.tfHora.inputView = pickerHora;
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneTouched:)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelTouched:)];
// the middle button is to make the Done button align to right
[toolBar setItems:[NSArray arrayWithObjects:cancelButton, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], doneButton, nil]];
self.tfHora.inputAccessoryView = toolBar;

Dismissing ViewController Shifts View of Parent Controller

My app looks like this when you launch it:
On every row except for the top one, I can push a new view controller, and dismiss it, and everything stays the same. However, if I click the Instagram row, and then dismiss the view that is pushed onto it, my screen looks like this:
In the Instagram controller that is pushed, the viewDidLoad looks like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Instagram";
UIBarButtonItem *theButton = [[UIBarButtonItem alloc] initWithTitle:#"Post" style:UIBarButtonItemStylePlain target:self action:#selector(doit)];
self.navigationItem.rightBarButtonItem = theButton;
self.downloading = YES;
self.mediaArray = [NSMutableArray arrayWithCapacity:0];
[self.collectionView registerClass:[SBInstagramCell class] forCellWithReuseIdentifier:#"SBInstagramCell"];
[self.collectionView setBackgroundColor:[UIColor whiteColor]];
[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:#"footer"];
[self.navigationController.navigationBar setTranslucent:NO];
[self.view setBackgroundColor:[UIColor whiteColor]];
self.multipleLastEntities = [NSArray array];
self.instagramController = [SBInstagramController instagramControllerWithMainViewController:self];
self.instagramController.isSearchByTag = self.isSearchByTag;
self.instagramController.searchTag = self.searchTag;
[self downloadNext];
self.collectionView.alwaysBounceVertical = YES;
refreshControl_ = [[SBInstagramRefreshControl alloc] initInScrollView:self.collectionView];
[refreshControl_ addTarget:self action:#selector(refreshCollection:) forControlEvents:UIControlEventValueChanged];
loaded_ = YES;
[self showSwitch];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
}
I get to this view like this:
SBInstagramController *instagram = [SBInstagramController instagram];
instagram.showOnePicturePerRow = YES; //to change way to show the feed, one picture per row(default = NO)
instagram.showSwitchModeView = YES; //show a segment controller with view option
[instagram refreshCollection]; //refresh instagram feed
[self.navigationController pushViewController:instagram.feed animated:YES];
To me, it looks like the UIImageView is being shifted down about 44 pixels, which would be the space of a Navigation Bar, I just can't understand why it would be doing that. I use AutoLayout and have both the UITableView and the UIImageView pinned to the top superview, but it is only the UIImageView that moves.

Toolbar items dissapear when view changed with UIActionSheet

When initiating a view from a UIActionSheet button, upon returning to the view via the navigationBar back button, the toolbar while still visible does not have any of the buttons that were previously on it. This error has arisen since updating to iOS 6 and occurs while testing it on the simulator and a device running iOS 6 only. If I comment out the code that hides the toolbar on the view pushed by the UIActionSheet the buttons are added when going back.
I'm making my toolbar items programatically in viewWillAppear and showing the UIActionSheet from the toolbar which I'm accessing via self.navigationController.toolbar.
Any idea what is causing this problem? It's only happened since iOS 6 has come around so is there any changes that I need to take into account regarding viewWillAppear?
This is how the view is pushed from the actionSheet:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (actionSheet.tag == 2) {
if (buttonIndex == 0) {
[self dismissAllTips];
self.actionNoteAddView= [[self.storyboard instantiateViewControllerWithIdentifier:#"IDActionNoteAddView"] retain];
actionNoteAddView.note_id = 0;
actionNoteAddView.iscompleted=0;
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"tool_tips"];
[self.navigationController pushViewController:actionNoteAddView animated:TRUE];
[actionNoteAddView release];
}else if(buttonIndex == 1){
...
These are the view methods for the pushed view:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationItem.hidesBackButton = NO;
[self.navigationController setToolbarHidden:YES];
txtcontent.layer.cornerRadius = 10.0f;
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
These are the view methods for the view that pushed the view using the actionSheet:
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationItem.hidesBackButton = YES;
[self.navigationController setToolbarHidden:NO];
self.navigationController.navigationBarHidden=NO;
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
self.navigationController.toolbar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.toolbar.tintColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
UIImage *actionButtonImage = [UIImage imageNamed:#"31-circle-plus#2x.png"];
UIBarButtonItem *actionButton = [[UIBarButtonItem alloc] initWithImage:actionButtonImage style:UIBarButtonItemStylePlain target:self action:#selector(actionPressed:)
];
UIImage *dashButtonImage = [UIImage imageNamed:#"19-gear.png"];
UIBarButtonItem *dashButton = [[UIBarButtonItem alloc] initWithImage:dashButtonImage style:UIBarButtonItemStylePlain target:self action:#selector(settingsPressed:)];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
NSArray *toolitems = [NSArray arrayWithObjects:dashButton, flexItem, actionButton, flexItem, nil];
[self setToolbarItems:toolitems];
self.title = #"Dashboard";
defaultProfile.text = [[NSUserDefaults standardUserDefaults] stringForKey:#"default_profile"];
BOOL dailyProcess = [[NSUserDefaults standardUserDefaults] boolForKey:#"daily_process"];
if(dailyProcess){
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"daily_process"];
[[NSUserDefaults standardUserDefaults] synchronize];
loading = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
labelProcess = [[UILabel alloc]initWithFrame:CGRectMake(60, 105, 240, 30)];
labelProcess.text = #"Processing...";
labelProcess.backgroundColor = [UIColor clearColor];
labelProcess.textColor=[UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
[labelProcess setFont:[UIFont systemFontOfSize:20]];
loading.opaque = NO;
loading.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f];
indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[indicator setHidesWhenStopped:YES];
indicator.center = self.view.center;
[self.view addSubview:loading];
[self.view addSubview:indicator];
[self.view addSubview:labelProcess];
[indicator startAnimating];
}
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
CGRect frame = CGRectMake(157, 365, 10, 10);
UIView *viewToPointAt = [[UIView alloc] initWithFrame:frame];
[self.view addSubview:viewToPointAt];
BOOL willies = [[NSUserDefaults standardUserDefaults] boolForKey:#"tool_tips"];
if(willies==YES){
if(popTip == nil) {
popTip = [[[CMPopTipView alloc] initWithMessage:#"Step 1/3: This is the Action Button. You can create, view and auto-fill notes which are then added to your timeline.(Click for step 2)."] autorelease];
popTip.delegate = self;
[popTip presentPointingAtView:viewToPointAt inView:self.view animated:YES];
popTip.backgroundColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
popTip.textColor = [UIColor whiteColor];
}
}
[viewToPointAt release];
}
Tried a lot of different techniques and eventually sorted it by showing it in one view method and hiding it in the next. It's one fo the strangest bugs I have encountered and this is hardly a fix, but I hate having unanswered questions.
You may solve this by hiding the toolbar in the next view, but that is not a very good solution, as other views that can be possibly opened from the view that contains the toolbar will all have to hide the toolbar when needed, this is annoying.
Another solution is to hide the toolbar in viewDidDisappear but there is another problem, let's say another new view needs the toolbar as well, and it sets the toolbar visible in its own viewWillAppear then the problem is that the viewWillAppear for the new view will be called actually before viewDidDisappear of the previous view, so in that case the toolbar disappear even the new view desires it.
Anyway, I'm not sure if this is a bug of iOS6 as it works fine for iOS5, what worked for me was to wrap the code that opens the new view into dispatch_async(dispatch_queue_t queue, dispatch_block_t block), my understanding is that by doing this the action sheet will be dismissed before the new view is shown as you put the code that opens the new view to the end of the main queue(like what we did for viewDidDisappear, but this happens before the call to viewWillAppear of next view so it works perfect).
Got the solution, and I think it is an Apple bug in iOS 6.0 and above.
In the NavigationController view stack if any view hides the toolbar, e.g. self.navigationController.toolbarHidden = YES, then since that point on all the Views that had already created a toolBar with buttons, will loose the buttons.
So, my solution to this problem was to keep the toolBar in all the Views(had to compromise on the UI, but in my app pikSpeak, the functionality was very important.)
This is an ancient thread, I know, but I just recently ran into this problem. The clue to my solution was that some delay was needed between pushing a new view and closing the action sheet. I changed from using clickedButtonAtIndex to didDismissWithButtonIndex so that the push would occur after the action sheet was gone. Problem solved!

UISegmentedControl within UINavigationController UIToolbar not correctly resizing

I am programmatically adding a UISegmentedControl to a UINavigationController's toolbar (I am in a UITableViewController). I want the segmented control to look decent, not filling the entire bar. Also, I want it to rotate with the view and resize. This should be pretty easy but I think I'm missing something. I actually got it to work, but this is not clean code so I am hoping someone can tell me which settings/methods to use for a "proper" implementation.
Getter:
- (UISegmentedControl*)stockFilterSegmentedControl {
if (!_stockFilterSegmentedControl) {
_stockFilterSegmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"All",#"Holdings", nil]];
[_stockFilterSegmentedControl addTarget:self action:#selector(stockFilterControlPressed:) forControlEvents:UIControlEventValueChanged];
_stockFilterSegmentedControl.selectedSegmentIndex = 0;
_stockFilterSegmentedControl.autoresizingMask = UIViewAutoresizingFlexibleHeight;
CGRect newFrame = _stockFilterSegmentedControl.frame;
newFrame.size.height = self.navigationController.toolbar.frame.size.height * .8;
_stockFilterSegmentedControl.frame = newFrame;
}
return _stockFilterSegmentedControl;
}
Where we insert it:
- (NSArray*)navFooterToolbarArray {
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.stockFilterSegmentedControl];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *refresh = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refresh:)];
return [NSArray arrayWithObjects:flexibleSpace, barButtonItem, flexibleSpace, refresh, nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Stocks";
self.toolbarItems = [self navFooterToolbarArray];
}
And to make it work I had to add:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
NSLog(#"Did autorotate.");
CGRect newFrame = self.stockFilterSegmentedControl.frame;
newFrame.size.height = self.navigationController.toolbar.frame.size.height * .8;
self.stockFilterSegmentedControl.frame = newFrame;
}
What's the right way to do this?
Thanks,
Damien
The answer is actually really simple - you set the segmentedControlStyle on the segmented control to UISegmentedControlStyleBar and it will resize perfectly without any drama. Autoresizing masks work as expected.
Thanks,
Damien
All you should really need is something like:
_stockFilterSegmentedControl.frame = CGRectInset(self.navigationController.toolbar.bounds, 5, 5); //set to toolbar rect inset by 5 pixels
_stockFilterSegmentedControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
You then won't have to do anything when the view rotates, it should just automatically resize to fit because of the autoresizingMask.

Resources