UILabel is not shown in custom UIView screen - ios

Here is how I implemented my custom UiView
In myView.h file
#interface myView : UIView
{
NSString *message;
}
...
#property (nonatomic, retain) UILabel *messageLabel;
...
#end
In myView.m file
This function will instantiate myView and add the message label to it
+ (id) initWithText:(NSString *) text
{
screenBounds = [[UIScreen mainScreen] bounds];
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
self = [super initWithFrame:CGRectMake(0, statusBarFrame.size.height, screenBounds.size.width, 40)];
if (self)
{
[self setBackgroundColor:[UIColor redColor]];
message = [text copy];
_messageLabel = [[UILabel alloc]initWithFrame:[self frame]];
[_messageLabel setText:message];
[_messageLabel setAdjustsFontSizeToFitWidth:YES];
[_messageLabel setTextAlignment:NSTextAlignmentJustified];
[_messageLabel setTextColor:[ UIColor blackColor]];
[self addSubview:_messageLabel];
}
return self;
}
Later I add myView as a subclass to the visible view in my screen. When I run the app I can see the red coloured myView but message label is not displayed in it.

When you init your UILabel with self.frame, you have to consider the value inside its parent view.
Maybe your 2nd parameter: y = statusBarFrame.size.height is to high and that's why your label is out your view ?
Try to init your label with CGRectMake(0,0,self.frame.width, self.frame.height)

check if text you are setting in label is blank and
_messageLabel = [[UILabel alloc]initWithFrame:self.frame];

I Tried this code And it worked. Sure that you didn't set other parameters to your UILabel somewhere else ? These are the differences with your code :
I replaced your '+' by '-' for the method.
I changed uilabel frame for initialisation.
Added a background color to label (only to check).
-(id)initWithText:(NSString *)text
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
self = [super initWithFrame:CGRectMake(0, statusBarFrame.size.height, screenBounds.size.width, 40)];
if (self) {
[self setBackgroundColor:[UIColor redColor]];
NSString *message = [text copy];
UILabel *_messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[_messageLabel setText:message];
[_messageLabel setBackgroundColor:[UIColor lightTextColor]];
[_messageLabel setAdjustsFontSizeToFitWidth:YES];
[_messageLabel setTextAlignment:NSTextAlignmentJustified];
[_messageLabel setTextColor:[ UIColor blackColor]];
[self addSubview:_messageLabel];
}
return self;
}

Before: I used to call initWithText() & show() from backgroundOP.m file where I do background operations. These functions are always executed in separate threads.
Now: I moved the call to initWithText() & show() method inside a delegate method and added the delegate to presenting UIViewController i.e., inside the viewController.m file in which I want my view to appear. Now I call this delegate from another file (i.e., from backgroundOP.m) and problem is solved. Now both UIView and UILabel is visible in screen.
But I don't understand why adding the UIView from the background thread function shows only the UIView and not its contents/subviews.
In my show() function, I use this dispatch queue to add the myView to presenting key window. Like below code
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
dispatch_async(dispatch_get_main_queue(), ^{
[window addSubview:self]; // self represents myView object
});
If someones knows the reason for this behaviour, please enlighten me.

Related

setHidden not working for UIView

I have a subclass of UIView called InvitedView. It is instantiated in viewDidLoad like this:
ViewController.m
invitedView = [[InvitedView alloc] initWithFrame:CGRectMake(100, 244, 120, 80)];
invitedView.backgroundColor = [UIColor colorWithRed:156.0f/255.0f green:214.0f/255.0f blue:215.0f/255.0f alpha:0.9f];
[self.view addSubview:invitedView];
[invitedView setHidden:YES];
The class itself looks like this:
InvitedView.m
#import "InvitedView.h"
#import "AppDelegate.h"
#import "ViewController.h"
#class ViewController;
#interface InvitedView() {
UIButton *accept;
UIButton *decline;
UILabel *question;
UIView *gray;
ViewController *myViewController;
}
#end
#implementation InvitedView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
gray = [[UIView alloc] initWithFrame:frame];
NSString *holduser = [(AppDelegate*)[[UIApplication sharedApplication] delegate] invitedby];
[self addSubview:gray];
accept = [[UIButton alloc] init];
decline = [[UIButton alloc] init];
question = [[UILabel alloc] init];
question.text = [[NSString alloc] initWithFormat:#"You have been invited to a group game by %#", holduser];
question.numberOfLines = 0;
question.textAlignment = NSTextAlignmentCenter;
question.textColor = [UIColor colorWithRed:211.0f/255.0f green:243.0f/255.0f blue:219.0f/255.0f alpha:1.0f];
accept.backgroundColor = [UIColor clearColor];
accept.frame = CGRectMake(20, gray.frame.size.height / 2, (gray.frame.size.width / 2) - 10, (gray.frame.size.height / 2) - 20);
decline.backgroundColor = [UIColor clearColor];
decline.frame = CGRectMake((gray.frame.size.width / 2) + 10, (gray.frame.size.width / 2) - 20, (gray.frame.size.width / 2) - 20, (gray.frame.size.height / 2) - 20);
question.frame = CGRectMake(20, 20, gray.frame.size.width, (gray.frame.size.height / 2) - 20);
[question setFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:18.0]];
[accept addTarget:myViewController action:#selector(acceptInvite) forControlEvents:UIControlEventTouchUpInside];
[decline addTarget:myViewController action:#selector(declineInvite) forControlEvents:UIControlEventTouchUpInside];
[gray addSubview:accept];
[gray addSubview:decline];
[gray addSubview:question];
}
return self;
}
#end
The method where the view is supposed to be shown is in the view controller showing the view. It ends up getting called, I can verify that the log messages happen all the way up until the setHidden function:
ViewController.m
- (void)doSomethingWithTheNewValueOfFlagForHid {
NSLog(#"issettingtheview******");
dispatch_async(dispatch_get_main_queue(), ^(void){
NSLog(#"issettingtheviewmu2******");
[invitedView setHidden:NO];
});
}
I would like to know why invitedView isn't being shown after [invitedView setHidden:NO].
It gets all the way to setHidden, and then nothing happens. I would appreciate any help, thanks in advance.
In ViewDidLoad, change line to
[invitedView setHidden:NO];
to make sure you can actually see the view (frame is ok, no view above ...)
You might also want to check Xcodes 3D View Debugging
The only reason that it wasn't showing up, is that invitedView was being instantiated inside an if statement that wasn't being executed. However - shallowThought's idea to switch setHidden to YES started me down a more productive debugging tract, leading to the discovery.

UIView not accepting UIViewControllers data

I have a GameOver UIView that I call from inside my main UIViewController. It is just a 'popover' window that has the text game over, the score, and some blur effects to blur the main UIViewcontroller.
I try to pass an int to the UIView, but it doesn't accept it unless it is in the - (void)drawRect:(CGRect)rect method.
If I move the score label to drawRect method, the label is updated. But the blur effects go away.
What am I doing wrong?
MainViewController.m
#import "GameOverView.h"
#interface ViewController () {
GameOverView * gov;
}
- (void) showGameOver {
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
NSLog(#"Passing score of: %i", self.score);
gov.finalScore = self.score;
[self.view addSubview:gov];
}
GameOverView.h
#interface GameOverView : UIView {}
#property (nonatomic) int finalScore;
#end
GameOverView.M
#implementation GameOverView
- (id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//self.backgroundColor = [UIColor redColor];
NSLog(#"Score:%i", self.finalScore );
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = super.bounds;
[super addSubview:visualEffectView];
UILabel * lblGameOver = [[UILabel alloc] initWithFrame:CGRectMake(0,0, frame.size.width, 200)];
lblGameOver.center = CGPointMake(frame.size.width/2, 100);
lblGameOver.text = [NSString stringWithFormat: #"GAME OVER %i", self.finalScore];
[self addSubview:lblGameOver];
UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, 200)];
button.center = CGPointMake(frame.size.width/2, 200);
[button setTitle:#"Start New Game" forState:UIControlStateNormal];
[button addTarget:self action:#selector(removeSelfFromSuperview) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
return self;
}
- (void) removeSelfFromSuperview{
[self removeFromSuperview];
}
You are using the finalScore property in the init method of the GameOverView class, but you are only setting its value after initializing it.
Change your initialization method to
- (id) initWithFrame:(CGRect)frame finalScore:(int)fs{
// use 'fs' instead of 'self.finalScore'
}
It should work.
I wonder how there isn't any problem with the view background color. You are initializing the view and adding it as subview like this:
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
gov.finalScore = self.score;
[self.view addSubview:gov];
This will give the view background color as black which is default color. So you don't find much difference if you use blur effect.
you need to give the color for the view during the initialization :
gov = [[GameOverView alloc] initWithFrame:self.view.bounds];
[gov setBackgroundColor:[UIColor yourColor]];
[self.view addSubview:gov];
If you are planning to keep the code in initWithFrame, you don't need to worry about setting the background color. If you keep the code in drawRect, then you must set the background color,else it will be black color.
When coming to setting the score label, it doesn't matter whether you put it in drawRect or initWithFrame method. Make sure you use drawRect method only if you really have to draw on the view,so that you can call it later by using setNeedsDisplay

Making a list of UIViews that slide up and down when touched

I'm trying to figure out an approach to build something like the image below, which is a list of items that when a section is clicked slides out content. It's a really common UX on most websites and what not. My idea is to have each gray box (button) slide out a UIView containing some other items. I'm still new to iOS development but I'm struggling to find how you can animate a UIView to slide down and push the content below it down as well. Hoping some one can give me a good starting point or point to some info outside the realm of the apple docs.
Thanks!
So if you just have a few views, I would not recommend the UITableView approach, since it is not so easy to customize with animations and table views usually want to fill the whole screen with cells. Instead write a expandable UIView subclass that has the desired two states. Add a method to switch between extended and collapsed state. On expanding/collapsing adjust their positions so that they always have enough space.
I provide you an example of views adjusting their frames. I guess it should be easy to do the same with auto layout constraints: give the views a fixed height constraint and change this on collapsing/expanding. The same way set the constraints between the views to be 0 so that they are stacked on top of each other.
Expandable View:
#interface ExpandingView(){
UIView *_expandedView;
UIView *_seperatorView;
BOOL _expanded;
}
#end
#implementation ExpandingView
- (id)init
{
self = [super initWithFrame:CGRectMake(15, 0, 290, 50)];
if (self) {
_expanded = NO;
self.clipsToBounds = YES;
_headerView = [[UIView alloc] initWithFrame:self.bounds];
_headerView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1];
[self addSubview:_headerView];
_seperatorView = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height-1, self.bounds.size.width, 1)];
_seperatorView.backgroundColor = [UIColor lightGrayColor];
[self addSubview:_seperatorView];
_expandedView = [[UIView alloc] initWithFrame:CGRectOffset(self.bounds, 0, self.bounds.size.height)];
_expandedView.backgroundColor = [UIColor blueColor];
[self addSubview:_expandedView];
}
return self;
}
- (void)layoutSubviews{
[self adjustLayout];
}
- (void)adjustLayout{
_headerView.frame = CGRectMake(0, 0, self.bounds.size.width, 50);
_seperatorView.frame = CGRectMake(0, 49, self.bounds.size.width, 1);
_expandedView.frame = CGRectMake(0, 50, self.bounds.size.width, self.bounds.size.height-50);
}
- (void)toggleExpandedState{
_expanded = !_expanded;
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, _expanded?200:50);
[self adjustLayout];
}
#end
ViewController:
#interface ExpandingViewController (){
NSArray *_expandingViews;
}
#end
#implementation ExpandingViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_expandingViews = #[
[[ExpandingView alloc] init],
[[ExpandingView alloc] init],
[[ExpandingView alloc] init],
];
for(ExpandingView *view in _expandingViews){
[view.headerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(expandingViewTapped:)]];
[self.view addSubview:view];
}
}
- (void)viewWillLayoutSubviews{
int y = 100;
for(ExpandingView *view in _expandingViews){
view.frame = CGRectOffset(view.bounds, (CGRectGetWidth(self.view.bounds)-CGRectGetWidth(view.bounds))/2, y);
y+=view.frame.size.height;
}
}
- (void)expandingViewTapped:(UITapGestureRecognizer*)tapper{
ExpandingView *view = (ExpandingView*)tapper.view.superview;
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
[view toggleExpandedState];
[self.view layoutIfNeeded];
} completion:nil];
}

inputaccessoryview not showing (StoryBoard)

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.

UIScrollView with image

Is it possible to use a UIScrollView to see an image that is about 800px long? I tried using a UIScrollView and the UIImageView but it's not scrolling. Anybody can help please?
Use:
UIScrollView *yourScrollview = [[UIScrollView alloc] initWithFrame:(CGRect){{0,0}, {320,480}}];
UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourImageHere.png"]];
yourImageView.frame = yourScrollview.bounds;
yourScrollview.contentSize = yourImageView.frame.size;
yourScrollview.minimumZoomScale = 0.4;
yourScrollview.maximumZoomScale = 4.0;
[yourScrollview setZoomScale:yourScrollview.minimumZoomScale];
yourScrollview.delegate = self;
[self.view addSubview:yourScrollview];
Don't forget to add UIScrollViewDelegate in your .h file
Note: ARC code
1. Create a new Project -> Single View Application
2. Put the follow code into:
"ViewController.m"
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(void) viewDidLoad
{
[super viewDidLoad];
UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[scrollView setContentSize:CGSizeMake(320, 800)];
UIView * myView = [[UIView alloc] initWithFrame : CGRectMake(0, 0, 320, 800)];
UIImageView * myImage = [[UIImageView alloc]initWithImage : [UIImage imageNamed:#"Test.png"]];
[myView addSubview: myImage];
[myImage release];
[scrollView addSubview: myView];
[myView release];
[self.view addSubview: scrollView];
[scrollView release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
3. Put the Image "Test.png" into your Project (Drag Drop into Xcode -> Folder:Supporting Files)
If it is not panning it means you forgot to set the contentSize property. I have a tutorial on my website that shows how to embed a UIImageView inside a UIScrollView and set it up for both panning and zooming. It includes complete downloadable source code. See Panning and Zooming with UIScrollView
#interface ZoomViewController : UIViewController <uiscrollviewdelegate> {
IBOutlet UIScrollView *scroll;
UIImageView *image;
}
#property (nonatomic, retain) UIScrollView *scroll;
#end
</uiscrollviewdelegate></uikit>
Once check your Viewdidload method.
- (void)viewDidLoad {
image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"img_body.png"]];
[super viewDidLoad];
image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"img_body.png"]];
scroll.contentSize = image.frame.size;
[scroll addSubview:image];
scroll.minimumZoomScale = 0.4;
scroll.maximumZoomScale = 4.0;
scroll.delegate = self;
[scroll setZoomScale:scroll.minimumZoomScale];
[super viewDidLoad];
}

Resources