Подтвердить что ты не робот

Как отобразить индикатор активности в центре UIAlertController?

В настоящее время на экране отображается UIAlertController. В представлении предупреждения должны отображаться только два элемента, заголовок и UIActivityIndicatorView в центре предупреждения. Ниже приведена функция, отображающая предупреждение и его элементы.

func displaySignUpPendingAlert() -> UIAlertController {
        //Create the UIAlertController
        let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .Alert)
        //Create the activity indicator to display in it.
        let indicator = UIActivityIndicatorView(frame: CGRectMake(pending.view.frame.width / 2.0, pending.view.frame.height / 2.0, 20.0, 20.0))
        indicator.center = CGPointMake(pending.view.frame.width / 2.0, pending.view.frame.height / 2.0)
        //Add the activity indicator to the alert view
        pending.view.addSubview(indicator)
        //Start animating
        indicator.startAnimating()

        self.presentViewController(pending, animated: true, completion: nil)
        return pending
    }

Однако индикатор активности не отображается в центре представления, на самом деле он отображается в правом нижнем углу экрана, вдали от представления. В чем причина этого?

EDIT: Я понимаю, что я могу кодировать цифры для позиции индикатора, но я хочу, чтобы предупреждение работало на нескольких устройствах с несколькими размерами экрана и ориентациями.

4b9b3361

Ответ 1

Обязательно установите свойство frame при создании представления.

func displaySignUpPendingAlert() -> UIAlertController {
        //create an alert controller
        let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .Alert)

        //create an activity indicator
        let indicator = UIActivityIndicatorView(frame: pending.view.bounds)
        indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        //add the activity indicator as a subview of the alert controller view
        pending.view.addSubview(indicator)
        indicator.isUserInteractionEnabled = false // required otherwise if there buttons in the UIAlertController you will not be able to press them
        indicator.startAnimating()

        self.presentViewController(pending, animated: true, completion: nil)

        return pending
}

To @62Shark:

let pending = UIAlertController(title: "Creating New User", message: nil, preferredStyle: .Alert)

let indicator = UIActivityIndicatorView()
indicator.setTranslatesAutoresizingMaskIntoConstraints(false)
pending.view.addSubview(indicator)

let views = ["pending" : pending.view, "indicator" : indicator]
var constraints = NSLayoutConstraint.constraintsWithVisualFormat("V:[indicator]-(-50)-|", options: nil, metrics: nil, views: views)
constraints += NSLayoutConstraint.constraintsWithVisualFormat("H:|[indicator]|", options: nil, metrics: nil, views: views)
pending.view.addConstraints(constraints)

indicator.userInteractionEnabled = false
indicator.startAnimating()

self.presentViewController(pending, animated: true, completion: nil)

Ответ 2

Я обратился к Objective C, если кто-то заинтересован:

UIAlertController *pending = [UIAlertController alertControllerWithTitle:nil
                                                               message:@"Please wait...\n\n"
                                                        preferredStyle:UIAlertControllerStyleAlert];
UIActivityIndicatorView* indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.color = [UIColor blackColor];
indicator.translatesAutoresizingMaskIntoConstraints=NO;
[pending.view addSubview:indicator];
NSDictionary * views = @{@"pending" : pending.view, @"indicator" : indicator};

NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views];
NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views];
NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal];
[pending.view addConstraints:constraints];
[indicator setUserInteractionEnabled:NO];
[indicator startAnimating];
[self presentViewController:pending animated:YES completion:nil];

Приветствия

Ответ 3

Для тех, кто предпочитает UIActivityIndicatorView, выровненный слева от UIAlertController.title, это мое решение в Swift для всех устройств:

let alert = UIAlertController(title: NSLocalizedString("Authenticating...", comment: "Authenticating"), message: nil, preferredStyle: .Alert);
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activityIndicator.frame = activityIndicator.frame.rectByOffsetting(dx: 8, dy: (alert.view.bounds.height - activityIndicator.frame.height)/2);
activityIndicator.autoresizingMask = .FlexibleRightMargin | .FlexibleTopMargin | .FlexibleBottomMargin
activityIndicator.color = themeManager().currentTheme.navigationBarTintColor;
activityIndicator.startAnimating();
alert.view.addSubview(activityIndicator);
self.presentViewController(progressAlert, animated: true, completion: nil);

Однако для выравнивания UIActivityIndicatorView в центре просмотра вы можете изменить следующее:

activityIndicator.center = CGPoint(x: (alert.view.bounds.width)/2, y: (alert.view.bounds.height)/2)
activityIndicator.autoresizingMask = .FlexibleLeftMargin | .FlexibleRightMargin | .FlexibleTopMargin | .FlexibleBottomMargin

Ответ 4

Apple не поощряет напрямую подклассифицировать UIAlertController, поэтому я создал класс, который отображает UIAlertController с центрированным идентификатором UIActivityIndicator и обрабатывает условие отмены с помощью протокола класса.

import Foundation
import UIKit

protocol BusyAlertDelegate {
    func didCancelBusyAlert()
}


class BusyAlert {

   var busyAlertController: UIAlertController?
   var presentingViewController: UIViewController?
   var activityIndicator: UIActivityIndicatorView?
   var delegate:BusyAlertDelegate?

   init (title:String, message:String, presentingViewController: UIViewController) {
       busyAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
       busyAlertController!.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "Cancel Button"), style: UIAlertActionStyle.Cancel, handler:{(alert: UIAlertAction!) in
            delegate?.didCancelBusyAlert()
    }))
        self.presentingViewController = presentingViewController
        activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
        busyAlertController!.view.addSubview(activityIndicator!)
    }

    func display() {
        dispatch_async(dispatch_get_main_queue(), {
               self.presentingViewController!.presentViewController(self.busyAlertController!, animated: true, completion: {
            self.activityIndicator!.translatesAutoresizingMaskIntoConstraints = false
               self.busyAlertController!.view.addConstraint(NSLayoutConstraint(item: self.activityIndicator!, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.busyAlertController!.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
            self.busyAlertController!.view.addConstraint(NSLayoutConstraint(item: self.activityIndicator!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.busyAlertController!.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
            self.activityIndicator!.startAnimating()

        })
    })

}

func dismiss() {
    dispatch_async(dispatch_get_main_queue(), {
        self.busyAlertController?.dismissViewControllerAnimated(true, completion: nil)
    })
}

}

Я рекомендую использовать lazy var для инициализации класса.

lazy var busyAlertController: BusyAlert = {
        let busyAlert = BusyAlert(title: "Lengthy Task", message: "Please     wait...", presentingViewController: self)
        busyAlert.delegate = self
        return busyAlert
        }()

Вот ссылка на пример кода: https://github.com/cgilleeny/BusyAlertExample.git

Ответ 5

Хорошо попробуйте этот код.

UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
                                    message:@"Creating new user\n\n\n"
                             preferredStyle:UIAlertControllerStyleAlert];

UIActivityIndicatorView *loader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
loader.center = CGPointMake(130.5, 65.5);
loader.color = [UIColor blackColor];
[loader startAnimating];
[alert.view loader];
[self presentViewController:alert animated:NO completion:nil];

Ответ 6

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/frame

Прямоугольник рамки, который описывает расположение и размер точек в системе координат супервизора. что ваш pending.view.frame == CGRect (0,0,0,0)

Нужно установить индикаторный центр в блок завершения там, когда ваше оповещение будет иметь супервизор

self.presentViewController(pending, animated: true, completion: nil)

Ответ 7

Мне нужно реализовать NSLayoutConstraint, чтобы поместить UIActivityIndicatorView в центр UIAlertController

Для Swift 3:

let loadingAlertController = UIAlertController(title: "Loading", message: nil, preferredStyle: .alert)


let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)

activityIndicator.translatesAutoresizingMaskIntoConstraints = false


loadingAlertController.view.addSubview(activityIndicator)


let xConstraint = NSLayoutConstraint(item: activityIndicator, attribute: .centerX, relatedBy: .equal, toItem: loadingAlertController.view, attribute: .centerX, multiplier: 1, constant: 0)


let yConstraint = NSLayoutConstraint(item: activityIndicator, attribute: .centerY, relatedBy: .equal, toItem: loadingAlertController.view, attribute: .centerY, multiplier: 1.4, constant: 0)


NSLayoutConstraint.activate([ xConstraint, yConstraint])


activityIndicator.isUserInteractionEnabled = false

activityIndicator.startAnimating()


let height: NSLayoutConstraint = NSLayoutConstraint(item: loadingAlertController.view, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 80)


loadingAlertController.view.addConstraint(height);


self.present(loadingAlertController, animated: true, completion: nil)

Ответ 8

Попробуйте следующее:

activityView.center = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height / 2.0)

Также вам нужно будет проверить пейзаж и реверс ширины и высоты.

if(landscapeMode)activityView.center = CGPointMake(self.view.bounds.size.height/2.0, self.view.bounds.size.width / 2.0)

Может быть, вы можете получить позицию просмотра предупреждения?

alert.view.frame.origin.x
alert.view.frame.origin.y

и использовать это для динамического отображения вашего вида активности, т.е. с помощью переменных?

Конечно, вы также можете захотеть разделить размер на 2 и добавить его так, чтобы он тоже центрировался.

alert.view.frame.size.height
alert.view.frame.size.width

Ответ 9

В быстрой:

activityIndicator.center = self.view.center

Если у вас есть панель инструментов или navController, вы можете переместить точку, но в противном случае центр будет центром...

Если у вас все еще есть проблемы, возможно, этот пособие поможет. Если вы пытаетесь центрировать его в контроллере табличного представления, этот ответ может помочь.

Ответ 10

У меня была такая же проблема, и использование фреймов не помогло мне. Ответ Yimin Lin был очень близок для меня, но я просто хотел представить альтернативу, используя ограничения в не визуальном формате:

//...
indicator.setTranslatesAutoresizingMaskIntoConstraints(false)
alert.view.addSubview(indicator)

alert.view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: alert.view, attribute: attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
alert.view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: alert.view, attribute: attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
//...

Ответ 11

Конвертированный ответ @petesalt на Swift 3:

let pending = UIAlertController(title: "Saving, please wait...", message: nil, preferredStyle: .alert)

let indicator = UIActivityIndicatorView()
indicator.translatesAutoresizingMaskIntoConstraints = false
pending.view.addSubview(indicator)

let views = ["pending" : pending.view, "indicator" : indicator]

var constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[indicator]-(-50)-|", options: NSLayoutFormatOptions.alignAllCenterY, metrics: nil, views: views)
constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[indicator]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: views)
pending.view.addConstraints(constraints)

indicator.isUserInteractionEnabled = false
indicator.startAnimating()

self.present(pending, animated: true, completion: nil)