Adding UIActivityIndicator to UITableView

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-20 06:22:02

问题


I need to load some data in a table view and while this is going on in the background I want to add an activity indicator in order to show that there is a process going on and will hide once the process finishes. What would be the most efficient way to implement something like this?


回答1:


Depends, whether you want to block your user or not and also how important is the activity indication.

If you don't want to block user, use Application.networkActivityIndicatorVisible, if you want to have larger activity indicator and still not to block user, animate UIView with text and UIActivityIndicator below the table view (tableview.height -= activityview.height) and then hide on complete or if you would like to block user, use blocking activity indicator.

  • http://www.dejal.com/developer/?q=developer/dsactivityview
  • https://github.com/jdg/MBProgressHUD (I was using MBProgressHUD personally and it's easy to learn and use)



回答2:


You can add a view which has a UIIndicatorView and a UILabel as your cell's subview. You can use this way to show error data loading/ error network/ empty data...

Example:

Your Controller can define two modes: UITableViewModeMessage and UITableViewModeData.

In viewDidLoad, you set self.tableViewMode = UITableViewModeMessage. When has returned data, set self.tableViewMode = UITableViewModeData and reload data for tableview.

Some code:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    if (self.tableViewMode == UITableViewModeMessage) {
        return 2;
    } else {
        return self.yourEntries ? self.yourEntries.count : 0;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    if (self.tableViewMode == UITableViewModeMessage) {
        return [self tableView:tableView messageCellForRowAtIndexPath:indexPath];
    } else {
        return [self tableView:tableView dataCellForRowAtIndexPath:indexPath];
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove Loading... progress view if exist.
    UIView *progressView = [cell viewWithTag:100];
    [progressView removeFromSuperview];

    if (self.tableViewMode == UITableViewModeMessage) {        
        if (indexPath.row == 1) {
            // remove the current label.
            cell.textLabel.text = nil;

            // We build progress view and attach to cell here but not in cellForRowAtIndexPath is because in this method cell frame is already calculated.
            UIView *progressView = [self progressViewForCell:cell message:@"Loading..." alpha:0.9];
            [cell addSubview:progressView];
        }
    }
}


// cell to display when loading
- (UITableViewCell *)tableView:(UITableView *)tableView messageCellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MessageCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.textLabel.textColor = [UIColor grayColor];
        cell.textLabel.textAlignment = UITextAlignmentCenter;
    }

    if (indexPath.row == 1) {
        cell.textLabel.text = @"Loading...";
    } else {
        cell.textLabel.text = nil;
    }

    return cell;
}

// cell to display when has data
- (UITableViewCell *)tableView:(UITableView *)tableView dataCellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    static NSString *CellIdentifier = @"DataCell";

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [[self.yourEntries objectAtIndex:indexPath.row] description];

    return cell;
}

// Build a view which has a UIActivityIndicatorView and a UILabel
- (UIView *)progressViewForCell:(UITableViewCell *)cell message:(NSString *)message alpha:(CGFloat)alpha
{
    // NOTE: progressView needs to be removed from cell in cellForRowAtIndexPath:
    CGRect progressViewFrame = CGRectZero;
    progressViewFrame.size.width = CGRectGetMaxX(cell.bounds);
    progressViewFrame.size.height = CGRectGetMaxY(cell.bounds) - 2;

    UIView *progressView = [[UIView alloc] initWithFrame:progressViewFrame];
    progressView.backgroundColor = RGBA(255, 255, 255, 1);
    progressView.alpha = alpha;
    progressView.tag = 100;

    UILabel *loadingLabel = [[UILabel alloc] initWithFrame:progressView.bounds];
    loadingLabel.backgroundColor = [UIColor clearColor];
    loadingLabel.font = [UIFont systemFontOfSize:14];
    loadingLabel.textColor = [UIColor blackColor];
    loadingLabel.textAlignment = UITextAlignmentCenter;
    loadingLabel.text = message;

    CGFloat widthOfText = [loadingLabel.text sizeWithFont:loadingLabel.font].width;
    CGFloat spaceBetweenIndicatorAndLabel = 5;

    // activityIndicatorView has size in which width and height is equal to 20.
    UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [activityIndicatorView setCenter:CGPointMake(CGRectGetMidX(cell.bounds) - (widthOfText / 2) - (activityIndicatorView.bounds.size.width / 2) - spaceBetweenIndicatorAndLabel, CGRectGetMidY(cell.bounds))]; 
    [activityIndicatorView setColor:[UIColor blackColor]];
    [activityIndicatorView startAnimating];

    [progressView addSubview:activityIndicatorView];
    [progressView addSubview:loadingLabel];

    return progressView;
}


来源:https://stackoverflow.com/questions/11747926/adding-uiactivityindicator-to-uitableview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!