I’m adding a UISegmentedControl right under the NavigationBar in a UITableViewController. This is the code.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationBar = self.navigationController.navigationBar;
UIView *segmentView=[[UIView alloc] initWithFrame:CGRectMake(0, self.navigationBar.frame.size.height, self.navigationBar.frame.size.width, 50)];
[segmentView setBackgroundColor:[UIColor whiteColor]];
segmentView.alpha = 0.95;
self.tabSegmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Favourites", #"All", nil]];
self.tabSegmentedControl.frame = CGRectMake(20, 10, self.navigationBar.frame.size.width - 40, 30);
[self.tabSegmentedControl addTarget:self action:#selector(tabChanged:) forControlEvents:UIControlEventValueChanged];
[segmentView addSubview:self.tabSegmentedControl];
[self.navigationBar addSubview:segmentView];
[self.tabSegmentedControl setSelectedSegmentIndex:1];
}
The view and the SegmentedControl appear on the screen well, but they are not clickable. The selector doesn’t get executed when tapped on the SegmentControl; it doesn’t even switch tabs! In fact, the stuff that is underneath the segmentView (items in the TableView) get clicked when you tap on it. I have tried but failed to understand why this is happening! Any suggestions would be helpful!
You are adding a view below the bounds of its super view. You may see the view however you cannot click it because it is out of bounds. If you set the property of the navigation bar clipsToBounds to YES you should see that the view disappears. What you need to do is add the segment controller to the table view. Here is an example:
- (void)viewDidLoad
{
[super viewDidLoad];
...
[self.view addSubview: self.segmentView]; // need to keep a pointer to segmentView
self.tableView.contentInset = UIEdgeInset(self.segmentView.frame.size.height, 0,0,0);
}
-(void) scrollViewDidScroll:(UIScrollView*) scrollView{
CGRect rect = self.segmentView.frame;
rect.origin = self.tableView.contentOffset;
self.segmentView.frame = rect;
}
Related
I've set the NavigationItem.title in Interface builder for readability but in code i need to do
self.navigationItem.title = SomeThingThatComesFromDB
I've Tried to do this in viewDidLoad and viewDidAppear but in first app launching the title is still the thing that I've set in interface builder.
How I can fix this?
This is my root view controller for application launch and here is the code that I'm using:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
for (Branch *b in [UserManager sharedInstance].branches) {
if ([b.branchId isEqualToString: [UserManager sharedInstance].vendorId]) {
self.title = b.branchName;
}
}
}
You got the following comparison in place to set/update the navigation item's title.
if ([b.branchId isEqualToString: [UserManager sharedInstance].vendorId]) {
self.title = b.branchName;
}
Problem seems to be that the [UserManager sharedInstance].vendorId] variable is not set (yet), when you call the function to update a navigation item's title. As you are able to set it correctly, after the view had disappeared and appeared back again.
The below code illustrates once again how one can set a navigation item's title, as you also did:
If you want to update the title in general for all related navigation elements (UITabbarController tabs, UINavigationController back button etc.) simply use:
self.navigationItem.title = SomeThingThatComesFromDB
https://developer.apple.com/reference/uikit/uiviewcontroller/1621364-title
If you got a dedicated navigation item in your UINavigationController's bar, you could access it the following way (make sure, there is only one to access)
self.navigationItem.rightBarButtonItem.title = SomeThingThatComesFromDB
self.navigationItem.leftBarButtonItem.title = SomeThingThatComesFromDB
Try out below code:
CGRect rect = self.navigationController.navigationBar.frame;
UIView *myView = [[UIView alloc] init];
UILabel *title = [[UILabel alloc] init];
[title setFont:[UIFont systemFontOfSize:18.0]];
title.text = *SomeThingThatComesFromDB*;
title.textColor = [UIColor whiteColor];
CGSize size = [title.text sizeWithAttributes:
#{NSFontAttributeName:
title.font}];
title.frame = CGRectMake(20, 0, size.width, rect.size.height);//40
myView.frame = CGRectMake(0, 0, 40+size.width, rect.size.height);
[myView addSubview:title];
self.navigationItem.titleView = myView;
I have been trying to incorporate a UIView/Toolbar above my keyboard but have had no luck. When I added a toolbar it was scrambled so thus I need to put it into a UIView but the UIView does not want to appear above the keyboard. Code Below:
My Header:
#property (nonatomic, Strong) IBOutlet UITextView *textView;
#property (nonatomic, strong) IBOutlet UIToolbar *TitleBar;
#property (nonatomic, weak) IBOutlet UIView *AddView;
The ViewDidLoad:
- (void)viewDidLoad
{
// observe keyboard hide and show notifications to resize the text view appropriately
/*[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
*/
if ([self respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
// iOS 7
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
} else {
// iOS 6
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
self.attributionTitle.delegate = self;
self.attribution.delegate = self;
textView.scrollEnabled = YES;
// quoteText.layer.borderColor = [UIColor blackColor].CGColor;
// quoteText.layer.borderWidth = 1.0f;
// textView.delegate = self; // code or in IB
[textView becomeFirstResponder];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
The textViewDidBeginEditing:
-(void)textViewDidBeginEditing:(UITextView *)textView
{
self.textView.inputAccessoryView = self.AddView;
}
Here is to show the UIView is connected:
I added the textView.inputAccessoryView = AddView;to the ViewDidLoadthen deleted the view from my storyboard and remade it. Lastly I added the UIView to the bottom black bar.
Adding the inputAccessoryView in textViewDidBeginEditing is probably too late. The input accessory view should be set before that, e.g., in the viewDidLoad method.
Try something like:
-(void)viewDidLoad{
[super viewDidLoad];
UIView
myTextField.inputAccessoryView = [self accessoryViewWithPreviousEnabled:NO nextEnabled:YES];
// more stuff as required...
}
And a method for creating a previous/next button (you'll need to provide your own images for the buttons and implements the previousAccessoryViewButtonTapped: and previousAccessoryViewButtonTapped: methods). It takes two BOOL parameters to indicate if the previous and/or next buttons should be enabled.
#pragma mark - Accessory view methods
-(UIView *)accessoryViewWithPreviousEnabled:(BOOL)previousEnabled nextEnabled:(BOOL)nextEnabled{
previousButton = [UIButton buttonWithType:UIButtonTypeCustom];
previousButton.frame = CGRectMake(10, 2, 60, 30);
[previousButton setImage:[UIImage imageNamed:PREVIOUS_BUTTON] forState:UIControlStateNormal];
previousButton.enabled = previousEnabled;
[previousButton addTarget:self action:#selector(previousAccessoryViewButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
nextButton = [UIButton buttonWithType:UIButtonTypeCustom];
nextButton.frame = CGRectMake(80, 2, 60, 30);
[nextButton setImage:[UIImage imageNamed:NEXT_BUTTON] forState:UIControlStateNormal];
nextButton.enabled = nextEnabled;
[nextButton addTarget:self action:#selector(nextAccessoryViewButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
UIView *transparentBlackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 34)];
transparentBlackView.backgroundColor = [UIColor colorWithRed:0.f green:0.f blue:0.f alpha:0.6f];
UIView *accessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 34)];
[accessoryView addSubview:transparentBlackView];
[accessoryView addSubview:previousButton];
[accessoryView addSubview:nextButton];
return accessoryView;
}
Note this method is hard coded for an iPad in landscape orientation. You need to change it for an iPhone.
The problem is that your self.AddView is already in your interface (because you put it there, in the storyboard). It can't be in two places at once.
I wish to add a UIToolbar programmatically to a view when a user clicks on a button (in my case when they zoom in on a photo).
It seems to work fine when I create the toolbar in the click method and add to the subview but if I create the toolbar in the viewDidLoad method, assign it to an instance variable,and add that instance variable later to the subview on click, nothing appears. The debugger shows that the instance variable is a UIToolbar and is not null. I didn't want to create and destroy the same toolbar on every click so I thought it was better just to keep it as an instance variable that I add and remove from the view as needed. Is this the right approach?
Why is it visible in the one case and not the other.
Setup
#synthesize toolBar;
- (UIToolbar*)createToolbar
{
UIToolbar* toolbar = [[UIToolbar alloc] init];
toolbar.frame = CGRectMake(0, self.view.frame.size.height - 44, self.view.frame.size.width, 44);
UIBarButtonItem *shareButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(sharePhoto:)];
NSArray *buttonItems = [NSArray arrayWithObjects:shareButton,nil];
[toolbar setItems:buttonItems];
return toolbar;
}
This works
- (void) clickMyButton {
toolBar = [self createToolbar];
[self.view addSubview:toolBar];
}
This doesn't show anything
- (void)viewDidLoad
{
[super viewDidLoad];
toolBar = [self createToolbar];
}
- (void) clickMyButton {
[self.view addSubview:toolBar];
}
Why doesn't it work in the latter case
The problem is that when viewDidLoad gets called, it is not guaranteed that the frames for your view and subviews are set. Try calling [self createToolbar] from viewWillAppear or viewDidAppear instead.
I'm trying to customize my NavigationBar with the help of a toolbar.
I've implemented it programmatically as follows:
UIToolbar* tools = [[UIToolbar alloc] initWithFrame: CGRectMake(0, 0, 100, 44.01)];
and then I added it to my NavigationBar. The problem is that I have this ugly effect on the borders:
I've tried to change the y and the height values, with no results.
Do you have any ideas to avoid this?
Thanks in advance, yassa
I wouldn't do it this way.
You can achieve the same effect by adding a view with 2 buttons to the navigationItem.rightBarButtonItem. it is very simple:
// view that will hold the buttons
UIView* container = [[UIView alloc] init];
// create 1 button and add it to the container
UIButton* button = [[UIButton alloc] init........];
[container addSubview:button];
//create 2 button and add it to the container
button = [[UIButton alloc] init.........];
[container addSubview:button];
// now create a Bar button item
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:container];
// set the nav bar's right button item
self.navigationItem.rightBarButtonItem = barButtonItem;
I partially agree with previous answers and comments.
The solution you suggested works fine for custom buttons. But what if I want to implement standard Edit button?
Access to the standard buttons/icons is through the UIBarButtonItem class, not UIButton. And you can't add UIBarButtonItem objects to a UIView.
After many research on the web, I've found the solution that completely cover my requirement. The toolbar must be created in the following way:
UIToolbar *tools = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 95.0f, 44.01f)];
tools.tintColor = self.navigationController.navigationBar.tintColor;
tools.barStyle = -1;
And this is the result:
Hope it helps!
yassa
Or you can do it in this way.
Just create new subclass of UIToolbar like this
#interface MyToolbar : UIToolbar
#end
#implementation MyToolbar
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.clearsContextBeforeDrawing = YES;
}
return self;
}
- (void)drawRect:(CGRect)rect {
// do nothing
}
- (void)dealloc {
[super dealloc];
}
#end
And use it as normal UIToolbar. I don't know why but it just works.
In my app, I have a split screen in which the detail view is a scrollview. I have 5 tables which are subviews of my scrollview in which 3 table views are side by side on top and 2 table views are side by side on bottom
I have already implemented a way in which when I click any of the rows of any of the table in the scrollview, that view disappears and another view zooms into its position.
I write the following code in the didSelectRowAtIndexPath in the middle table subview,
CGFloat xpos = self.view.frame.origin.x;
CGFloat ypos = self.view.frame.origin.y;
self.view.frame = CGRectMake(xpos+100,ypos+150,5,5);
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:2];
self.view.frame = CGRectMake(xpos,ypos,220,310);
[UIView commitAnimations];
[self.view addSubview:popContents.view];
popContents is the view I need to zoom into to the view previously occupied by that particular table view and that happens correctly.
However the problem that I am facing is that since there is another table subview in the side, if I increase the frame size to say 250 or so, the part of the zoomed in view gets hidden by the tableview on the side ( as its as if a part of the zoomed in view goes under the tableview on the side).
Is there anyway to correct this so that my zoomed in view would not get hidden by the tableviews on its sides?
I hope I have explained my problem correctly...
UPDATE:
Here is the code I am using for adding the subviews for the scrollview
// Scroll view
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 30, 1000, 740)];
scrollView.contentSize = CGSizeMake(1000, 700);
scrollView.delegate = self;
scrollView.scrollEnabled = YES;
scrollView.showsHorizontalScrollIndicator = YES;
scrollView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
[self.view addSubview:scrollView];
aView = [[aViewController alloc] initWithNibName:#"aViewController" bundle:nil];
aView.view.frame = CGRectMake(10, 25, 220, 310);
[aView loadList:objPatients];
[scrollView addSubview:aView.view];
bView = [[bViewController alloc] initWithNibName:#"bViewController" bundle:nil];
bView.view.frame = CGRectMake(10, 350, 220, 310);
[bView loadList:objPatients];
[scrollView addSubview:bView.view];
cView = [[cViewController alloc] initWithNibName:#"cViewController" bundle:nil];
cView.view.frame = CGRectMake(240, 25, 220, 310);
[cView loadList:objPatients];
[scrollView addSubview:cView.view];
dView = [[dViewController alloc] initWithNibName:#"dViewController" bundle:nil];
enView.view.frame = CGRectMake(240, 350, 220, 310);
[enView loadList:objPatients];
[scrollView addSubview:dView.view];
eView = [[eViewController alloc] initWithNibName:#"eViewController" bundle:nil];
eView.view.frame = CGRectMake(470, 25, 220, 310);
[eView loadList:objPatients];
[scrollView addSubview:eView.view];
say for example, I add the code for didSelectRowAtIndexPath in cViewController subview...
This is a guess since I would need to know how your table views are added to the scroll view, but the middle table view was probably added before the one on the side. Views are "stacked" in the order they're added with the last one on top. You'll need to get the scroll view to move the middle view to the front with this method
- (void)bringSubviewToFront:(UIView *)view
The best way to do that would be to create a protocol for the table views and make the scroll view the delegate. The method would be something like this
- (void) moveAViewToFront: (MyTableView *) aTableView
{
[self.view bringSubviewToFront: aTableView.view];
}
You would then call the delegate method before setting up the animation.
Edited
After a little more thought I realized that the subviews have a reference to their superview so this bit of code should provide an idea on how to solve the problem. I created a test app which has a view controller which adds two sub views. The view controller header file is MoveSubviewViewController.h
#import <UIKit/UIKit.h>
#interface MoveSubviewViewController : UIViewController
{
}
#end
and it's implementation is
#import "MoveSubviewViewController.h"
#import "MoveableSubview.h"
#implementation MoveSubviewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Create two overlapping subviews. The blue subview will start at the top of
// the frame and extend down two thirds of the frame.
CGRect superviewFrame = self.view.frame;
CGRect view1Frame = CGRectMake( superviewFrame.origin.x, superviewFrame.origin.y,
superviewFrame.size.width, superviewFrame.size.height * 2 / 3);
MoveableSubview *view1 = [[MoveableSubview alloc] initWithFrame: view1Frame];
view1.backgroundColor = [UIColor blueColor];
[self.view addSubview: view1];
[view1 release];
// The green subview will start one third of the way down the frame and
// extend all the to the bottom.
CGRect view2Frame = CGRectMake( superviewFrame.origin.x,
superviewFrame.origin.y + superviewFrame.size.height / 3,
superviewFrame.size.width, superviewFrame.size.height * 2 / 3);
MoveableSubview *view2 = [[MoveableSubview alloc] initWithFrame: view2Frame];
view2.backgroundColor = [UIColor greenColor];
[self.view addSubview: view2];
[view2 release];
}
#end
The subview class is MoveableSubview with another simple header
#import <UIKit/UIKit.h>
#interface MoveableSubview : UIView
{
}
#end
and implementation
#import "MoveableSubview.h"
#implementation MoveableSubview
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Move this view to the front in the superview.
[self.superview bringSubviewToFront: self];
}
#end
The thing to do is to add the
[self.superview bringSubviewToFront: self];
line before setting up the animation.