Graphical Bugs while programmatically creating UILabel, UITextField, etc - ios

I programmatically created a login view and a table view.
Under certain circumstances which i cannot reproduce there occur some strange visual bugs:
Text with some letters having a different font size than others
A button where the border is not initially shown but only if you click on it. In the same case, the border of the button can be shown in a UITextField instead of the place holder ( see screenshot )
A label showing up not in the right place, but in the above mentioned textfield, upside down ( i did not manage to screenshot this one yet )
Below, i added two screenshots with most of the app blacked out, only showing the bugs:
http://uppix.net/b/c/4/dd1e41acb94b7d0ad8eb173772e97.png
http://uppix.net/b/f/2/a5993440c07753b851701068330be.png
Here you can see that text gets mixed with different font sizes.
This errors occur not regularly or reproduce-able.
I added the code of the login screen below:
// Implement loadView to create a view hierarchy programmatically, without
// using a nib.
- (void)loadView {
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
UIFont* font = [UIFont systemFontOfSize:14];
float midLine = 100.0;
float height = 30.0;
float borderY = 70.0;
float borderX = 10.0;
float width = 320.0 - borderX * 2.0;
float paddingX = 10.0;
float paddingY = 5.0;
CGRect usernameLabelRect = CGRectMake(borderX, borderY, midLine, height);
CGRect usernameFieldRect = CGRectMake(borderX + midLine + paddingX, borderY,
width - midLine - paddingX - 40 , height);
CGRect passwordLabelRect = CGRectMake(borderX, borderY + height + paddingY,
midLine, height);
CGRect passwordFieldRect = CGRectMake(borderX + midLine + paddingX,
borderY + height + paddingY,
width - midLine - paddingX - 40, height);
CGRect loginButtonRect = CGRectMake(borderX + 40,
borderY + height*2 + paddingY*2, width - 80,
height);
//CGRect warningRect = CGRectMake(borderX,
// borderY * height * 3.0 + paddingY *3.0,
// width, height);
CGRect warningRect = CGRectMake(borderX, 175, width, 40);
UILabel* usernameLabel = [[UILabel alloc] initWithFrame:usernameLabelRect];
usernameLabel.textAlignment = UITextAlignmentRight;
usernameLabel.font = font;
usernameLabel.text = #"Username:";
UILabel* passwordLabel = [[UILabel alloc] initWithFrame:passwordLabelRect];
passwordLabel.textAlignment = UITextAlignmentRight;
passwordLabel.font = font;
passwordLabel.text = #"Password:";
usernameField = [[UITextField alloc] initWithFrame:usernameFieldRect];
[usernameField setBorderStyle:UITextBorderStyleRoundedRect];
//[usernameField setPlaceholder:#"<Username>"];
usernameField.font = font;
usernameField.autocapitalizationType = UITextAutocapitalizationTypeNone;
usernameField.autocorrectionType = UITextAutocorrectionTypeNo;
passwordField = [[UITextField alloc] initWithFrame:passwordFieldRect];
passwordField.font = font;
[passwordField setBorderStyle:UITextBorderStyleRoundedRect];
//[passwordField setPlaceholder:#"<Password>"];
passwordField.autocapitalizationType = UITextAutocapitalizationTypeNone;
passwordField.autocorrectionType = UITextAutocorrectionTypeNo;
passwordField.secureTextEntry = YES;
loginButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
loginButton.frame = loginButtonRect;
[loginButton setTitle: #"Einloggen" forState:UIControlStateNormal];
[loginButton setTitleColor:[UIColor blackColor]
forState:UIControlEventTouchDown];
loginButton.contentVerticalAlignment =
UIControlContentVerticalAlignmentCenter;
loginButton.contentHorizontalAlignment =
UIControlContentHorizontalAlignmentCenter;
[loginButton addTarget:self action:#selector(OnLoginClicked:)
forControlEvents:UIControlEventTouchUpInside];
[loginButton setBackgroundColor:[UIColor clearColor]];
warningLabel = [[UILabel alloc] initWithFrame:warningRect];
warningLabel.font = font;
warningLabel.numberOfLines = 3;
warningLabel.text =
#"Wenn Sie die Applikation jetzt schließen, so werden Ihre Logindaten verworfen.";
[myView addSubview:usernameLabel];
[myView addSubview:passwordLabel];
[myView addSubview:usernameField];
[myView addSubview:passwordField];
[myView addSubview:loginButton];
[myView addSubview:warningLabel];
/*
[usernameLabel release];
[passwordLabel release];
[usernameField release];
[passwordField release];
[loginButton release];
[warningLabel release];
*/
self.view = myView;
[myView release];
}

I can't work all of your screen positioning in my head, but it looks to me like many of your fields overlap : is this intentional ? Maybe that is the cause ? I normally create views in code, but this might be one case for IB!
You haven't shown any code for the table view, however I've seem similar issues before where you add subviews to a cell, then next time the cell is deQueued with DequeueReusableCell you add subviews again without checking if they are there or clearing them. This results in all sorts of overlaps just like the first screenshot.

The problem was that i called UIKit messages from Not-The-Main-Thread, which causes all kinds of graphical problems. Solved it by using performSelectorOnMainThread: in several places in my code =)

Related

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];
}

CGRectMake( ) - y reference looks totally wrong

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)];

IOS UIButton Target doesnot working

here is my code
for (NSString *message in self.messages) {
label = [[UIButton alloc] initWithFrame:CGRectZero];
[label setTitle:message forState:UIControlStateNormal];
//label.titleLabel.text = message;
label.tag = i;
[label addTarget:self action:#selector(gototest:) forControlEvents:UIControlEventTouchDown];
CGSize size = [message sizeWithFont:label.titleLabel.font];
CGFloat width = size.width + kPADDING;
label.frame = CGRectMake(xPos, 0.0, width, self.frame.size.height);
[self addSubview:label];
i++;
xPos += width;
}
-(void)gototest:(UIButton*)sender
{
int tag = sender.tag;
NSLog(#"test %#",#"ccc ");
}
So nothing happen when I click on the buttons.
Note that the class is extend from UIScrollView and also I have to create a marquee with different news and when I click in any of this news, I have to go to the detail of the chosen new.
Please help me
UIControlEventTouchDown should not be the problem, it works too. Can you try the following
label = [UIButton buttonWithType:UIButtonTypeCustom];
instead of
label = [[UIButton alloc] initWithFrame:CGRectZero];
Too I suspect the following line too
label.frame = CGRectMake(xPos, 0.0, width, self.frame.size.height);
the frame you are setting confirm it is correct, in normal usage it may appear that your UIButton is visible, but it may not. Try put
label.clipsToBounds=YES;
and check, if your UIButton is actually visible, that might be the reason your action not working..
UPDATE
Ok, As per my understanding, as you are saying, you are trying to create Marquee, and the original implementation had UILabel and you are trying to change that to UIButton. Let change few things as the code below,
for (NSString *message in self.messages) {
label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = message;
label.tag = i;
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gototest:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[label addGestureRecognizer:tapGestureRecognizer];
label.userInteractionEnabled = YES;
CGSize size = [message sizeWithFont:label.font];
CGFloat width = size.width + kPADDING;
label.frame = CGRectMake(xPos, 0.0, width, self.frame.size.height);
[self addSubview:label];
i++;
xPos += width;
}
And your action
-(void)gototest:(UITapGestureRecognizer*)sender
{
int tag = sender.view.tag;
NSLog(#"test %#",#"ccc ");
}
Use touch event "UIControlEventTouchUpInside" intends of "UIControlEventTouchDown".
It will works fine :
[label addTarget:self action:#selector(grottiest:)
forControlEvents:UIControlEventTouchUpInside];
Edit :
label = [[UIButton alloc] initWithFrame:CGRectMake(xPos, 0.0, 100, 100)];
[label setTitle:message forState:UIControlStateNormal];
//label.titleLabel.text = message;
label.tag = i;
[label addTarget:self action:#selector(gototest:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:label];
Your code is working fine with single button. The problem is somewhere else..
UIButton *label = [[UIButton alloc] initWithFrame:CGRectZero];
[label setTitle:#"Click" forState:UIControlStateNormal];
//label.titleLabel.text = message;
label.tag = 0;
[label addTarget:self action:#selector(gototest:) forControlEvents:UIControlEventTouchDown];
label.frame = CGRectMake(0,0,100,50);
[self addSubview:label];
Replace:
label = [[UIButton alloc] initWithFrame:CGRectZero];
with
UIButton *label = [[UIButton alloc] initWithFrame:CGRectZero];

Issue with vertical scrolling in UIScrollView

I am using following code to create my view.
self.percentage_ans_view = [[UIView alloc] init];
float height = 0.0f;
for (int i=0; i < answer_set.count; i++) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20,height ,280,50 )];
[label setText: [self.answer_set objectAtIndex:i]];
[label setTextAlignment:NSTextAlignmentLeft];
[label setBackgroundColor:[UIColor clearColor]];
label.textColor = [UIColor colorWithRed:0.2941f green:0.4666f blue:0.9549f alpha:1.0f];
label.lineBreakMode = NSLineBreakByWordWrapping;
label.numberOfLines = 0;
[label sizeToFit];
// label.tag = 5000 + i;
label.userInteractionEnabled = YES;
label.font = [UIFont fontWithName:#"Arial" size:14.0f] ;
[self.percentage_ans_view addSubview:label];
height += label.frame.size.height;
NSLog(#"LABEL SIZE height : %f & width : %f",label.frame.size.height,label.frame.size.height);
NSLog(#"ans:%#", [self.answer_set objectAtIndex:i]);
UIButton *ans_btn = [UIButton buttonWithType:UIButtonTypeCustom];
ans_btn.frame = CGRectMake(0 - 5, height, (width * 3)+ 20,40 );//CGRectMake(0 - 5, 45 + (i * 80), (width * 3)+ 20,40 )
[ans_btn setTitle:[NSString stringWithFormat:#"%d%#",percent,#"% "] forState:UIControlStateNormal];
ans_btn.titleLabel.font = [UIFont boldSystemFontOfSize:20];
ans_btn.titleLabel.textColor = [UIColor whiteColor];
ans_btn.backgroundColor = [UIColor colorWithRed:0.2941f green:0.4666f blue:0.9549f alpha:1.0f] ;
// ans_btn.frame = frame; your desired size
ans_btn.clipsToBounds = YES;
height += ans_btn.frame.size.height;
[self.percentage_ans_view addSubview:ans_btn];
}
[self.swipe addSubview:self.percentage_ans_view];
Here self.swipe is UIScrollView which is not scrolling vertically. So i am not able to see last two labels and button of my view. What i am doing wrong ?
Set the contentSize property of your UIScrollView properly (basically the width/height of the content that can be displayed in the scroll view without scrolling), set the pagingEnabled property of the scroll view to YES, and then add your view that you want to scroll as a subview of the UIScrollView.
As long as the lenght of the subview is more than the width of the contentSize you specified, it should scroll vertically.
If this scrollView is an IBOutlet, check if the autolayout is disabled for the parent view.
If you are using auto layout, you should add constrains to the scrollViews subviews, that will fully specify it's contentSize.

How can I know which view I am clicking? And why the button no reaction?

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.

Resources