UISegmentedControl setFrame not working - ios

I am trying to add segmented control to tableviewheader. I am using the following code to do that
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"ALL", #"HOUSE", #"SENATE", nil]];
segmentedControl.frame = CGRectMake(24, 0, 272, 30);
[segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue:) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.tintColor = [UIColor grayColor];
[self.view addSubview:segmentedControl];
segmentedControl.selectedSegmentIndex = 0;
self.tableView.tableHeaderView = segmentedControl;
I can't set the frame, no matter what value is put its always 100% wide. How can i set the add 24px margin on left and right ?

That is because you are using the segment control as a tableHeaderView. a UITableViewHeaderView will be always be as wide as your tableView. You can only change the height.

Adding to akshaynhegde answer, you can easily achieve this by adding an extra UIView as parent and add the UISegmentControl to that UIView. In this case the parent UIView will take the whole width of UITableView but not the UISegmentControl.
So following should be the change in your code
UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0,0,320.0,30.0)];
[view addSubview:segmentedControl];
self.tableView.tableHeaderView = view;
It should solve your problem.
Cheers.

First, you are adding segmentedControl on controller view [self.view addSubview:segmentedControl] and then assigning it to table header view
self.tableView.tableHeaderView = segmentedControl;
Which is wrong, you need to create a view with size table header size and then add segmentedControl add on view and assign this view to table header view.
Example
**UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"ALL", #"HOUSE", #"SENATE", nil]];
segmentedControl.frame = CGRectMake(24, 0, 272, 30);
[segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue:) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.tintColor = [UIColor grayColor];
[view addSubview:segmentedControl];
self.tableView.tableHeaderView = view;**

Related

UIImageView size changes

I have navigation bar with custom view on it. UIImageView and UILabel are subviews of titleView. And I add UITapGestureRecognizer to titleView to make it show another UIViewController when the user taps on it. When you tap on titleView other UIViewController opens. But when you click on back button in my titleView size of UIImageView changes. Here is the code
UIView *titleView = [[UIView alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 30)];
UILabel *title = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width/2, 30)];
title.text = _groupName;
[title setTextColor:[self colorFromHexString:#"#474747"]];
[title setFont:[UIFont fontWithName:#"Roboto-Bold" size:16]];
[title setTextAlignment:NSTextAlignmentCenter];
[title setBackgroundColor:[UIColor clearColor]];
_imageView.frame = CGRectMake(0, 0, 30, 30);
_imageView.layer.cornerRadius = 15.0;
_imageView.layer.masksToBounds = YES;
_imageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
_imageView.layer.borderWidth = 0.1;
_imageView.contentMode = UIViewContentModeScaleAspectFit;
title.frame = CGRectMake(title.frame.origin.x+20, title.frame.origin.y, self.view.frame.size.width/2, 30);
UITapGestureRecognizer *recognizer;
recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(titleTapped:)];
titleView.userInteractionEnabled = YES;
[titleView addGestureRecognizer:recognizer];
[titleView addSubview:title];
[titleView setBackgroundColor:[UIColor clearColor]];
[titleView addSubview:_imageView];
self.navigationItem.titleView = titleView;
Here are the images where you can see the changes
I check your code Add clips to bounds and do not need to title frame two times.
_imageView.frame = CGRectMake(0, 0, 30, 30);
_imageView.layer.cornerRadius = 15.0;
_imageView.layer.masksToBounds = YES;
_imageView.clipsToBounds = true;
Rather than setting the frame of the views directly, you might try using Auto Layout; I suspect what's happening is that your custom view is getting re-layed-out after the back button, and it's reverting to the image view's instrinsicSize.
What you could do instead is turn off translatesAutoresizingMaskIntoConstraints on the subviews, and then add constraints to position them, and finally add width and height constraints to the image view.
Using Auto Layout is also recommended if you ever intend to internationalize your app -- if you set up your constraints correctly, then the translated title will fit and you won't have to ever play around with hardcoded values.

Add a view at the top of another view iOS

I need help. I'm designing my UI, and I have been using the properties FRAME and CENTER to layout my views. Both of those are so much helpful to me. I also use the technique of adding my elements as subview of UIViews container.
But, right now, I want to place a UIView at the top of another. Please take a look at my picture. The buttons at the bottom of the screen is already set and is perfect right now, I'm only having a hard time to place my UIView (a container of my textfields) above the button/divider.
I'm only starting in iOS, I think 1 month plus already. I know basics of constraints programmatically but I don't want to use this for now as much as possible.
PS. I make my screen programmatically.
Sample of my code in this screen
// start adding container
UIView *container2 = [[UIScrollView alloc] init];
container2.frame = CGRectMake(0, 0, [TPRConstants screenWidth] * 0.95, heightOfScrollView);
container2.backgroundColor = [UIColor blueColor];
container2.contentSize = CGSizeMake([TPRConstants screenWidth] * 0.95, 250);
[self.view container2];
// stuffs and subviews/textfields inside the container
self.phoneTextField = [[UITextField alloc] init];
_phoneTextField.frame = CGRectMake(0, 200, scrollView.frame.size.width, 50);
_phoneTextField.delegate = self;
_phoneTextField.borderStyle = UITextBorderStyleNone;
_phoneTextField.background = [UIImage imageNamed:#"textfieldLogIn.png"];
_phoneTextField.backgroundColor = [UIColor clearColor];
[_phoneTextField setKeyboardType:UIKeyboardTypeNumberPad];
[container2 addSubview:_phoneTextField];
// add container for divider and log in button
UIView *container = [[UIView alloc] init];
container.frame = CGRectMake(0, 0, [TPRConstants screenWidth], 80);
container.backgroundColor = [UIColor whiteColor];
container.center = CGPointMake([TPRConstants screenWidth] * 0.50, [TPRConstants screenHeight] - container.frame.size.height/2);
[self.view addSubview:container];
// add divider
UIImageView *divider = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, container.frame.size.width, 5)];
divider.image = [UIImage imageNamed:#"dividerCP.png"];
divider.backgroundColor = [UIColor clearColor];
divider.contentMode = UIViewContentModeCenter;
[container addSubview: divider];
// add save login
UIButton *saveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
saveBtn.frame = CGRectMake(0, 0, container.frame.size.width * 0.95, 50);
saveBtn.center = CGPointMake(container.frame.size.width /2 , (container.frame.size.height - saveBtn.frame.size.height/2) - 10 );
[saveBtn addTarget:self action:#selector(saveBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[saveBtn setBackgroundImage:[UIImage imageNamed:#"logoutupCP.png"] forState:UIControlStateNormal];
[saveBtn setTitle:#"Save" forState:UIControlStateNormal];
[saveBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[saveBtn setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[saveBtn setBackgroundImage:[UIImage imageNamed:#"logoutdownCP.png"] forState:UIControlStateHighlighted];
[container addSubview: saveBtn];
In iOS everything in a view is added as a stack i.e on top of each other. So your button will always be on top of the divider as it is added last.
If you try your solution now on several screens, you will find that all of the items will be in different positions.
So you have to add constraints.
The easiest way is via storyboard.
Keep your textfields in one view and your button and divider in another view and add a vertical spacing constraint between both views.
Note: Ofcourse you have to add all the required trailing, leading, top and bottom constraints on each textField and the container views and separator image in view plus center horizontally and vertically constraints to the button.
If you wish to place a UIView at the base of phoneTextField use the maximum y position of phoneTextField for the y origin position of the UIView.
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0,CGRectGetMaxY(phoneTextField.frame)+0,[TPRConstants screenWidth],50);
newView.backgroundColor = [UIColor blueColor];
[self.view addSubview:newView];
Then change the saveBtn frame to make space for newView:
saveBtn.frame = CGRectMake(0, CGRectGetMaxY(newView.frame), container.frame.size.width * 0.95, 50);

UISegmentedControl sticky mode

Is it possible to have a UISegmentedControl stick when it is selected, rather than just act as a normal button? In this sense they would be more like a UISwitch.
Here is my code:
segmentedControl = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:#"1",#"2",#"3",
nil]];
segmentedControl.frame = CGRectMake(0, 0, 120, 30);
[segmentedControl setWidth:40.0 forSegmentAtIndex:0];
[segmentedControl setWidth:40.0 forSegmentAtIndex:1];
[segmentedControl setWidth:40.0 forSegmentAtIndex:2];
[segmentedControl addTarget:self action:#selector(segmentedControlValueDidChange:) forControlEvents:UIControlEventValueChanged];
segmentedControl.selectedSegmentIndex = 0;
segmentedControl.momentary = YES;
self.navigationItem.titleView = segmentedControl;
Here is a video of what is happening: https://www.dropbox.com/s/laijgt3zjdaya1z/Segmented.mov?dl=0
A UISegmentedControl "sticks" when it is selected by default. You're getting the behavior you describe because you set the momentary property to YES. The default is NO, so just delete that line.

Add a sticky view underneath the Navigation Bar

I've seen a few other examples, but I haven't seen anything that actually sticks. What I want is essentially what a tableViewHeader does. I have a tableViewController with a navigation bar. I want to put a view into place that shows some search criteria in a small bar directly below the navbar. But I need it to stick when the user swipes to view the results.
I've tried adding a UIView as a subview to the navigation bar, but it always sits at the top of the Navigation Bar, overlaying everything.
Here's what worked:
// Create a custom navigation view
_navigationView = [[UIView alloc] init];
_navigationView.backgroundColor = [UIColor whiteColor];
_navigationView.frame = CGRectMake(0.0f,
self.navigationController.navigationBar.frame.origin.y + 44.0f,
self.view.frame.size.width,
30.0f);
// Create bottom border for the custom navigation view
_navigationViewBorder = [[UIView alloc] init];
_navigationViewBorder.backgroundColor = [UIColor darkGrayColor];
_navigationViewBorder.tag = 1;
_navigationViewBorder.frame = CGRectMake(0.0f,
self.navigationController.navigationBar.frame.origin.y + 74.0f,
self.view.frame.size.width,
0.5f);
// Add labels for date, results, and the time range
_dateDisplay = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 70, 15)];
[_dateDisplay setFont:[UIFont fontWithName:#"HelveticaNeue" size:13]];
[_dateDisplay setText:#""];
_timeRangeDisplay = [[UILabel alloc] initWithFrame:CGRectMake(98, 0, 135, 15)];
[_timeRangeDisplay setFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:13]];
[_timeRangeDisplay setText:#""];
_resultsDisplay = [[UILabel alloc] initWithFrame:CGRectMake(240, 0, 80, 15)];
[_resultsDisplay setFont:[UIFont fontWithName:#"HelveticaNeue" size:13]];
[_resultsDisplay setText:#""];
[_navigationView addSubview: _dateDisplay];
[_navigationView addSubview: _timeRangeDisplay];
[_navigationView addSubview: _resultsDisplay];
// Add two views to the navigation bar
[self.navigationController.navigationBar.superview insertSubview:_navigationView belowSubview:self.navigationController.navigationBar];
[self.navigationController.navigationBar.superview insertSubview:_navigationViewBorder belowSubview:_navigationView];
Why not add the view to your viewController's view, and set up its constraints so that it sits just below the navigationBar, but above the tableView?
If it's only supposed to be there some of the time, you can animate its constraints to show/hide it.

Programmatically add a UISegmentedControl to a UINavigationBar

How do I PROGRAMMATICALLY add a UISegmentedControl to a UINavigationBar?
I do not want to use a XIB file for this.
I have a UIView with a UITableView that is added as a subview.
I have tried two methods but both are not satisfactory:
1)
self.segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"All",#"Subject",#"Category",#"Finished",nil]];
self.segmentedControl.backgroundColor = [UIColor cloudsColor];
[self.segmentedControl setSelectedSegmentIndex:0];
[self.segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue) forControlEvents:UIControlEventValueChanged];
self.mainView.tableHeaderView = self.segmentedControl;
The reason this first one fails is that in the UITableView, when the user scrolls, the segmented control is scrolled as well! I don't want that to happen. It must stay pinned to the top.
2) Second attempt
UISegmentedControl *statFilter = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Filter_Personnal", #"Filter_Department", #"Filter_Company", nil]];
[statFilter setSegmentedControlStyle:UISegmentedControlStyleBar];
[statFilter sizeToFit];
self.navigationItem.titleView = statFilter;
This removes my title!!! I have a title at the top in the UINavigationBar and this method removes it!!
Here's an example of what I want to accomplish: UISegmentedControl below UINavigationbar in iOS 7
The UISegmentedControl must stay pinned below as part of the UINavigationBar and it must be below the title!
Thanks!
Use tableView:viewForHeaderInSection: (and possibly tableView:heightForHeaderInSection:) instead of tableHeaderView. Set tableStyle to UITableViewStylePlain (this should be the default).
You can use the following code :
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
if (section == 0) {
UIView *viewHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"All",#"Subject",#"Category",#"Finished",nil]];
segmentedControl.backgroundColor = [UIColor cloudsColor];
[segmentedControl setSelectedSegmentIndex:0];
[segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue) forControlEvents:UIControlEventValueChanged];
segmentedControl.frame = CGRectMake(0, 20, viewHeader.frame.size.width, 50);
[viewHeader addSubview:segmentedControl];
return viewHeader;
}
return nil;
}
Hope this helps.
Thanks.
As the other posters have suggested, you could put the segmented control above the table view and under the nav bar, but you'd need to shift down the table view.
...Or, you could add the segmented control as a tableHeaderView.
A third option is to actually add it to the navigation bar. To do that you have to turn it into a navBarItem. Something like this:
UISegmentedControl *statFilter = [[UISegmentedControl alloc]
initWithItems:
[NSArray arrayWithObjects:
#"Filter_Personnal",
#"Filter_Department",
#"Filter_Company",
nil]];
[statFilter setSegmentedControlStyle:UISegmentedControlStyleBar];
[statFilter sizeToFit];
UIBarItem *theBarItem = [[UIBarItem alloc] initWithCustomView: statFilter];
self.navigationItem.rightBarButtonItem = theBarItem;

Resources