18

我想在加载数据时(在另一个线程中)在 uitableview 上显示一个活动指示器。所以在 UITableViewController 的 ViewDidLoad 方法中:

-(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];
      });
    });
   .......

为什么活动指示器不显示在表格视图上?我怎样才能实现它?

4

5 回答 5

21

您需要将 UIActivityIndi​​catorView 添加到某些东西。您可以将其添加到 UITableView 标题视图。为此,您需要提供自己的自定义视图。

...
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
[view addSubview:ac]; // <-- Your UIActivityIndicatorView
self.tableView.tableHeaderView = view;
...
于 2012-04-28T11:45:24.523 回答
12

我一直在努力寻找解决方案并阅读了很多论坛,但我没有得到我想要的。在了解了活动指示器和表格视图控制器的工作原理后,我想出了以下解决方案。

出于某种原因,如果您尝试使用 tableReload 或任何其他昂贵的进程在同一线程上启动活动指示器,则活动指示器永远不会运行。如果您尝试在另一个线程中运行 table reload 或其他一些操作,那么它可能不安全并且可能会产生错误或不需要的结果。所以我们可以在另一个线程上运行显示活动指示器的方法。

我还将此解决方案与 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];
}
于 2012-05-23T07:24:37.687 回答
6

[iOS 5 +]
如果你只想显示activityWheel而不需要额外的父视图,你也可以直接将activityWheel添加到tableView中,并使用tableViews contentOffset计算框架的y值:

@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 的回答或在后台执行繁重的工作。

于 2013-10-22T14:49:36.320 回答
4

UIViewController 有解决方法。(您可以使用带有表格视图的 UIViewController 来实现 UITableViewController。)在 storyboard 中,在 UIViewController 的视图中添加一个 activityIndi​​cator。然后在 viewDidLoad 中添加以下内容:

[self.activityIndicator layer].zPosition = 1;

activityIndi​​cator 将显示在表格视图上。

于 2015-03-27T15:04:21.317 回答
-1

[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]
于 2015-10-05T12:49:28.543 回答