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.
Related
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);
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.
I am facing a really strange issue:
I am instantiating multiple UIImageView inside a for loop with the method CGRectMake, the y origin I am giving seems to be totally wrong on the screen:
Here is my code:
- (void)makeTheView
{
self.view.backgroundColor = [UIColor whiteColor];
UIScrollView *header = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 100)];
header.backgroundColor = [UIColor colorWithRed:254/255.0f green:255/255.0f blue:213/255.0f alpha:1.0f];
[self.view addSubview:header];
for (int i = 0; i < 10; i++) {
UIImageView *avatar = [[UIImageView alloc] initWithFrame:CGRectMake(5 + i * 75, 5, 70, 70)];
avatar.image = [UIImage imageNamed:#"bo_pic_baby5.jpg"];
[avatar.layer setCornerRadius:8.0];
avatar.layer.masksToBounds = YES;
NSLog(#"%f", avatar.frame.origin.y);
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, avatar.frame.size.width, 20)];
title.backgroundColor = [UIColor colorWithRed:148/255.0f green:148/255.0f blue:148/255.0f alpha:0.5f];
title.font = [UIFont fontWithName:#"Arial" size:15];
title.text = #"崔健";
title.textAlignment = NSTextAlignmentCenter;
title.textColor = [UIColor whiteColor];
[avatar addSubview:title];
[header addSubview:avatar];
}
}
According to this code avatar is within header at 5px from the top of header.
But the following is what I obtain visually:
note: when the white area begin, the header view stopped
This is not a real issue since I can reevaluate my frames like this :
CGRectMake(5 + i * 75, - 20, 70, 70)
but it looks really weird, and I am quite sure I am missing something totally trivial here...
I think this will be fixed by:
self.automaticallyAdjustsScrollViewInsets = NO;
Since iOS 7, view controllers automatically adjust scroll view insets so that the scroll view content is not hidden behind the navigation bar because it expects scroll views to start at the top of the screen.
However, the usual solution is to just set the scrollview frame.origin.y to 0.
Your Code is Absolutely Correct , As you are Adding the scrollview on (0,64) Position , So 64 will be count from Bottom of the Navigation Bar, If you want it on top (Just Below the Navigation bar), Change this declaration to as below :
UIScrollView *header = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 100)];
I'm trying to add a scrollview to my UIView, and put a label, textview, image on it but the scroll bar doesn't show up and I can't scroll.
//faux view
UIView* fauxView = [[[UIView alloc] initWithFrame: CGRectMake(10, 10, 200, 200)]autorelease] ;
[self.bgView addSubview: fauxView];
//the new panel
self.bigPanelView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.bgView.frame.size.width, self.bgView.frame.size.height)]autorelease];
self.bigPanelView.center = CGPointMake( self.bgView.frame.size.width/2, self.bgView.frame.size.height/2);
self.bigPanelView.backgroundColor = self.initialBackgroundColor;
UIScrollView * scroll = [[UIScrollView alloc] initWithFrame:self.bigPanelView.bounds];
[scroll setContentSize:CGSizeMake(200, 200)];
[self.bigPanelView addSubview:scroll];
scroll.showsVerticalScrollIndicator = YES;
// add label
UILabel *lblTitle = [[[UILabel alloc] initWithFrame:CGRectMake(0, 25, self.bgView.frame.size.width, 46)]autorelease];
// If I change the 25 to 235 the label will come under the screen but still I cannot scroll.
lblTitle.textAlignment = NSTextAlignmentCenter; // Align the label text in the center
lblTitle.backgroundColor = [UIColor clearColor];
lblTitle.text = self.initialTitle;
lblTitle.textColor = self.initialTitleColor;
lblTitle.font = [UIFont systemFontOfSize:31];
[scroll addSubview: lblTitle];
You have to make the scrollview's contentSize larger than the view:
[scroll setContentSize:CGSizeMake(200, 200)];
needs to be something like:
[scroll setContentSize:CGSizeMake(400, 400)];
Of course, make that the size of the content of whatever you're going to put the scroll view, and that way, it only scrolls if needs to.
For Scrolling - The scrollView contentSize should be larger then the scrollView frame.
I am designing a viewcontroller which have several button bar, each bar canbe clicked and show a content view.like:
http://i.stack.imgur.com/m5V4Q.png
When I click the buttonbar, it's frame will expand bigger, and you can see the content in it(which is a button).
First, a bar button(320*30 size) and a contentView is a set, they are subviews of listview. And several listview makes the whole view.
Second, when I click it, the list view will expand from 320*30 to 320*180, the contentview in it will expand from 300*0 to 300 * 130(20 pixel of margin). and I set the clipsToBounds of contentview to Yes to make sure the content in contentview won't show when the frame height is 0.
Now,the click can show the contentview exactly as I want. But here is a problem: I can't click the button in it, and I tried to set their userInteractionEnabled to yes . And even I set the contentview as user-defined,which I set the view's userInteractionEnabled to yes and overwrite the touchbegin function to show a alertView. Those test are failed, no reaction found. And I checked and sure that there shouldn't be any view covered it.
What's the reason might be?
The code of setup the list view is:
NSArray *array = [titleArray objectAtIndex:i];
NSString *ShenSuoTitle = [array objectAtIndex:0];
NSString *ShenSuoContent = [array objectAtIndex:1];
UIView *listView = [[UIView alloc] initWithFrame:CGRectMake(0, totalHeight, 320, ShenSuoViewHeight)];
[listView setBackgroundColor:[UIColor blackColor]];
[listView setTag:[[NSString stringWithFormat:#"%d",(i+1)] intValue]];
[self.scrollView addSubview:listView];
totalHeight = totalHeight + 1 + ShenSuoViewHeight;
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, ShenSuoViewHeight)];
[titleView setBackgroundColor:[UIColor whiteColor]];
[titleView setTag:[[NSString stringWithFormat:#"%d1",i+1] intValue]];
[listView addSubview:titleView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTag:[[NSString stringWithFormat:#"%d2",i+1] intValue]];
[btn setFrame:CGRectMake(0, 0, 320, ShenSuoViewHeight)];
[btn addTarget:self action:#selector(reSetFrame:) forControlEvents:UIControlEventTouchUpInside];
[titleView addSubview:btn];
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(5, 12, 30, 30)];
img.image = [UIImage imageNamed:#"list_ico.png"];
[img setTag:[[NSString stringWithFormat:#"%d3",i+1] intValue]];
[titleView addSubview:img];
NSLog(#"img:%f,%f",img.frame.origin.y,img.frame.size.height);
UILabel *labTitle = [[UILabel alloc] initWithFrame:CGRectMake(35, 15, 100, 25)];
labTitle.textColor = [UIColor blackColor];
labTitle.backgroundColor = [UIColor clearColor];
labTitle.font = [UIFont boldSystemFontOfSize:15];
labTitle.text = ShenSuoTitle;
[titleView addSubview:labTitle];
NSLog(#"labTitle:%f,%f",labTitle.frame.origin.y,labTitle.frame.size.height);
//add a label for selected
UILabel *selectedLabel = [[UILabel alloc] initWithFrame:CGRectMake(214, 14, 86, 21)];
selectedLabel.textColor = [UIColor grayColor];
//selectedLabel.alpha = 0.75;
selectedLabel.backgroundColor = [UIColor clearColor];
selectedLabel.text = #"All";
selectedLabel.font = [UIFont boldSystemFontOfSize:15];
[selectedLabel setTag:[[NSString stringWithFormat:#"%d5",i+1] intValue]];
[titleView addSubview:selectedLabel];
NSLog(#"selectedLabel:%f,%f",selectedLabel.frame.origin.y,selectedLabel.frame.size.height);
UIView *content = [[UIView alloc] initWithFrame:CGRectMake(10, 10 + ShenSuoViewHeight, 300, 0)];
content.backgroundColor = [UIColor grayColor];
UILabel *testLa = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];
testLa.text = #"Label";
UIButton *testBut = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testBut.frame = CGRectMake(0, 40, 100, 30);
testBut.titleLabel.textColor = [UIColor greenColor];
testBut.titleLabel.text = #"Button";
content.tag = [[NSString stringWithFormat:#"%d4",i+1] intValue];
[content addSubview:testLa];
[content addSubview:testBut];
content.clipsToBounds = YES;
[testLa release];
[listView addSubview:content];
[content release];
[labTitle release];
[img release];
[titleView release];
[listView release];
the code handle the click to make the list view expands is:
UIView *titleView = (UIView *)[self.view viewWithTag:[[NSString stringWithFormat:#"%d1",i+1] intValue]];
titleView.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:0.9];
UIView *listView = (UIView *)[self.view viewWithTag:[[NSString stringWithFormat:#"%d",i+1] intValue]];
listView.frame = CGRectMake(0, totalHeight, 320, ShenSuoViewHeight);
totalHeight = totalHeight + 1 + 20 + 180 + ShenSuoViewHeight;
UIView *content = [self.view viewWithTag:[[NSString stringWithFormat:#"%d4",i+1] intValue]];
content.frame = CGRectMake(10, 10 + ShenSuoViewHeight, 300, 180);
UIImageView *img = (UIImageView*)[self.view viewWithTag:[[NSString stringWithFormat:#"%d3",i+1] intValue]];
img.image = [UIImage imageNamed:#"list_ico_d.png"];
I'm not sure I follow your situation exactly, and some code would be nice. To answer your question though, the reason is most likely that the touch is being intercepted elsewhere. It may also be that you just forgot to connect an action method to the button. Try using breakpoints or NSLogs to see what methods are being triggered and which aren't.
Thanks a lot. It is due to my fault. The code of expanding the bar which setting the listview's frame is wrong, it should add in the expanded height. This leads the visual is ok but the clicking not be handled.
So this problem closed.