iOS Calc X position to place elements on a View - ios

I want to add a Label and an Image in titleView of my NavigationItem. I am adding UILabel and UIImageView to a UIView and setting it as titleView of the navigation Item. Things are being added, but I am not able to calculate the length of label and place image next to it.
My code is :-
// Title Name + Image
UIView *titView = [[UIView alloc] initWithFrame:self.navigationItem.titleView.bounds];
self.navigationItem.titleView = titView;
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(-10, -20, 150, 30)];
title.text = #"Bunny ";
[title setTextColor:[UIColor orangeColor]];
[titView addSubview:title];
float x2 = 30; //+ title.bounds.size.width;
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"return" ]];
img.frame = CGRectMake(x2, -20, img.bounds.size.width, 30);
[titView addSubview:img];
I am looking for some way to calc the width text and set accordingly the width of the label. Right now I have set the width of the label as 150. And secondly, calc the x position to place the image just next to the label.
Tried many ways, but nothing works as expected. How can I achieve this ? Can you he give some guidelines such that regardless of length of text of label, things works as expected and UIView gets placed in the center of navigation item.
Any help is highly appreciated. Thanks.

You can call
[title sizeToFit];
after setting its properties and it will size itself to match the contained string.
Set the imageViews x origin to
CGRectGetMaxX(title.frame) + desiredSpacing;
And it could help to subclass UIView to achieve the final results by overwriting layoutSubviews and placing your views there, since the titleView's frame can be adjusted by the navigationBar...basically like this:
#implementation TitleView{
UILabel *_titleLabel;
UIImageView *_img;
}
- (id)initWithTitle:(NSString *)title andImage:(UIImage *)image
{
self = [super init];
if (self) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.text = title;
[_titleLabel setTextColor:[UIColor orangeColor]];
[_titleLabel sizeToFit];
[self addSubview:_titleLabel];
_img = [[UIImageView alloc] initWithImage:image];
[self addSubview:_img];
}
return self;
}
- (void)layoutSubviews{
CGFloat spacingBetweenTextAndImage = 0;
CGFloat width = CGRectGetWidth(_titleLabel.frame)+CGRectGetWidth(_img.frame)+spacingBetweenTextAndImage;
CGFloat x = (CGRectGetWidth(self.bounds)-width)/2;
_titleLabel.frame = CGRectMake(x, (CGRectGetHeight(self.bounds)-CGRectGetHeight(_titleLabel.bounds))/2, CGRectGetWidth(_titleLabel.bounds), CGRectGetHeight(_titleLabel.bounds));
x+=CGRectGetWidth(_titleLabel.bounds)+spacingBetweenTextAndImage;
_img.frame = CGRectMake(x, (CGRectGetHeight(self.bounds)-CGRectGetHeight(_img.bounds))/2, CGRectGetWidth(_img.bounds), CGRectGetHeight(_img.bounds));
}
#end
use in your viewController:
UIView *titleView = [[TitleView alloc] initWithTitle:#"Bunny" andImage:[UIImage imageNamed:#"return" ]];
self.navigationItem.titleView = titleView;

Related

Keep subviews as original dimensions in UIStackView

Currently I'm trying to make 3 buttons in a horizontal group of 3 that have equal spacing
UIStackView * menuButtons = [[UIStackView alloc] initWithFrame:CGRectMake(0, 0, 60, 16)];
menuButtons.axis = UILayoutConstraintAxisHorizontal;
menuButtons.alignment = UIStackViewAlignmentBottom;
menuButtons.spacing = 6;
menuButtons.distribution = UIStackViewDistributionEqualSpacing;
UIButton* btnOne = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
UIButton* btnTwo = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
UIButton* btnThree = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
[menuButtons addArrangedSubview:btnOne];
[menuButtons addArrangedSubview:btnTwo];
[menuButtons addArrangedSubview:btnThree];
ive noticed when I inspect the frame of the button views after adding them to my stackview programatically, they all show different sizes than originally set, when I expect them all to still be 16
ie: btnOne CGSize(17, 16), btnTwo CGSize(23.5, 23,5), btnThree CGSize(21.3, 21.3)
I don't understand why this happens, and I've tried all the distributions but I can't figure this out when I'm not setting the frames on these views anywhere else
Here is an example - based on your code - using auto-layout constraints.
Note that you do NOT need to specify width and height constraints for your UIStackView, as it will expand as needed to fit the arranged subviews.
If you do set a width constraint, you'll end up with (likely) unexpected results, because you've also specified fixed-width spacing of 6.
So, you would want either:
width constraint + UIStackViewDistributionEqualSpacing, or
no width constraint + default distribution + .spacing = 6
Hope this helps...
//
// StackTestViewController.m
//
// Created by Don Mag on 6/24/17.
//
#import "StackTestViewController.h"
#interface StackTestViewController ()
#end
#implementation StackTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupMenuButtons];
}
- (void)setupMenuButtons {
// instantiate a UIStackView
UIStackView *menuButtons = [[UIStackView alloc] init];
// horizontal
menuButtons.axis = UILayoutConstraintAxisHorizontal;
// spacing between arranged views
menuButtons.spacing = 6;
// instantiate 3 buttons
UIButton* btnOne = [UIButton new];
UIButton* btnTwo = [UIButton new];
UIButton* btnThree = [UIButton new];
// give 'em background colors so we can see them
btnOne.backgroundColor = [UIColor redColor];
btnTwo.backgroundColor = [UIColor greenColor];
btnThree.backgroundColor = [UIColor blueColor];
// for each button,
// tell it not to use Autoresizing Mask
// set width and height constraints each to 16
for (UIButton *b in #[btnOne, btnTwo, btnThree]) {
[b setTranslatesAutoresizingMaskIntoConstraints:NO];
[b.widthAnchor constraintEqualToConstant:16.0].active = YES;
[b.heightAnchor constraintEqualToConstant:16.0].active = YES;
}
// add them to the Stack View
[menuButtons addArrangedSubview:btnOne];
[menuButtons addArrangedSubview:btnTwo];
[menuButtons addArrangedSubview:btnThree];
// add the Stack View to self view
[self.view addSubview:menuButtons];
// tell Stack View not to use Autoresizing Mask
[menuButtons setTranslatesAutoresizingMaskIntoConstraints:NO];
// set X and Y position for the Stack View (just using 80,80 for this example)
[menuButtons.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:80.0].active = YES;
[menuButtons.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:80.0].active = YES;
}
#end

Adding an Image with a Title in a UINavigationController

I would like to show a small icon next to the title in my UINavigationController.
Through the magic of Photoshop, like this:
I know I need to create a new view and build the image and title into it. Here is what I am doing:
In viewDidLoad in the UINavigationController view controller, I call the method
[self setTitleBar];
Which calls this method:
- (void) setTitleBar {
CGRect navBarFrame = self.navigationController.navigationBar.frame;
//UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(navBarFrame.origin.x, navBarFrame.origin.y, (leftButtonFrame.origin.x + leftButtonFrame.size.width) - rightButtonFrame.origin.x, navBarFrame.size.height)];
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(navBarFrame.origin.x, navBarFrame.origin.y,self.view.frame.size.width,navBarFrame.size.height)];
titleView.backgroundColor = [UIColor clearColor];
CGPoint tvCenter = CGPointMake(titleView.frame.size.width/2, titleView.frame.size.height/2);
UIImage * icon = [UIImage imageNamed:#"star"];
UIImageView *iconView = [[UIImageView alloc] initWithImage:icon];
iconView.frame = CGRectMake(0, 0, icon.size.width, icon.size.height);
UILabel *title = [[UILabel alloc] init];
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor whiteColor];
title.textAlignment = NSTextAlignmentCenter;
title.text = #"SOME TITLE";
title.frame = CGRectMake(0, 0, 100, titleView.frame.size.height);
[title sizeToFit];
iconView.center = CGPointMake(tvCenter.x - (icon.size.width/2), tvCenter.y);
[titleView addSubview:iconView];
[titleView addSubview:title];
self.navigationItem.titleView = titleView;
}
My logic in the titleView is: Get the left most button's frame and get the right most buttons frame. THEN do some math to figure out how big the view can be. That should be the titleView's frame size.
However, I can't seem to get it to work. If I plug in a frame size of 0,0,100,40; then it shows the frame but everything is squished together. But you see it. I know that 100 should be dynamic to ensure that the title is shown.
But I can't seem to figure it out.
Any help?
You can place objects on the Navigation Controller View, as subviews.
- (void) setTitleBar {
//Let's say your icon size is 20
int starSize = 20;
//Now you'll have to calculate where to place the ImageView respect the TextSize (for this you'll need to know the text and font of your UINavigationItem title)
CGSize textSize = [#"SOME TITLE" sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"navfontname" size:15]}];
UIImageView *startImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.navigationController.view.frame.size.width/2 - textSize.width/2, self.navigationController.view.frame.size.height/2 - starSize/2, starSize,starSize)];
startImageView.image = [UIImage imageNamed:#"star"];
[self.navigationController.view addSubview:startImageView];
}

iOS - Resize UISwitch in UINavigationBar

I am trying to use a UISwitch in my UINavigationBar. I want a smaller switch than the default, so I am scaling the size down with anonymousSwitch.transform = CGAffineTransformMakeScale(0.55, 0.55); When I do this, the switch shrinks, but I cannot figure out how to align it vertically with the other elements in my UINavigationBar.
Here is what it looks like currently:
Ideally, the UISwitch would be spaced away from the 175 UILabel as much as the X UIButton is spaced from the 175 UILabel, and the UISwitch would be in a straight line with the rest of the elements in the UINavigationBar. I tried doing switch.center = CGPointMake(switch.center.x, shareButton.center.y), but this did not affect the placement of the UISwitch at all.
Is there any way for me to position the switch like I want?
I had the same problem.
I tried to solve it and came up with this solution.
I don't think it's a perfect solution and might not work on every iOS-Version.
First you need to subclass UISwitch like this:
#interface UICustomSwitch : UISwitch
#property (assign, nonatomic) CGFloat scale;
#end
#implementation UICustomSwitch
- (void)setFrame:(CGRect)frame {
CGFloat superview_height = self.superview.frame.size.height;
frame.origin.y = (superview_height - frame.size.height * _scale) / 2;
[super setFrame:frame];
}
#end
The second thing to do is to create and setup your UICustomSwitch like that:
UICustomSwitch* switch = [UICustomSwitch new];
switch.transform = CGAffineTransformMakeScale(0.75, 0.75);
switch.scale = 0.75;
UIBarButtonItem* button = [[UIBarButtonItem alloc] initWithCustomView:switch];
To create a bigger space between the 175 and the switch you could just add another UIBarButtonItem between the 175 and the switch. E.g. a fixed spacer with a specific width.
Like i said, i don't think it's a flawless solution.
In my tests it worked.
Another solution by 0yeoj (but a little bit adjusted -> always centered for every navigationBar height, for toolbars it's the same, just use self.navigationController.toolbar.frame.size.height ):
UIView* switch_container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, self.navigationController.navigationBar.frame.size.height)];
UISwitch* switch = [[UISwitch alloc] initWithFrame:switch_container.bounds];
switch.transform = CGAffineTransformMakeScale(0.75, 0.75);
switch.center = CGPointMake(switch_container.bounds.size.width/2, switch_container.bounds.size.height/2);
[switch addTarget:self action:#selector(action:) forControlEvents:UIControlEventValueChanged];
[switch_container addSubview:switch];
UIBarButtonItem* button = [[UIBarButtonItem alloc] initWithCustomView:switch_container];
self.navigationItem.rightBarButtonItem = button;
Have you tried moving switch with another transform method like,
CGAffineTransformMakeTranslation(xValue, yValue);
also you can merge two transform together and give that transform to switch like,
CGAffineTransform scale= CGAffineTransformMakeScale(0.55, 0.55);
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 10);
anonymousSwitch.transform = CGAffineTransformConcat(scale, translate);
This is the code i tested..
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *xbutton = [UIButton buttonWithType:UIButtonTypeCustom];
xbutton.frame = CGRectMake(0, 6, 35, 35);
xbutton.backgroundColor = [UIColor redColor];
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
UISwitch *switchButton = [[UISwitch alloc] init];
switchButton.frame = CGRectMake(0, 0, 35, 35);
switchButton.transform = CGAffineTransformMakeScale(0.55, 0.55);
switchButton.center = CGPointMake(containerView.frame.size.width/2, containerView.frame.size.height/2);
[containerView addSubview:switchButton];
UIBarButtonItem *additionalButton = [[UIBarButtonItem alloc] initWithCustomView:containerView];
UIBarButtonItem *xBarButton = [[UIBarButtonItem alloc] initWithCustomView:xbutton];
//rearrange it if necessary
NSArray *arrayButton = [NSArray arrayWithObjects: xBarButton, additionalButton, nil];
self.navigationItem.leftBarButtonItems = arrayButton;
}.
hmm... i haven't DOWNGRADED yet to yosemite so i dont have ios8.3 here this code works perfectly for me though..

rightView property error in iOS7 for UITextField

I am setting an imageView as the rightView of a textfield. This is my code:
UITextField *textField = [[UITextField alloc]initWithFrame:controlFrame];
[textField setBorderStyle:UITextBorderStyleRoundedRect];
[textField setBackgroundColor:[UIColor whiteColor]];
CGRect imageViewFrame = CGRectMake(controlFrame.origin.x + controlFrame.size.width - 20,controlFrame.origin.y, 15.0,controlFrame.size.height-10);
UIImage *image = [UIImage imageNamed:#"arrow.png"];;
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[imageView setBackgroundColor:[UIColor clearColor]];
[imageView setFrame:imageViewFrame];
[textField setRightViewMode:UITextFieldViewModeAlways];
textField.rightView = imageView;
Its working perfect on iOS 6.1 devices
But in iOS 7 devices
Any Solution for this?
Thanks in advance
Was just working on this myself and used this solution:
- (CGRect) rightViewRectForBounds:(CGRect)bounds {
CGRect textRect = [super rightViewRectForBounds:bounds];
textRect.origin.x -= 10;
return textRect;
}
This will move the image over from the right by 10 instead of having the image squeezed up against the edge in iOS 7.
Additionally, this was in a subclass of UITextField, which can be created by:
Create a new file that's a subclass of UITextField instead of the default NSObject
Add a new method named - (id)initWithCoder:(NSCoder*)coder to set the image
- (id)initWithCoder:(NSCoder*)coder {
self = [super initWithCoder:coder];
if (self) {
self.clipsToBounds = YES;
[self setRightViewMode:UITextFieldViewModeUnlessEditing];
self.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"textfield_edit_icon.png"]];
}
return self;
}
You may have to import #import
Add the rightViewRectForBounds method above
In Interface Builder, click on the TextField you would like to subclass and change the class attribute to the name of this new subclass
There's another faster option, no need to subclass your uitextfield. There's an example
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 10, 6)];
[imageView setImage:[UIImage imageNamed:#"grey_filter.png"]];
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 6)];
[paddingView addSubview:imageView];
Just create a View bigger than your image with your padding. Add your UIImageView and then put it as left/right view in your textfield.

UITableView center a UIImage and UILabel in viewForHeaderInSection

I wanna center vertically and horizontally an image inside of HeaderSection and a label inside of the image. But I don't have a clear idea about how make that. My code is:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIImage *image = [UIImage imageNamed:#"bg_title_category"];
UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)] autorelease];
UILabel *sectionTitle = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)] autorelease];
UIImageView *sectionHeaderBG;
sectionTitle.text = #"Trial"; //[[tableDataSource objectAtIndex: section] objectForKey: #"Title"];
sectionTitle.textAlignment = NSTextAlignmentCenter;
sectionTitle.font = [UIFont fontWithName:#"Helvetica-Bold" size:14];
sectionTitle.textColor = [UIColor whiteColor];
sectionTitle.shadowColor = [UIColor colorWithWhite:0 alpha:0.4];
sectionTitle.shadowOffset = CGSizeMake(1, 1);
sectionTitle.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
sectionHeaderBG = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _tableView.frame.size.width/2, image.size.height)];
sectionHeaderBG.image = [UIImage imageNamed:#"bg_title_category"];
[headerView addSubview:sectionHeaderBG];
[headerView addSubview:sectionTitle];
return headerView;
}
But this code not center anything... Thanks in advance!
The problem is that you're creating headerView with origin (0,0) and it's size the same one as your image; then you're adding all of your views to headerView. When the table view adds this header view it will not be centered, rather it'll placed at (0,0).
What I'd suggest you to do is to create headerView with the same origin (0,0) but with the width of your tableView and the height depening on you. Let's just assume for now the height will be the same as your image plus 10px at the top and bottom just to give it some margin. Then you can add your UIImageView and UILabel inside headerView and center them with respect to it. It'd be something like this:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIImage *image = [UIImage imageNamed:#"bg_title_category"];
// Create your headerView with the same width as the tableView and a little taller than the image
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0, tableView.bounds.size.width, image.size.height + 20)]; //10px top and 10px bottom. Just for illustration purposes.
// Create the image view
UIImageView *sectionHeaderBG = [[UIImageView alloc] initWithImage:image];
// Now center it and add it to headerView
sectionHeaderBG.center = CGPointMake(headerView.bounds.size.width/2, headerView.bounds.size.height/2);
[headerView addSubview: [sectionHeaderBG autorelease]];
// Now it's turn of the label. Again I suggest using the tableView's width
UILabel *sectionTitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)];
// Now center it. You could even do this when creating it's frame
sectionTitle.center = CGPointMake(headerView.bounds.size.width/2, headerView.bounds.size.height/2);
// do the rest of the configuration for your label...
// and add it to headerView
[headerView addSubview: [sectionTitle autorelease]];
return [headerView autorelease];
}
Hope this helps!

Resources