blrsk
blrsk

Reputation: 345

How can I replace the text in a round rect button with a spinner?

I have a view with a generic rounded rect button that segues to another view. When users press the rounded rect it starts a fetch. I would like to have a spinning wheel replace the text ("Next") inside the rounded rect button while the fetch is processed.

I created the spinner:

UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];

But I don't know how to make it replace the text in the rounded rect button.

Any suggestion? Thank you.

Upvotes: 4

Views: 2525

Answers (2)

Rey Gonzales
Rey Gonzales

Reputation: 866

I wrote a category that utilizes associated objects

UIButton+ActivityIndicator.h

// Created by reynaldo on 1/16/14.

#import <Foundation/Foundation.h>

@interface UIButton (ActivityIndicator)
- (void)startActivityIndicator;
- (void)stopActivityIndicator;
@end

UIButton+ActivityIndicator.m

// Created by reynaldo on 1/16/14.

#import <objc/runtime.h>
#import "UIButton+ActivityIndicator.h"

static char TITLE_KEY;
static char ACTIVITY_INDICATOR_KEY;

@implementation UIButton (ActivityIndicator)

- (void)startActivityIndicator {
    objc_setAssociatedObject(self, &TITLE_KEY, self.currentTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    [self setTitle:@"" forState:UIControlStateNormal];
    UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    [self addSubview:activityIndicatorView];
    activityIndicatorView.frame = CGRectMake(self.frame.size.width / 2, self.frame.size.height / 2. - 2, 7, 7);
    [activityIndicatorView startAnimating];

    objc_setAssociatedObject(self, &ACTIVITY_INDICATOR_KEY, activityIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (void)stopActivityIndicator {
    NSString *title = objc_getAssociatedObject(self, &TITLE_KEY);
    UIActivityIndicatorView *activityIndicatorView = objc_getAssociatedObject(self, &ACTIVITY_INDICATOR_KEY);

    if(activityIndicatorView) {
        [activityIndicatorView removeFromSuperview];
    }

    if(title.length) {
        [self setTitle:title forState:UIControlStateNormal];
    }
}

@end

Upvotes: 1

Martin Kenny
Martin Kenny

Reputation: 2498

Create (or get a reference to) the button as usual, then, while handling the button click, create your spinner and set it as a subview of the button. It's probably also worth disabling the button to stop multiple clicks.

Something along the following lines should do the trick:

  ...
  UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  button.frame = CGRectMake(10, 10, 70, 40);
  [button setTitle:@"Next" forState:UIControlStateNormal];
  [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:button];
  ...

- (void)click:(UIButton *)button {
  [button setTitle:@"" forState:UIControlStateNormal];
  UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  [spinner startAnimating];
  spinner.frame = button.bounds;
  [button addSubview:spinner];
  button.enabled = NO;

  // do your actual work...
}

Upvotes: 7

Related Questions