Resized UIToolbar refuses to keep its UIBarButtonItem aligned correctly - objective-c

I have a UIToolbar at the top of my view, and it needs to be resized in an animation. The toolbar contains:
A UIBarButtonItem using system item UIBarButtonSystemItemAdd (the '+' button)
A UIBarButtonItem using a custom view (the title)
A UIBarButtonItem using the style UIBarButtonItemStyleBordered (the 'Edit' button)
I am adding these buttons using a spacer between each, which keeps the title in the center:
[toolbar setItems: #[addButton, spacer, titleButton, spacer, editButton] animated:NO];
The toolbar resizes just fine, and the two buttons keep their locations pinned to the outside edges. However, the title button does not stay in the center of the toolbar. Instead, it seems to pin its right edge to the same location, creating a space on its left side. During the animation, this give the impression that it is sliding right.
To be clear, I do want the title bar to keep its same width - I do not want it to expand as the toolbar grows. But I need the title to stay in the center of the toolbar.
Since a UIBarButtonItemis not a UIView, I can't (?) use the autoresizingmask functionality.
How do I keep the title in the center of the toolbar?
Additional Info
This might be because the Add and Edit buttons have different widths - when I add only the title (with a spacer either side), the behavior is correct.

It turns out that I was leaving out a crucial detail. I am manually setting the width of the edit button to 50.
If this is removed, the resizing works as expected. However, I am then unable to control the size of the Edit button, which I like to set to 50 so it matches the one on the navigation bar.
I found a workable solution. Keep the width of the Edit button at 50. Add a fixed separator immediately after the '+' button, and set its width to 18 (50 - the width of the '+' button). This balances the items either side of the title.

I know it's too bad, still you can use custom button as bar button item and use images of Add/Edit button in it. So that you can set the button frames, at any places. So your button won't placed to right most place.
UIButton * addButton = [[UIButton alloc] init];
[addButton setBackgroundImage:<AddimageName> forState:UIControlStateNormal];
UIBarButtonItem * addItem = [[UIBarButtonItem alloc] initWithCustomView:addButton];

Related

UIView in UITableView disappear when becomes firstResponder

In storyboard I have a UITableViewController-->UITableView-->UITableViewSecion--> with static cells
in the same UITableView I also have a UIView that holds a background image and UITextView.
A click on a button shows the UIView and set it's frame, which appears OK, but as soon as I click on the UITextView or make it firstResponder programmatically the keyboard appears and the view disappears
the code when clicking the button
self.myView.frame = CGRectMake(0, self.tableView.contentOffset.y+100, self.tableView.frame.size.width, self.tableView.frame.size.height-100);
self.myView.hidden = NO;
how can I fix this?
Can you copy paste us the code where you add the view to the tableview? Are you doing it with constraints or with frames?
The issue you are having is probably due to the fact the UITableViewControllers automatically shrink the contentSize of the UITableView they hold when the keyboard shows. If you add a UIView to your tableView with addSubview: programmatically, you might need to add a flexible bottom resize mask to make sure when the contentSize shrinks in height, your view stays attached to the top and not the bottom.
Try this on viewDidLoad:
[theViewYouAddedToTableView setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin];

How does a UIAlertView determine the vertical and horizontal center of the view it's within?

I'd like to use this same solution with my UIView to get the same result.
I have a UIView with a UIScrollView. These are embedded in a UINavigationController.
A customer adds an item to their basket and I would like to give them a confirmation message. Right now a little basket UIBarButtonItem updates a title within to show the number of items. This is fine but not every user/customer will notice this.
I don't really like the style of a UIAlertView for this situation. So I'm going to add my own UIView and style it how I want to.
I'm trying to figure out how to get the UIView to show up in the center of the window. Whether the customer is using an iPhone4 or iPhone5.
UIView code:
UIView *confirmationPopup = [[UIView alloc] initWithFrame:CGRectMake(10, 200, 300, 100)];
[confirmationPopup setBackgroundColor:[UIColor redColor]];
// confirmationPopup.center = [confirmationPopup.superview convertPoint:confirmationPopup.superview.center fromView:confirmationPopup.superview.superview];
[[[self navigationController] view] addSubview:confirmationPopup];
The popup view is centered horizontally automatically but not vertically. I've tried to play around with the line you can see I've commented out but it doesn't center the UIView in the center of the window. It appears to be centering it inside the NavBar
Would appreciate some solutions.
Don't hard-code; use auto layout. You might be helped by my custom class for this purpose, an imitation alert view substitute that you can configure however you like. It takes advantage of iOS 7 custom presentation view transitions. (Of course in iOS 8 there will be even more support for this kind of thing, i.e. UIPresentationController.)

iOS7 custom interactive transition, hidden back button reappears as "..." when cancelled

I have a custom interactive transition which requires me to hide the standard back button. Basically, the transition looks like a push from left-to-right rather than the standard right-to-left push we're all familiar with. That's why my back button is on the right side instead.
As you can see from two screenshots I took before and after cancelling pop transition activated by a UIScreenEdgePanGestureRecognizer, once the transition is cancelled there is a "..." where the back button would be.
I'm currently using
self.navigationItem.hidesBackButton = YES;
and I've tried putting it in awakeFromNib, viewDidLoad, viewDidAppear, viewWillAppear methods all without fixing the problem.
So using the power of Reveal.app I investigated the view hierarchy before and after and saw this:
What you see highlighted in each part of the image is what appears to be changing in the area of the nav bar that contains the hidden back button. Before it's a UINavigationButton and then it becomes a UINavigationButtonItem with a UILabel, which must be what contains the "..." and remains like this.
Any help would be much appreciated. I hope this is detailed enough to give a good picture of the issue.
Try creating an empty backbutton first (in the parent viewcontroller before the vc is pushed) - maybe that will prevent the "..." UILabel from being created.
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:#""
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
Another idea: Just set the parent vc title to an empty string.
self.title = #"";

How to position progress spinner inside the title bar of a Mac application

I am trying to place a progress spinner at the right side of the the title bar of the window of my Mac OS X application, but I can't do that with the Interface Builder, as it doesn't let me drag the view inside it.
So, I tried to put it in the title bar programmatically, with the following code inside the applicationDidFinishLaunching method in AppDelegate.m:
loadingSpinner = [[NSProgressIndicator alloc] init];
[loadingSpinner setFrame:NSMakeRect(485, 0, 17, 17)];
[loadingSpinner setStyle:NSProgressIndicatorSpinningStyle];
NSView *titleBarView = [[_window standardWindowButton:NSWindowCloseButton] superview];
[titleBarView addSubview:loadingSpinner];
However, this is putting my progress spinner view at the bottom of the window instead of the title bar. It appears NSMakeRect() is positioning it relative to the bottom of the window, not the top.
If I change the second parameter of NSMakeRect (y position) to something like 370, it puts the loading spinner in the place I want it to be, but obviously when I resize the window vertically, it brings the progress spinner together to the bottom.
I've never seen something like this before. How can I fix that?
P.S.: Also, I don't know if there's a "more right" way to get the title bar view. As you can see, I'm using the superview of the close button view to get it, which seems a bit "dirty".
Randall Brown has some code to put a button in an NSWindow's title bar on his blog. You were on the right track. The superview of the close button is the entire window including the title bar. Its a little less hacky to get it with [[_window contentView] superview].

Rotating UITabBarController Icon

I have an UITabBar in my application. One of the tab bar icons looks like a loading symbol. When the user presses the loading button I want the icon to spin/rotate until the loading is done. Should I use UIImageView to animate or something else? How should I make this happen?
Jacos, unfortunately you cannot do that with the UITabBarController and manipulate the tabBarController's tabBar properties. My best bet would be that you use a UIToolBar and assign a black color and make it appear like a tabBar and have buttons added in them as a subView so that they look like tabBarItems.
Its much more customizable, and you can even provide a scrolling experience and add more buttons to it.
I know this question is 4 years old but I had the same problem and managed to fix it by reading the tutorial in here:
https://medium.com/#werry_paxman/bring-your-uitabbar-to-life-animating-uitabbaritem-images-with-swift-and-coregraphics-d3be75eb8d4d#.bjfpbdnut
The main point is to get the view for desired UITabBarItem and the get the UIImageView from it in viewDidLoad:
UIView *plusView = self.tabBar.subviews[1];
self.plusImageView = plusView.subviews.firstObject;
self.plusImageView.contentMode = UIViewContentModeCenter;
Then in didSelectItem method you can do this:
[UIView animateWithDuration:0.4 animations:^{
[self.plusImageView setTransform:CGAffineTransformMakeRotation(M_PI/4)];
}];
My code only rotate the image view for 45 degrees but you can change as you wish.
I guess you could change the UITabBarItem's icon on a timer, but that seems pretty kludgey. You would have to pre-render each frame of your "loading" icon rather than rotate an ImageView.
Another hackey solution would be to add your ImageView to the UIWindow and move it on top of the TabBarController's TabBar (adding it to the TabBar itself is asking for trouble).
You shouldn't try to animate the actual UIImageView within the UITabBarController. I would take this approach:
Set the image for the relevant tab to nil or a blank image.
Create a UIActivityIndicatorView and add it over the tab bar. Position it over the correct tab.
[self.tabBarController.tabBar addSubview:activityIndicatorView];
When your loading task has completed, restore the normal image to the tab and remove the activityIndicator from the tab bar.