IOS: ActivityIndicator над UITableView... Как?
Я хочу отображать индикатор активности над uitableview при загрузке данных (в другом потоке). Итак, в методе ViewDidLoad для UITableViewController:
-(void)viewDidLoad
{
[super viewDidLoad];
//I create the activity indicator
UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[ac startAnimating];
//Create the queue to download data from internet
dispatch_queue_t downloadQueue = dispatch_queue_create("PhotoDownload",NULL);
dispatch_async(downloadQueue, ^{
//Download photo
.......
.......
dispatch_async(dispatch_get_main_queue(), ^{
......
......
[ac stopAnimating];
});
});
.......
Почему индикатор активности не отображается над табличным представлением? Как я могу это достичь?
Ответы
Ответ 1
Вам нужно добавить UIActivityIndicatorView. Вы можете добавить его в представление заголовка UITableView. Для этого вам нужно будет предоставить собственное пользовательское представление.
...
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
[view addSubview:ac]; // <-- Your UIActivityIndicatorView
self.tableView.tableHeaderView = view;
...
Ответ 2
Я пытался найти решение для этого и прочитал много форумов, но я не получил то, что хотел. Поняв, как работает индикатор активности и контроллер табличного представления, я придумал следующее решение.
По какой-то причине, если вы попытаетесь запустить индикатор активности в том же потоке с помощью tableReload или любого другого дорогостоящего процесса, индикатор активности никогда не запускается. Если вы попытаетесь запустить перезагрузку таблицы или какую-либо другую операцию в другом потоке, это может быть небезопасно и может привести к ошибкам или нежелательным результатам. Таким образом, мы можем запустить метод, который отображает индикатор активности в другом потоке.
Я также объединил это решение с MBProgressHUD, чтобы представить что-то более приятное, чем представление с индикатором активности. В любом случае внешний вид ActivityView можно настроить.
-(void)showActivityViewer
{
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
UIWindow *window = delegate.window;
activityView = [[UIView alloc] initWithFrame: CGRectMake(0, 0, window.bounds.size.width, window.bounds.size.height)];
activityView.backgroundColor = [UIColor blackColor];
activityView.alpha = 0.5;
UIActivityIndicatorView *activityWheel = [[UIActivityIndicatorView alloc] initWithFrame: CGRectMake(window.bounds.size.width / 2 - 12, window.bounds.size.height / 2 - 12, 24, 24)];
activityWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
activityWheel.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
[activityView addSubview:activityWheel];
[window addSubview: activityView];
[[[activityView subviews] objectAtIndex:0] startAnimating];
}
-(void)hideActivityViewer
{
[[[activityView subviews] objectAtIndex:0] stopAnimating];
[activityView removeFromSuperview];
activityView = nil;
}
- (IBAction)reloadDataAction:(id)sender {
[NSThread detachNewThreadSelector:@selector(showActivityViewer) toTarget:self withObject:nil];
//... do your reload or expensive operations
[self hideActivityViewer];
}
Ответ 3
[iOS 5 +]
Если вы просто хотите показать ActivityWheel без дополнительного родительского представления, вы также можете добавить ActivityWheel прямо в tableView и вычислить значение y для фрейма с помощью tableViews contentOffset:
@interface MyTableViewController ()
@property (nonatomic, strong) UIActivityIndicatorView *activityView;
@end
// ....
- (void) showActivityView {
if (self.activityView==nil) {
self.activityView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
[self.tableView addSubview:self.activityView];
self.activityView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
self.activityView.hidesWhenStopped = YES;
// additional setup...
// self.activityView.color = [UIColor redColor];
}
// Center
CGFloat x = UIScreen.mainScreen.applicationFrame.size.width/2;
CGFloat y = UIScreen.mainScreen.applicationFrame.size.height/2;
// Offset. If tableView has been scrolled
CGFloat yOffset = self.tableView.contentOffset.y;
self.activityView.frame = CGRectMake(x, y + yOffset, 0, 0);
self.activityView.hidden = NO;
[self.activityView startAnimating];
}
- (void) hideActivityView {
[self.activityView stopAnimating];
}
Если ActivityView не отображается сразу (или никогда), обратитесь к zirinisp answer или выполните тяжелую работу в фоновом режиме.
Ответ 4
Обходной путь для UIViewController. (Вы можете использовать UIViewController с табличным представлением, чтобы получить UITableViewController.)
В раскадровке добавьте ActivityIndicator в представлении UIViewController.
Затем в viewDidLoad добавьте следующее:
[self.activityIndicator layer].zPosition = 1;
Идентификатор активности будет отображаться над табличным представлением.
Ответ 5
Несмотря на то, что вопрос довольно старый, я добавляю и мой.
[IOS 8+]
Вышеупомянутое не работает для меня. Вместо этого я храню
вид индикатора (ac) в классе.
Тогда я делаю:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (ac.isAnimating)
return 50.0f;
return 0.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (ac.isAnimating)
return ac;
return nil;
}
Для показа индикатора я делаю
[ac startAnimating]
Чтобы скрыть это, я делаю
[ac stopAnimating]
Я надеюсь, что это кому-то поможет.