I want to create a header toolbar like shown in the image below. It is from the web view of the Twitter app.
I created a UIToolbar and put it at the top. Then I inserted the Buttons left and right and changed the Identifier to get the correct symbols.
My problem is the text in the middle. I create a UIBarButtonItem and placed it between the buttons. Here is my Problem.
How to I achieve that the UIBarButtonItem title does not overlap the left and the right button when the title is to long?
In my case:
How do I achieve that the title gets ... at the end if it gets to long?
How can I set the sub title?
How can I achieve that the button is not clickable, i.e., has color black?
Edit Using the answer from #Viral Savaj: Here is what it looks like:
To test if the title is too long, you should use character counting. Let myHeaderBarString represent your string for the title. You will probably have to adjust this number to find the right length before it gets truncated.
if count(myHeaderBarString) > 40 {
myHeaderBarString = myHeaderBarString.substringToIndex(40)
myHeaderBarString.append("...")
}
For a subtitle, you should insert a new view with a UILabel inside it.
You can set custom title view to the navigation bar like this way.
//To hide default back button
self.navigationItem.hidesBackButton=YES;
//Title View for Navigation
UIView *navTitle1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
[navTitle1 setBackgroundColor:[UIColor lightGrayColor]];
//Left View button and separator
UIButton *crossBarButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[crossBarButton setTitle:#"X" forState:UIControlStateNormal];
//Center view with two buttons and seprator for them
UILabel *topTitle = [[UILabel alloc] initWithFrame: CGRectMake(50,0, self.view.bounds.size.width-100, 22)];
topTitle.text = #"text";
topTitle.font = [UIFont systemFontOfSize:25];
topTitle.lineBreakMode = NSLineBreakByCharWrapping;
UILabel *subTitle = [[UILabel alloc] initWithFrame: CGRectMake(50,20, self.view.bounds.size.width-100, 18)];
subTitle.text = #"subtext";
subTitle.font = [UIFont systemFontOfSize:18];
subTitle.lineBreakMode = NSLineBreakByCharWrapping;
//Right button with seprator before that
UIButton *uploadBarButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width-50, 0, 44, 44)];
[uploadBarButton setTitle:#"U" forState:UIControlStateNormal];
[navTitle1 addSubview:crossBarButton];
[navTitle1 addSubview:topTitle];
[navTitle1 addSubview:subTitle];
[navTitle1 addSubview:uploadBarButton];
self.navigationItem.titleView = navTitle1;
You can refer THIS for more detail.
Use BarButtonItem.customView, it works.
let button = UIButton(frame: CGRectMake(0,0,200,40))
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.setTitle("gogogogogogogogoogogogogogogogogogoogo", forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.addTarget(self, action: "showMessage:", forControlEvents: .TouchUpInside)
let rightBarButtonItem = UIBarButtonItem()
rightBarButtonItem.customView = button
self.navigationItem.rightBarButtonItem = rightBarButtonItem
Related
I have 2 navigation bar items, but the size is too big, I want to make it smaller. how do i manage the size of them? should i edit them in the interface builder or should i manage them programmatically in viewDidLoad ?
I had given all the image size needed in the image asset, but it doesnt work
You have to take custom view for the navigationItem
take a button and give frame as per your requirement
set an image to the button
assign a button as customView to UIBarButtonItem
try following code ..it may help you
let customButton = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 30, height: 30))
customButton.setImage(UIImage.init(named:"imageName"), for: .normal)
self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(customView: customButton)
Thank you
To use resized images in bar buttons, bellow code will help you:
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
[customView setBackgroundColor:[UIColor clearColor]];
CGRect iconRect = CGRectMake(((40 - 28)/2), ((40 - 28)/2), 28, 28);
UIImageView *imageIcon = [[UIImageView alloc] initWithFrame: iconRect];
imageIcon = [UIImage imageNamed:imageName];
[customView addSubview: imageIcon];
UIButton *tranparentButton = [UIButton buttonWithType:UIButtonTypeCustom];
[subscribeButton setFrame:CGRectMake(0, 0, 40, 40)];
[customView addSubview: tranparentButton];
[tranparentButton addTarget:self action:#selector(cancelButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithCustomView: customView];
self.navigationItem.rightBarButtonItem = rightBarButton;
Thanks
I'm using Xcode 8.0.
I add a custom left barbutton to my NavBar:
UIImage * imageNormal = [UIImage imageNamed:#"InfoIcon"];
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(testPressed ) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:imageNormal forState:UIControlStateNormal];
// set the frame of the button
button.frame = CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height);
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height)];
[view addSubview:button];
// set the barbuttonitem to be the view
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.leftBarButtonItem = barButtonItem;
Here what I got:
unfortunately my button is not centered because the Nav bar has a custom image higher than the standard. But if I press the info Icon it works.
If I change the icon position with this line of code:
button.frame = CGRectMake(0, -30, imageNormal.size.width, imageNormal.size.height);
I got the right positioning:
But in this case the bar button is not anymore clickable, and I don't get why this is happening.
As workaround I attach a gesture to the view:
UITapGestureRecognizer *_tapOnVideoRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.revealViewController action:#selector(revealToggle:)];
[view addGestureRecognizer:_tapOnVideoRecognizer];
it works, but the tap is on the view and not on the button so that the changing status of the button when pressed is not working.
#JakubKnejzlik from https://stackoverflow.com/a/12554715/1320479
suggests:
This can be fixed by subclassing the wrapper view (superview of button, custom view of uibarbuttonitem) and overriding the hittest method to return button accordingly.
But I have no idea how to do it
I have a navigation controller with a custom back button on the left. I do this programmatically so this is not an auto-layout issue. My problem is that the navigation controller title is not centered, it is going off the right side of the screen. I remember seeing a fix for this awhile back dealing with setting some type of fixed space as the right bar button item, but I cannot seem to find anything similar to this now.
Could someone tell me how to set the navigation controller title to centered and if the title is too big for its space, set nav bar title to fix its font size to fit the width of title space. This all needs to be done programmatically, thanks!
In navigation controller, by default, the view controller A that pushes current view controller B. The title of A will show up in backBarButton in view controller B.
The navigation controller title not centered is also because the previous view controller title is too long.
To counter that, use this in viewWillAppear of view controller A:
self.navigationItem.backBarButtonItem= UIBarButtonItem(title: "",
style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
self.navigationItem.backBarButtonItem!.title = ""`
Thanks so much for the answers, they were useful in helping my find a solution. My solution was to use the titleView property of the navigation controller. It sets the title without having to go through the trouble of making a custom UIView and the setAdjustsFontSizeToFitWidth property solved my problem of the font size being too big. I've added a little extra formatting to make it look nice, but I won't post it since it doesn't have to do with my question. Here is the code I am using:
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, self.view.frame.size.width-60, self.navigationController.navigationBar.frame.size.height)];
titleLabel.text = #"This is my big, long title";
titleLabel.textColor = [UIColor blackColor];
titleLabel.textAlignment = UITextAlignmentCenter;
[titleLabel setAdjustsFontSizeToFitWidth:YES];
self.navigationItem.titleView = titleLabel;
You have to add custom view in the navigation
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 0, 150, 44)];
UILabel *titleLabel=[[UILabel alloc] initWithFrame:CGRectMake(10, 165,370, 25)];
titleLabel.text=#"Home";
titleLabel.textColor=[UIColor whiteColor];
[view addSubview:titleLabel];
[self.navigationController.navigationBar addSubview:view];
Try out this, it would help you and it is tested.
Objective C version
UIButton * button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
[button addTarget:self action:#selector(yourSelector:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"<" forState:UIControlStateNormal];
button.titleEdgeInsets = UIEdgeInsetsMake(-3, -15, 3, 15);
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc]initWithCustomView:button];
self.navigationItem.leftBarButtonItem = leftItem;
Swift version
button = UIButton(frame: CGRectMake(0, 0,50, 50))
button?.addTarget(self, action: "backButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
button?.setTitle("<", forState: .Normal)
button?.titleLabel?.font = UIFont(name: kFontHelveticaNeueRegular, size: 30)
button?.titleEdgeInsets = UIEdgeInsetsMake(-3, -15, 3, 15)
button?.setTitleColor(UIColor.whiteColor(), forState: .Normal)
var leftItem = UIBarButtonItem(customView: button!)
controller.navigationItem.leftBarButtonItem = leftItem
Add following method in your Utilities class
+ (void)setTitle:(NSString *)title forViewController:(UIViewController *)viewController {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setTextAlignment:NSTextAlignmentCenter];
[label setTextColor:[UIColor whiteColor]];
[label setFont:[UIFont boldSystemFontOfSize:18]];
[label setText:title];
[label sizeToFit];
viewController.navigationItem.titleView = label;
}
Use across view controllers as follows
[Utilities setTitle:#"Title for View Controller" forViewController:self];
Add both leftbarbutton and Rightbarbutton . Usually back button exist . If you add an empty right bar button , title will get centered.
I want to set a text on the position of leftBarButtonItem/rightBarButtonItem in the UINavigationBar. You have to use UIBarButtonItem, but you can put different UIView objects into it. First I tried to use a label, but that doesn't work. The code is in C#, but you should get the idea:
UILabel textLabel = new UILabel();
textLabel.Text = "My custom text which should be displayed in navigation bar";
UIBarButtonItem customBarButtonItem = new UIBarButtonItem (textLabel);
NavigationItem.RightBarButtonItem = customBarButtonItem;
The label is not shown. If I use a button it seems to work (except the styling has to be adapted).
UIBarButtonItem customBarButtonItem = new UIBarButtonItem ("My custom text which should be displayed in navigation bar", UIBarButtonItemStyle.Plain,null);
NavigationItem.RightBarButtonItem = customBarButtonItem;
Why isn't it possible to use a UILabel? What is the correct way of showing a text like a header in a UIBarButtonItem?
Edit:
My current findings are:
Either set the title of UIBarButtonItem or set the frame of UILabel (thanks to Anbu.Karthik for this).
change
UILabel testLabel = new UILabel();
testLabel.frame=CGRectMake(0, 0, 200, 21);
testLabel.Text = "yuhu";
UIBarButtonItem test = new UIBarButtonItem (testLabel.text);
Change this line of code UIBarButtonItem test = new UIBarButtonItem (testLabel);
UILabel testLabel = new UILabel();
testLabel.Text = "yuhu";
testLabel.frame=CGRectMake(x, y, width, height);
//change this line
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc] initWithCustomView:testLabel];
NavigationItem.RightBarButtonItem = test;
Use this
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
What is the proper way to change height of navigation bar?
I need to create custom title in navigation bar, it should contains two UILabels one above other. The Title should be resized to fit those UILabels.
Should I override sizeThatFits: method in my custom TitleView, would other buttons correctly change to fit that size? How can I change a size of NavigationBar?
That is what I need to create using latest SDK features.
Create the following class category (you can create it in your implementation file):
#import "objc/runtime.h"
#interface UINavigationBar (CustomHeight)
- (void)setHeight:(CGFloat)height;
#end
static char const *const kHeight = "Height";
#implementation UINavigationBar (CustomHeight)
- (void)setHeight:(CGFloat)height
{
objc_setAssociatedObject(self, kHeight, #(height), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)height
{
return objc_getAssociatedObject(self, kHeight);
}
- (CGSize)sizeThatFits:(CGSize)size
{
CGSize newSize;
if (self.height) {
newSize = CGSizeMake(self.superview.bounds.size.width, [self.height floatValue]);
} else {
newSize = [super sizeThatFits:size];
}
return newSize;
}
#end
And after that, simply call [self.navigationController.navigationBar setHeight:100.0] in your viewDidLoad or where you need it. Works in both iOS 7.1 and 8.1.
Disclaimer: Any alteration of the API and its functions is prone to future issues with new OS releases! Apple does not intend to allow us to change the navigation bar height (except for some rare instances) so use any solution wisely after assessing the risks vs advantages.
Looking at that design that you posted, I don't have the impression that the bar is really higher than the standard 44pt. Please note that starting with iOS7 the status bar is integrated into the same bar and the 20pt of the status bar is added to the total height.
IMHO, the only problem you need to solve is to stack the title/subtitle, and that can be easily done with a custom titleView, as Kampai has demonstrated.
Add custom view for both navigation title and navigation right bar button.
Here how you can add title view like above.
// Custom view for navigation title.
UIView *customTitleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 22)];
label1.text = #"Stasik";
label1.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:20];
label1.textAlignment = NSTextAlignmentCenter;
[customTitleView addSubview:label1];
UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(0, 22, 100, 22)];
label2.text = #"Stasik iPhone";
label2.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:16];
label2.textAlignment = NSTextAlignmentCenter;
label2.textColor = [UIColor darkGrayColor];
[customTitleView addSubview:label2];
self.navigationItem.titleView = customTitleView;
// Custom view for right navigation.
UIButton *upButton = [UIButton buttonWithType:UIButtonTypeCustom];
upButton.frame = CGRectMake(0, 0, 20, 44);
[upButton setImage:[UIImage imageNamed:#"up"] forState:UIControlStateNormal];
[upButton addTarget:self action:#selector(upButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *upButtonBarItem = [[UIBarButtonItem alloc] initWithCustomView:upButton];
UIButton *downButton = [UIButton buttonWithType:UIButtonTypeCustom];
downButton.frame = CGRectMake(0, 0, 20, 44);
[downButton setImage:[UIImage imageNamed:#"down"] forState:UIControlStateNormal];
[downButton addTarget:self action:#selector(downButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *downButtonBarItem = [[UIBarButtonItem alloc] initWithCustomView:downButton];
// Remove trailing space for right view.
UIBarButtonItem *nagativeSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
nagativeSpace.width = -11;
self.navigationItem.rightBarButtonItems = #[nagativeSpace, upButtonBarItem, downButtonBarItem];
// Left item
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 40, 44);
[backButton setImage:[UIImage imageNamed:#"back"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
// Remove leading space for left view.
nagativeSpace.width = -15;
UIBarButtonItem *backButtonBarItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItems = #[nagativeSpace, backButtonBarItem];
OutPut:
Arrow images are different than OP's requirement but it serves layout for navigation views.
From above code make change in nagativeSpace.width value to arrange buttons with accurate distance from left as well as right margins.