How do I add a UISegmentedControl to a UITableView?
Similar to the image found here:
http://cdn.imore.com/sites/imore.com/files/styles/large/public/field/image/2012/08/iHomework-for-iPhone-managing-assignments-and-tasks.jpg
I would like to have a UISegmentedControl that sticks underneath the navigation bar.
This is what I've tried so far:
In my viewDidLoad method, I've created a UISegmentedControl
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"One", #"Two", nil]];
segmentedControl.frame = CGRectMake(50, 0, 220, 100);
[segmentedControl addTarget:self action:#selector(segmentedControlHasChangedValue:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segmentedControl];
However, the segmented control overlaps with the tableview itself.
EDIT
Additionally,I would like to create this uisegmentedcontrol fully programmatically as I don't want to use a nib file.
self.tableView.tableHeaderView = segmentedControl;
If you want it to obey your width and height properly though enclose your segmentedControl in a UIView first as the tableView likes to mangle your view a bit to fit the width.
Related
In my UISegmentedControl I wish to show icons instead of text.
I cannot find any indication what the height of these icons should be. I would prefer to supply properly sized icons instead of having the OS resize them for me.
So, when calling
[[UISegmentedControl alloc] initWithItems:#[icon1, icon2]];
what should the sizes of these icons be?
You can give the segmentControl a bigger frame.
UISegmentedControl *test = [[UISegmentedControl alloc] initWithItems:[#icon1, #icon2]];
test.frame = CGRectMake(90, 90, 200, 80);
test.backgroundColor = [UIColor blueColor];
[self.view addSubview:test];
itemsArray should be the items images array.
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;**
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;
I have a couple of upcoming designs to implement. These designs have some overlap that I want to make general for my project. The app should be navigation based and all have company brand image in the navbar, but the navbar should be larger than it originally is, with the title below the main image.
The top blue part is the same brand image throughout the project, the below gray part is where the title label resides, which means that the title label should be adjusted. I want to be able to use setTitle for my view controllers. The back button should be centered in the blue part, so slightly adjusted towards the top of the screen, instead of centered in the navigation bar.
I've gotten some inspiration from the following questions and a category would be a nice way to go or am I in the wrong here? Do you have any suggestions?
Objective-C: Background image and title in Navigation Bar
UINavigationBar custom title position
Changing the UINavigationBar background image
You can do like this in the viewDidLoad method
UIView *navbar = self.navigationBar;
navbar.translatesAutoresizingMaskIntoConstraints = NO;
[navbar addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:[navbar(80)]" // custom height
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(navbar)]];
[navbar addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"[navbar(320)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(navbar)]];
self.widthConstraint = navbar.constraints[1]; // width is the 2nd constraint
For adjusting back button use custom back button image and position an icon within image as you wish. Use [UINavigationBar appearance] to set custom back button.
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:#"IconBack"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage new]];
For adjusting titles use corresponding methods of UINavigationBar and UIBarButtonItem appearances.
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:10 forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -10) forBarMetrics:UIBarMetricsDefault];
As per this link : https://stackoverflow.com/a/7688626/667586
Create a UINavigationBar Category with a custom sizeThatFits.
#implementation UINavigationBar (customNav)
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(self.frame.size.width,70);
return newSize;
}
#end
For Title, use
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))
On a project I did something like this:
self.navigationItem.titleView = [MyClass getTitleView:parameter];
self.navigationController.navigationBar.frame = CGRectMake(0.0, 0.0, 320.0, self.navigationItem.titleView.frame.size.height);
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
.
.
.
// 44 is the default height of a nav bar
if (self.navigationItem.titleView.frame.size.height > 44) {
[backButton setImageEdgeInsets:UIEdgeInsetsMake(-self.navigationItem.titleView.frame.size.height/4, 0, self.navigationItem.titleView.frame.size.height/4, 0)];
}
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
The method [MyClass getTitleView:parameter] gives you the view you want with the labels and images you need, then you readjust the navigation bar and buttons, the hardcoded constants on the button insets are just to center the button vertically because our nav bar also had an extra label at the bottom, also you might want to fix the width of the bar, ours supports portrait only.
We have this code on the viewWillAppear: method because only one class uses it but a category sounds reasonable if you don't have a base ViewController to subclass from.
Not sure if it works in all cases, but here is a starting point.
I noticed that UINavigationBar height could be changed via autolayout constraints. By default bar's autoresizing mask is translated into constraints. I turned it off and added width and height constraints manually. Width constraint depends on orientation and should be changed when orientation transition occurs. All changes are performed in UINavigationController subclass.
#interface NavigationController ()
#property (strong, nonatomic) NSLayoutConstraint *widthConstraint;
#end
#implementation NavigationController
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *navbar = self.navigationBar;
navbar.translatesAutoresizingMaskIntoConstraints = NO;
[navbar addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:[navbar(80)]" // custom height
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(navbar)]];
[navbar addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"[navbar(320)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(navbar)]];
self.widthConstraint = navbar.constraints[1]; // width is the 2nd constraint
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
CGSize size = [UIScreen mainScreen].bounds.size;
self.widthConstraint.constant =
UIInterfaceOrientationIsLandscape(toInterfaceOrientation)
? size.height
: size.width;
[UIView animateWithDuration:duration animations:^{
[self.navigationBar layoutIfNeeded];
}];
}
#end
For adjusting back button use custom back button image and position an icon within image as you wish. Use [UINavigationBar appearance] to set custom back button.
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:#"IconBack"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage new]];
For adjusting titles use corresponding methods of UINavigationBar and UIBarButtonItem appearances.
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:10 forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -10) forBarMetrics:UIBarMetricsDefault];
The scene currently in view is "RunTestViewController". As you can see there is a segment control embedded.
Everything runs fine, the segmentcontrol works, however when I scroll the segment control stays put and end up on top of the cells.
Is there a way embed the segment controller into the tableview so it moves with the table?
Thanks,
**EDIT:
------------------**
I have added this code in the viewDidLoad section:
UIView *headerView = [[UIView alloc] init ];
[headerView addSubview:resultsSegment];
self.tableView.tableHeaderView = headerView;
This allows the segmentcontrol to move when the table view scrolls, which is great, however the segment control is now unclickable, any ideas?
You want to embed a view or control into a tableview so that it scrolls with the tableview? You should put the view or control into the tableview header.
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,200)];
UISegmentedControl *segmentControl = [[UISegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 200, 44)];
[headerView addSubview:segmentControl];
self.tableView.tableHeaderView = headerView;