Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add Progress bar to UIAlertController?

I want to add progress bar in swift iOS 8 UIAlertController. Is this possible? Is there any way to subclass UIAlertController and add progres bar and connect some delegate functions?

thanks

like image 243
Nik Avatar asked Jul 28 '15 18:07

Nik


4 Answers

If you just need a progressbar you can simply add it as a subview as follows:

Updated for Swift 5:

//  Just create your alert as usual:
let alertView = UIAlertController(title: "Please wait", message: "Need to download some files.", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

//  Show it to your users
present(alertView, animated: true, completion: {
    //  Add your progressbar after alert is shown (and measured)
    let margin:CGFloat = 8.0
    let rect = CGRect(x: margin, y: 72.0, width: alertView.view.frame.width - margin * 2.0 , height: 2.0)
    self.progressView = UIProgressView(frame: rect)
    self.progressView!.progress = 0.5
    self.progressView!.tintColor = self.view.tintColor
    alertView.view.addSubview(self.progressView!)
})

Swift 2.0:

//  Just create your alert as usual:
let alertView = UIAlertController(title: "Please wait", message: "Need to download some files.", preferredStyle: .Alert)
alertView.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))

//  Show it to your users
presentViewController(alertView, animated: true, completion: {
    //  Add your progressbar after alert is shown (and measured)
    let margin:CGFloat = 8.0
    let rect = CGRectMake(margin, 72.0, alertView.view.frame.width - margin * 2.0 , 2.0)
    let progressView = UIProgressView(frame: rect)
    progressView.progress = 0.5
    progressView.tintColor = UIColor.blueColor()
    alertView.view.addSubview(progressView)
})

It's quite difficult to resize the UIAlertController for bigger content but for a progressbar this should do the trick.

like image 130
coyer Avatar answered Nov 06 '22 22:11

coyer


A solution with auto layout:

    UIAlertController *alertCtr = [UIAlertController alertControllerWithTitle:@"Test" message:@"50%" preferredStyle:UIAlertControllerStyleAlert];
    [alertCtr addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        // Do things
    }]];

    UIView *alertView = alertCtr.view;

    UIProgressView *progressView = [[UIProgressView alloc] initWithFrame:CGRectZero];
    progressView.progress = 0.5;
    progressView.translatesAutoresizingMaskIntoConstraints = false;
    [alertView addSubview:progressView];


    NSLayoutConstraint *bottomConstraint = [progressView.bottomAnchor constraintEqualToAnchor:alertView.bottomAnchor];
    [bottomConstraint setActive:YES];
    bottomConstraint.constant = -45; // How to constraint to Cancel button?

    [[progressView.leftAnchor constraintEqualToAnchor:alertView.leftAnchor] setActive:YES];
    [[progressView.rightAnchor constraintEqualToAnchor:alertView.rightAnchor] setActive:YES];

    [self presentViewController:alertCtr animated:true completion:nil];

enter image description here

like image 35
Dong Phong Avatar answered Nov 06 '22 21:11

Dong Phong


My apologies, guys, for using objective c, in this solution, but I thought it might help others, who do not use Swift yet. And, also, you can probably convert this quite easily into Swift. It is more the methodology I wanted to highlight.

I am also not sure whether Apple might reject this solution, but here goes anyway.

Apple states that from iOS7 onwards, UIAlertView should not be subclassed. The view hierarchy for this class is private and must not be modified:

https://developer.apple.com/reference/uikit/uialertview?language=objc

In other words, adding a UIView to a UIAlertView has absolutely no effect.

However, I have a solution that involves adding the UIProgressView above the UIAlertView, but adding the former to the app window. Using the UIView superview.center property, and some slight adjustments, the desired affect can be achieved:

-(void)addProgressBar{
    float width = 232;
    float height = 5;
    self.progbar = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    self.progbar.backgroundColor = [UIColor colorWithWhite:0.75f alpha:1.0f];
    [self.progbar setFrame:CGRectMake(0,0,width,height)];
    [self.progbar setTrackTintColor:[UIColor colorWithWhite:0.75f alpha:1.0f]];
    [self.progbar setProgressTintColor:[UIColor colorWithRed:21.0f/255.0f green:126.0f/255.0f blue:251.0f/255.0f alpha:1.0f]];
    self.progbar.alpha = 0.0;
    [[UIApplication sharedApplication].keyWindow addSubview:self.progbar];
    self.progbar.center = self.progbar.superview.center;
    [self.progbar setFrame:CGRectMake(self.progbar.frame.origin.x,self.progbar.frame.origin.y+10,self.progbar.frame.size.width,self.progbar.frame.size.height)];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:2.0];
    [self.progbar setAlpha:1.0];
    [UIView commitAnimations];
}

I add the fade in, to allow the UIAlertView to fully appear first. Then add some other delegate functions to dismiss the UIProgressView, at the correct moments:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if(self.alert.cancelButtonIndex == buttonIndex){
        [self.progbar removeFromSuperview];
    }
}

- (void)alertViewCancel:(UIAlertView *)alertView{
    [self.progbar removeFromSuperview];
}

enter image description here

like image 4
Charles Robertson Avatar answered Nov 06 '22 22:11

Charles Robertson


func downloadAlert() {
        let alertController = UIAlertController(title: "Title", message: "Loading...", preferredStyle: .Alert)

        let progressDownload : UIProgressView = UIProgressView(progressViewStyle: .Default)

        progressDownload.setProgress(5.0/10.0, animated: true)
        progressDownload.frame = CGRect(x: 10, y: 70, width: 250, height: 0)

    alertController.view.addSubview(progressDownload)
    presentViewController(alertController, animated: true, completion: nil)
}
like image 2
Chea Sambath Avatar answered Nov 06 '22 21:11

Chea Sambath