I had created an application using story board with auto layout support. Now i want to add an loading view on request/response. I had created loading view by code like this
self=[super initWithFrame:f];
[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7]];
CGPoint p=[self center];
self.activityIndicator=[[UIActivityIndicatorView alloc] initWithFrame: CGRectMake(p.x-37/2, p.y-32/2, 37, 37)];
[self.activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];
[self addSubview:self.activityIndicator];
lblMsg=[[UILabel alloc] initWithFrame:CGRectMake(p.x-50/2,CGRectGetMaxY(self.activityIndicator.frame), 200, 30)];
lblMsg.text=#"Logging...";
lblMsg.backgroundColor=[UIColor clearColor];
lblMsg.textColor=[UIColor lightGrayColor];
[self addSubview:lblMsg];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
return self;
Now problem is that it is not performing rotation. it is always coming in portrait mode. How can i apply autorotate functionality to it.
may be this will help you try this
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
i couldn't find where you are start animating for UIActivityIndicatorView.
[self.activityIndicator startAnimating];
One of the best framework to use for loadingView
1) https://github.com/jdg/MBProgressHUD
You can use NetworkActivityIndicator.
When you sending the request, use
[self setNetworkActivityIndicatorVisible:YES];
and when the response come back, use
[self setNetworkActivityIndicatorVisible:NO];
Related
I am adding activity indicator on top of the view and wish to disable the selections in the background when the activity indicator is on. Also for some reason, my activity indicator is still spins for about 30-45 seconds(depending on the network speed) after the data is displayed on the table view. I have created a category for activity indicator.
Activity Indicator category code:
- (UIView *)overlayView {
return objc_getAssociatedObject(self, OverlayViewKey);
}
- (void)setOverlayView:(UIView *)overlayView {
objc_setAssociatedObject(self, OverlayViewKey, overlayView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)showActivityIndicatorForView:(UIView *)view {
self.overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.center = self.overlayView.center;
[view setUserInteractionEnabled:NO];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self.overlayView setUserInteractionEnabled:NO];
[self startAnimating];
[self.overlayView addSubview:self];
[view addSubview:self.overlayView];
[view bringSubviewToFront:self.overlayView];
self.hidesWhenStopped = YES;
self.hidden = NO;
}
- (void)hideActivityIndicatorForView:(UIView *)view {
[self stopAnimating];
[self.overlayView setUserInteractionEnabled:YES];
[self.overlayView removeFromSuperview];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
[view setUserInteractionEnabled:YES];
}
Usages in table view controller:
#interface MyTableViewController()
#property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
#end
#implementation MyTableViewController
- (id) initWithSomething:(NSString *)something {
self = [super init];
if (self) {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self getDataServiceRequest];
[self.activityIndicator showActivityIndicatorForView:self.navigationController.view];
}
- (void)requestCompletionCallBack sender:(ServiceAPI *)sender {
// Do something here with the data
[self.activityIndicator hideActivityIndicatorForView:self.navigationController.view];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
#end
What am I doing wrong here? Why am I still able to select the data in the background when the activity indicator is on and even after disabling the user interaction.
Move your call to hideActivityIndicatorForView to inside the call to dispatch_async(dispatch_get_main_queue(). It's a UI call, and needs to be done on the main thread.
As for how to disable other actions on your view controller, you have a few options. One simple thing I've done is the put the activity indicator inside a view that's pinned to the whole screen, set to opaque=false, and with a color that's black with an alpha setting of 0.5. That way the content underneath is visible but the user can't click on it. You need to add an outlet to your "coveringView" and show-hide it instead of showing/hiding the activity indicator view.
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
fix it
[self performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
I have created a custom UIView to show an UIActivityIndicatorView and a message. Idea is to reuse this across my app for consistency. Below is the code:
#implementation CDActivityIndicator
#synthesize activityIndicator, message;
//init method called when the storyboard wants to instantiate this view
- (id) initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
message = [[UILabel alloc] initWithFrame:CGRectZero];
[message setBackgroundColor:[UIColor clearColor]];
[message setTextColor:[UIColor whiteColor]];
[message setTextAlignment:NSTextAlignmentCenter];
[message setFont:[UIFont fontWithName:#"HelveticaNeue" size:15.0f]];
[self addSubview:activityIndicator];
[self addSubview:message];
//set background color
[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5]];
}
return self;
}
-(void) layoutSubviews {
[super layoutSubviews];
//position the indicator at the center of the view
[activityIndicator setCenter:[self center]];
//position the label
[message setFrame:[self frame]];
}
- (void) begin {
//make sure the current view is visible, and message is hidden
[self setHidden:NO];
[activityIndicator setHidden:NO];
[self bringSubviewToFront:activityIndicator];
[message setHidden:YES];
[self performSelectorOnMainThread:#selector(startAnimating) withObject:self waitUntilDone:YES];
}
- (void) startAnimating {
if( !activityIndicator.isAnimating ) {
[activityIndicator startAnimating];
}
}
To try this out, I added a UIView to one of my views in the storyboard and set the class for that view to CDActivityIndicator. When I call begin() from the corresponding View Controller, the CDActivityIndicator gets shown as an empty view with the expected background color. However, the activity indicator doesn't show. All methods are getting called as expected.
Any idea what I might be missing? Thanks!
You should change your subviews frame setting like this.
CGPoint point = [self.superview convertPoint:self.center toView:self];
[activityIndicator setCenter:point];
[message setFrame:self.bounds];
The frame defines the origin and dimensions of the view in the coordinate system of its superview. Every UIView has its own coordinate system. You should take this into account.
I am trying to adapt my application for iOS 7. The issue I am having is I can not change the tint color of some controls.
I did add
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if (IOS7_OR_LATER)
self.window.tintColor = [self greenTintColor];
to my app delegate's
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
It mostly helped but color of message box and action sheet buttons is still the default blue.
How can I recolor all such buttons too?
Some screenshots:
As UIAlertView is deprecated You can. Use UIAlertController.
You can use tintColor property.
OLD
The UIAlertView class is intended to be used as-is and does not
support subclassing. The view hierarchy for this class is private and
must not be modified.
-From Apple Doc
You can use tintColor property or You can use Some Custom Library for that, you can find it at cocoacontrols.com.
I was able to change the cancel button's text color to white in app delegate.
[[UIView appearance] setTintColor:[UIColor whiteColor]];
For Actionsheet You can use
Utilize the willPresentActionSheet delegate method of UIActionSheet to change the action sheet button color.
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet
{
for (UIView *subview in actionSheet.subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *)subview;
button.titleLabel.textColor = [UIColor greenColor];
}
}
}
Combining best answers above, and updated for deprecation:
[[UIView appearanceWhenContainedInInstancesOfClasses:#[[UIAlertController class]]] setTintColor:[UIColor greenColor]];
or Swift:
UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .green
Works in 2018, Swift 4 / iOS 12.
You can adjust the color by searching and modifying the UILabel in the subview hierarchy of the alert window that is created right after showing the alert:
- (void)setButtonColor:(UIColor*)buttonColor {
dispatch_after(dispatch_time(0,1), dispatch_get_main_queue(), ^{
NSMutableArray *buttonTitles = [NSMutableArray array];
for (NSUInteger index = 0; index < self.numberOfButtons; index++) {
[buttonTitles addObject:[self buttonTitleAtIndex:index]];
}
for (UILabel *label in [[[UIApplication sharedApplication] keyWindow] recursiveSubviewsOfKind:UILabel.class]) {
if ([buttonTitles containsObject:label.text]) {
label.textColor = buttonColor;
label.highlightedTextColor = buttonColor;
}
}
});
}
[alert show];
[alert setButtonColor:UIColor.redColor];
The recursiveSubviewsOfKind: method is a category on UIView that returns an array of views in the complete subview hierarchy of the given class or subclass.
for UIAlertView with colored buttons you can use the cocoapod "SDCAlertView"
about CocoaPods: http://www.cocoapods.org
how to install CocoaPods: https://www.youtube.com/watch?v=9_FbAlq2g9o&index=20&list=LLSyp50_buFrhXC0bqL3nfiw
In iOS 6.0 create custom view in App delegate
.h
UIView* _loadingView;
UIView* _subView;
UIActivityIndicatorView*loadingIndicator;
UITabBarController *tabBar_Controller;
NSTimer *timer;
#property (strong, nonatomic) UIView* _loadingView;
#property (strong, nonatomic) UIView* _subView;
.m- (void)fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begins animation block
[UIView setAnimationDuration:3.0]; // sets animation duration
[UIView setAnimationDelegate:self]; // sets delegate for this block
[UIView setAnimationDidStopSelector:#selector(finishedFading)];
self.txtview.alpha = 0.0; // Fades the alpha channel of this view
[UIView commitAnimations]; // commits the animation block. This
}
- (void) finishedFading
{
[self.txtview removeFromSuperview];
}
- (void)showConnectivity:(NSString *)strTitle
{
[_loadingView setBackgroundColor:[UIColor clearColor]];
[_loadingView setAlpha:0.5];
[_loadingView.layer setCornerRadius:10];
[self.window addSubview:_loadingView];
[_loadingView setHidden:NO];
[_subView.layer setCornerRadius:7];
[_subView setBackgroundColor:[UIColor colorWithHue:0.0f saturation:0.0f brightness:0.0f alpha:0.6]];
[_subView setOpaque:YES];
[self.window addSubview:_subView];
[_subView setHidden:NO];
[_loadingView setHidden:NO];
[_subView setHidden:NO];
loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[loadingIndicator setFrame:CGRectMake(85,10,35,35)];
[_subView addSubview:loadingIndicator];
[loadingIndicator setBackgroundColor:[UIColor redColor]];
[loadingIndicator startAnimating];
UILabel *_lab=[[UILabel alloc]initWithFrame:CGRectMake(8,10,72,45)];
[_lab setText:strTitle];
[_lab setTextColor:[UIColor whiteColor]];
[_lab setBackgroundColor:[UIColor clearColor]];
[_lab setFont:[UIFont boldSystemFontOfSize:13.0]];
[_lab setTextAlignment:NSTextAlignmentCenter];
[_subView addSubview:_lab];
}
- (void)CoonectingViewHidden
{
[_loadingView setHidden:YES];
[_subView setHidden:YES];
NSArray *_aryViews = [_subView subviews];
for(int i = 0; i<[_aryViews count];i++)
{
id obj = [_aryViews objectAtIndex:i];
if(![obj isKindOfClass:[UIActivityIndicatorView class]])
[obj removeFromSuperview];
}
[loadingIndicator stopAnimating];
[loadingIndicator hidesWhenStopped];
}
in using .m
#import"Appdelegate.h"
- (void)showLoadingIndicator:(NSString *)message
{
AppDelegate *delegateObj2=(AppDelegate *)[UIApplication sharedApplication].delegate;
[delegateObj2 showConnectivity:message];
}
-(void)stopLoading
{
AppDelegate *delegateObj3=(AppDelegate *)[UIApplication sharedApplication].delegate;
[delegateObj3 CoonectingViewHidden];
}
// [self showLoadingIndicator:#"Loading"];
n
[self stopLoading];
I have a ViewController with a NavigationController and I want to add a translucent UIView with some Buttons over the ViewController when I press a ViewController button, the problem is that I can not put the UIView over the NavigationBar. How can I solve this?
This is my code ( Very simple)
-(void)setOpacityView
{
opacityVw = [[UIView alloc] initWithFrame:self.view.bounds];
opacityVw.backgroundColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
WPCustomButton *closeBtn = [[WPCustomButton alloc] initWithFrame:CGRectMake(230, 10, 80, 20)];
[closeBtn setTitle:#"Close X" forState:UIControlStateNormal];
[closeBtn setBackgroundColor:[UIColor clearColor]];
[closeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[closeBtn addTarget:self action:#selector(closeView) forControlEvents:UIControlEventTouchUpInside];
[opacityVw addSubview:closeBtn];
}
// ---------------------------------------------------------------------------------------------------------------------
#pragma mark - Button methods
-(void) closeView
{
[opacityVw removeFromSuperview];
}
-(void)setProfileImage
{
[self setOpacityView];
[self.view addSubview:opacityVw];
}
I answered a similar question here
Try something like this:
-(void)setProfileImage
{
[self setOpacityView];
[self.navigationController.view addSubview:opacityVw];
}
Add it to the AppDelegate's UIWindow instead.
- (void)setProfileImage
{
[self setOpacityView];
[ [[UIApplication sharedApplication] delegate].window addSubview:opacityVw];
}
Don't forget to change your view size:
opacityVw = [[UIView alloc] initWithFrame:[[[UIApplication sharedApplication] delegate]window].bounds];
You can create MainViewController and put that as your window.rootViewController. Add your navigationController to this MainViewController. After that it you add the view to your mainViewController, it would be on top of navigation Controller.
Just make it simple :
-(void)setProfileImage
{
[self setOpacityView];
self.navigationController.navigationBarHidden = YES;
[self.view insertSubview:opacityVw aboveSubview:self.view];
}
-(void) closeView
{
[opacityVw removeFromSuperview];
self.navigationController.navigationBarHidden = NO;
}
I am making call to two web services simultaneously, i am showing activity indicator at that time. Since either of the service can end first. I am not sure how to hide the activity indicator. I am thinking to use flag. But i am not sure whether that is the better way.Please help me with some better approach.
One easy way is to use AFNetworking library, which takes care of NetworkActivityIndicator for you. You just need to set [[AFNetworkActivityIndicatorManger sharedManager] setEnabled:YES]; in your app delegate.
Otherwise, keeping a counter is a good way to do it. When you start each web request, just increment the counter and decrement the counter in the success or failure block. In those blocks, after decrementing the counter, if the counter is equal to zero, then set isNetworkActivityIndcatorVisible property of [UIApplication sharedApplication] to NO.
Try This.
Add one line Before [self.window addSubview: activityView1]
activityView1.tag = 110;
(You can set any number other than 110 also)
And Write following code to remove:
for(UIView *viewActivityIndicator in [[UIApplication sharedApplication] keyWindow].subviews)
{
if(viewActivityIndicator.tag == 110)
{
[viewActivityIndicator removeFromSuperview];
}
}
If there is no special requirement than use some library instead of managing self.
Some Good Example :
1. SVProgressHUD
2. MBProgressHUD
You need to create a method in AppDelegate.m class
#pragma mark activity indicator view
-(void)showActivityViewer:(NSString* )msg
{
if (activityView1 == nil)
{
[activityView1 release];
activityView1 = [[UIView alloc] initWithFrame: CGRectMake(0, 0, 320, 580)];
activityView1.backgroundColor = [UIColor darkGrayColor];
activityView1.alpha = 0.8;
UILabel* lblLoading=[[UILabel alloc] initWithFrame:CGRectMake(70, 260, 180, 60)];
lblLoading.numberOfLines=0;
lblLoading.text=msg;
lblLoading.backgroundColor=[UIColor clearColor];
lblLoading.textAlignment=UITextAlignmentCenter;
[lblLoading setContentMode:UIViewContentModeBottom];
lblLoading.textColor=[UIColor whiteColor];
[activityView1 addSubview:lblLoading];
[lblLoading release];
UIActivityIndicatorView *activityWheel = [[UIActivityIndicatorView alloc] initWithFrame: CGRectMake(self.window.bounds.size.width / 2 - 15, self.window.bounds.size.height / 2 - 30, 30, 30)];
activityWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
activityWheel.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
[activityView1 addSubview:activityWheel];
[activityWheel release];
}
[self.window addSubview: activityView1];
[[[activityView1 subviews] objectAtIndex:0] setText:msg];
[[[activityView1 subviews] objectAtIndex:1] startAnimating];
}
Every time whenever you need to show activity indicator in the whole use this...It automatically manages all the things
To hide the indicator call this method,same in the AppDelegate.m class
-(void)hideActivityViewer
{
[[[activityView1 subviews] objectAtIndex:1] stopAnimating];
[activityView1 removeFromSuperview];
}