How to align view and subview center Objective-C - ios

I have these two views that i would like to align to be centered.
self.loadingView = [[UIView alloc] initWithFrame:CGRectMake(75, 155, 120, 120)];
self.loadingView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.loadingView.clipsToBounds = YES;
self.loadingView.layer.cornerRadius = 10.0;
self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
self.activityView.frame = CGRectMake(65, 40, self.activityView.bounds.size.width, self.activityView.bounds.size.height);
[self.loadingView addSubview:self.activityView];
loadingView needs to be aligned center to the iPhones screen. This means a code that can support different sizes of screens. And then activityView should be aligned centered inside the loadingView.
I have tried some code examples but none worked. And it was really confusing. If someone could provide some code exampels and explaing a bit how it works to get a hang of this.
EDIT1
I wrote just as you did i added the self.view.center part but it is still not in the middle?
Also the second question was how to add the indicator view in the CENTER of the loadingView.

- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor= [UIColor blackColor];
UIActivityIndicatorView * indicator;
indicator = [[UIActivityIndicatorView alloc] init];
indicator.center = self.view.center;
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[indicator startAnimating];
[self.view addSubview:indicator];
// Do any additional setup after loading the view, typically from a nib.
}
this will add the activity indicator in the center of the screen..

Related

Activity Indicator is not showing in front of view

I have a view in Which I have added a UIScrollview. In UIScrollView I added an UIImageView. After Picking Image from ImagePicker I am adding image to UIImageView.
Problem : I am showing UIActivityIndicatorView before adding image to ImageView.
Case 1: When I add activity Indicator to self.view It is showing behind the UIScrollView means not showing at all.
Case 2: If I add Indicator to Scrollview it is not adding in view.
I tried many thing bringSubviewToFront , insertSubview:indicator aboveSubview:myscrollview
Here is my CODE :
scroller = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 60, Screen_width, Screen_height - 60)];
scroller.delegate = self;
[self.view addSubview:scroller];
scroller.contentSize = CGSizeMake(Screen_width, 667);
profileImageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 10, Screen_width-40, Screen_width-40)];
profileImageView.backgroundColor = gray;
profileImageView.contentMode = UIViewContentModeScaleAspectFill;
profileImageView.clipsToBounds = YES;
profileImageView.userInteractionEnabled=YES;
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
_profileIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
_profileIndicator.frame = CGRectMake(40.0, 20.0, 60.0, 60.0);
_profileIndicator.center = self.view.center;
[self.view addSubview:_profileIndicator];
[_profileIndicator startAnimating];
}
All the UI things should be in main thread. So, please make sure you are using UIActivityIndicator in main thread.

UIActivityIndicator doesn't stop in iOS

I am showing spinner(UIActivityIndicator) while download is going on. It shows spinner as download starts, but it doesn't stop showing once download is finished. i have seen some question for the same issue but did not help. I need to make it work in ios7 as well as iOS8.
I am using below code...
- (void) startSpinner:(NSString *)message {
container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
container.center = self.view.center;
container.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:0.4];
container.layer.cornerRadius = 10;
container.layer.masksToBounds = true;
container.tag = 134;
activityLabel = [[UILabel alloc] init];
activityLabel.frame = CGRectMake(0, 70, 100, 30);
activityLabel.text = message;
activityLabel.textColor = [UIColor darkGrayColor];
activityLabel.textAlignment = NSTextAlignmentCenter;
activityLabel.font = [UIFont boldSystemFontOfSize:10];
[container addSubview:activityLabel];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = CGPointMake(container.frame.size.width/2, container.frame.size.height/2);
[container addSubview:activityIndicator];
[self.view addSubview:container];
[activityIndicator startAnimating];
}
-(void)stopSpinner{
[activityIndicator stopAnimating];
container = [self.view viewWithTag:134];
[container removeFromSuperview];
activityIndicator = nil;
NSLog(#"activity indicator should be removed %#",activityIndicator);
}
And one more issue it does not show spinner in the center of the device screen.
Any help will be appreciated....
There are a few things wrong here.
container.center = self.view.center;
If you are trying to center the container in self.view, then this won't do it. self.view.center is the center of the view's frame but you would need to use the center of the view's bounds. Here is the corrected code:
container.center = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
You also need to change how you set the activity indicator's frame:
activityIndicator.center = CGPointMake(CGRectGetMidX(container.bounds), CGRectGetMidY(container.bounds));
Also, if you call startSpinner more than once, you can have more than one spinner added to the view, which could possibly be the reason your spinner doesn't seem to be stopping. I recommend that you alloc and init only one spinner and do it in the class constructor. You can do the same with the container and activityLabel objects. Alternatively, you could call stopSpinner at the top of startSpinner (and add some null-checks in stopSpinner to avoid referencing a null pointer).
It's impossible to say for sure based on your code why it appears that the spinner doesn't stop, but my guess is that you're calling startSpinner several times in a row without any intervening call to stopSpinner.
If you're only calling stopSpinner once then verify that you're doing so in the main thread.
You can add the spinner view on navigation controller, so it will look at the center as you want. I think this will solve your problem.
[self.navigationController.view addSubview:coverView];
And don't forget to remove it from self.navigationController.view

Displaying UIActivityIndicatorView until UIView is loaded

In my UIViewController's loadView method I start a UIActivityIndicator. Later in loadView I load a complex UIView, which takes about 2-3 secs to load. (UIScrollView with a lot of pictures more specifically). My problem is that the UIActivityIndicator spinner is only visible, after my other layer has loaded too. (which is of course useless to me). What is a correct way to handle this?
- (void)loadView {
CGRect fullScreenRect=[[UIScreen mainScreen] bounds];
UIView *contentView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
self.view = contentView;
spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
spinner.center = self.view.center;
[self.view addSubview:spinner];
[spinner startAnimating];
scrollView=[[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
...setting up scrollView...
[self.view addSubview:scrollView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[spinner removeFromSuperview];
}
I have found a somewhat similar thread:
UIActivityIndicatorView not showing until after loading done
But it suggests to load things in a background thread, but loading and displaying a UIView is only possible in the main thread as far as I know.
I am a beginner, and sorry if my question is fundamentally wrong.
I managed to make it the way Carl Veazey suggested. It was pretty easy actually. I spawned a new background thread, and loaded my UIScrollView there.
I used, in LoadView:
spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
spinner.center = self.view.center;
[self.view addSubview:spinner];
[spinner startAnimating];
[self performSelectorInBackground:#selector(populateScrollView) withObject:nil];
And:
-(void) populateScrollView{
...creating scrollView...
[self.view addSubview:scrollView];
[spinner removeFromSuperview];
}
It works perfectly. What is really weird for me, is that I am adding the scrollview to the UI in a background thread, not in the main thread. I thought I could only mess with the UI in the main thread.
(I could do the same thing with GCD. When the background thread finished loading the scrollview, I could display scrollview in the main thread's queue. But the former solution somehow works as well...)
Sorry for ugly text formatting.
There is a very cute way to do what you want.
Firstly you have to show the indicator view and only after a little amount of time (0.1 sec or even lesser) you ask your scrollView to populate.
- (void)loadView {
CGRect fullScreenRect=[[UIScreen mainScreen] bounds];
UIView *contentView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
self.view = contentView;
spinner = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
spinner.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
spinner.center = self.view.center;
[self.view addSubview:spinner];
[spinner startAnimating];
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
scrollView=[[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 340, fullScreenRect.size.width)]autorelease];
...setting up scrollView...
[self.view addSubview:scrollView];
});
}
Try this simple method, Its working well for me....
UIActivityIndicatorView *activityIndicator= [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
activityIndicator.layer.cornerRadius = 05;
activityIndicator.opaque = NO;
activityIndicator.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f];
activityIndicator.center = self.view.center;
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[activityIndicator setColor:[UIColor colorWithRed:0.6 green:0.8 blue:1.0 alpha:1.0]];
[self.view addSubview: activityIndicator];
Add following lines while load your view
//-- Add this line while processing to load your view
[activityIndicator startAnimating];
//-- Add this line when after you view loaded
[activityIndicator stopAnimating];

creating uiview programmatically?

Creating a view with following code.
- (void)loadView {
paintView=[[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 430)];
[paintView setBackgroundColor:[UIColor yellowColor]];
self.view = paintView;
[paintView release];
But my problem is whole screen fills with yellow color, but I want with specified frame.
I am creating this view in a view based application.. Am i doing something wrong, Overridind the original view?
You can do it in following way.
- (void)loadView {
/// make a empty view to self.view
/// after calling [super loadView], self.view won't be nil anymore.
[super loadView];
paintView=[[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 430)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:paintView];
[paintView release];
};
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,35)];
newView.backgroundColor=[UIColor clearColor];
UITextView *mytext = [[UITextView alloc] initWithFrame:CGRectMake(5.0, 0.0, 100.0, 28.0)];
mytext.backgroundColor = [UIColor clearColor];
mytext.textColor = [UIColor blackColor];
mytext.editable = NO;
mytext.font = [UIFont systemFontOfSize:15];
mytext.text = #"Mytext";
mytext.scrollEnabled=NO;
[mytext release];
[newView addSubview:mytext];
[self.view addSubview:newView];
replace self.view =paintView;
by
[self.view addSubview: paintView];
I am Going change Line No 3 in LoadView Method , you should add the subView in main View instead on assiging it Directly.
[self.view addSubview:paintview];

Why does navigationItem.titleView align left when presentmodalviewcontroller called?

I'm using a UILabel for the titleView of a navigation bar (I'm making simple in-app web browser). It works fine, except that when I present a modal view controller, the titleView shifts from the center of the navbar to the far left (underneath the back button). I've tested in 3.0 and up. Here is relevant code:
- (void)viewDidLoad {
[super viewDidLoad];
// Title view label
CGRect labelFrame = CGRectMake(0.0, 0.0, 120.0, 36.0);
UILabel *label = [[[UILabel alloc] initWithFrame:labelFrame] autorelease];
label.font = [UIFont boldSystemFontOfSize:14];
label.numberOfLines = 2;
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(0.0, -1.0);
label.lineBreakMode = UILineBreakModeMiddleTruncation;
self.navigationItem.titleView = label;
}
-(void)displayComposerSheet:(NSString*)mailto
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
Screenshots:
Any idea why this is happening? Thanks.
I looked into the problem with some hit and try and found the following facts:
If the UINavigationBar doesn't have the rightBarButtonItem, the titleView shifts towards the right by ~30pts.
It could be reproduced for leftBarButtonItem. But I haven't tried.
In a scenario where the a default UINavigationBar's (with no changes to rightBarButtonItem defaults) titleView is set. And then a new UIView is pushed to the navigation stack which HAS a rightBarButtonItem. Now, if this view is popped [with back button], the navigation bar will remove the rightBarButtonItem. And this will account for the weird offset that shifts the titleView towards a side.
How I fixed the problem was like this:
self.navigationItem.titleView = myCustomTitleView;
// Fake right button to align titleView properly.
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 1)]];
// Width equivalent to system default Done button's (which appears on pushed view in my case).
rightBarButtonItem.enabled = NO;
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
Everything is sweet now. yummmm.
Thanks to DougW for pointing me in right direction. Here's the best hack I found. Basically I retain the UILabel as a class property. Before presenting modal view I unset the titleView, and then reset it immediately after. When the modal view is dismissed I unset then reset the titleView. To the user none of this is visibly notable.
-(void)displayComposerSheet:(NSString*)mailto
{
self.navigationItem.titleView = nil;
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
picker.navigationBar.tintColor = [APPDELEGATE getNavTintColor];
[picker setToRecipients:[NSArray arrayWithObject:mailto]];
[self presentModalViewController:picker animated:YES];
[picker release];
self.navigationItem.titleView = titlelabel;
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
self.navigationItem.titleView = nil;
self.navigationItem.titleView = titlelabel;
[self dismissModalViewControllerAnimated:YES];
}
Does it animate? It may be animating the title view as though it's transitioning to a new view. I don't see anything wrong with your code as written.
I would suggest in your displayComposerSheet, you just unset the titleView, or animate the alpha of the titleView to 0.0. Then, animate it back to 1.0 when you dismiss the modal view controller. Not ideal, but it may look better that way.
Frankly, the whole UINavigation system is crap. We went ahead and re-wrote it ground up because of bizarre issues like these.
The only problem is your frame size. so u have to change it.
Try this one.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 36.0)];
label.font = [UIFont boldSystemFontOfSize:14];
label.numberOfLines = 2;
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(0.0, -1.0);
label.lineBreakMode = UILineBreakModeMiddleTruncation;
label.text=#"Stack Overflow";
self.navigationItem.titleView = label;
You can try move the code in viewDidAppear:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// You code to customize title view
self.navigationItem.titleView = logoImage;
}
It works for me.
If you change the width size to be small like 100 points or smaller instead of 120 you set, this problem may go away. Setting width of the label smaller worked for me.
UIView *view= [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
[view setUserInteractionEnabled:NO];
view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"logo_small.png"]];
UIBarButtonItem *barButton=[[UIBarButtonItem alloc]initWithCustomView:view ];
self.navigationItem.leftBarButtonItem = barButton;

Resources