Domanda

Uso un UISearchBar per inserire un indirizzo per stabilire una connessione di rete. Mentre viene stabilita la connessione, voglio mostrare l'indicatore di attività anziché il minuscolo BookmarkButton sul lato destro della barra di ricerca. Per quanto posso vedere non ci sono proprietà dichiarate pubbliche che mi darebbero accesso alla subview corretta della barra di ricerca. Ho visto questo fatto, qualche pensiero?

È stato utile?

Soluzione

Che ne dici di sostituire l'icona di ricerca sul lato sinistro con un indicatore di attività mentre sono in corso ricerche o connessioni?

SearchBarWithActivity.h:

#import <UIKit/UIKit.h>

@interface SearchBarWithActivity : UISearchBar

- (void)startActivity;  // increments startCount and shows activity indicator
- (void)finishActivity; // decrements startCount and hides activity indicator if 0

@end

SearchBarWithActivity.m:

#import "SearchBarWithActivity.h"

@interface SearchBarWithActivity()

@property(nonatomic) UIActivityIndicatorView *activityIndicatorView;
@property(nonatomic) int startCount;

@end


@implementation SearchBarWithActivity

- (void)layoutSubviews {
    UITextField *searchField = nil;

    for(UIView* view in self.subviews){
        if([view isKindOfClass:[UITextField class]]){
            searchField= (UITextField *)view;
            break;
        }
    }

    if(searchField) {
        if (!self.activityIndicatorView) {
            UIActivityIndicatorView *taiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            taiv.center = CGPointMake(searchField.leftView.bounds.origin.x + searchField.leftView.bounds.size.width/2,
                                      searchField.leftView.bounds.origin.y + searchField.leftView.bounds.size.height/2);
            taiv.hidesWhenStopped = YES;
            taiv.backgroundColor = [UIColor whiteColor];
            self.activityIndicatorView = taiv;
            [taiv release];
            _startCount = 0;

            [searchField.leftView addSubview:self.activityIndicatorView];
        }
    }

    [super layoutSubviews];
}

- (void)startActivity  {
    self.startCount = self.startCount + 1;
}

- (void)finishActivity {
    self.startCount = self.startCount - 1;
}

- (void)setStartCount:(int)startCount {
    _startCount = startCount;
    if (_startCount > 0)
        [self.activityIndicatorView startAnimating];
    else {
        [self.activityIndicatorView stopAnimating];
    }
}

@end

Altri suggerimenti

Ho aggiornato la risposta da @JohnLemberger per lavorare con iOS 7 (nota: l'ho provato solo su iOS 7), nonché un riepilogo delle mie modifiche:

NOTA: questo non è un codice molto robusto all'inizio, poiché Apple può cambiare la gerarchia di visualizzazione di UISearchBar in qualsiasi versione (come hanno fatto tra iOS 6 e 7).

SearchBarWithActivity.h (nulla è cambiato):

@interface SearchBarWithActivity : UISearchBar

- (void)startActivity;  // increments startCount and shows activity indicator
- (void)finishActivity; // decrements startCount and hides activity indicator if 0

@end

@interface XXTreatmentHeaderViewController : XXViewController

@property (nonatomic, strong, readonly) SearchBarWithActivity *searchBar;

@end

SearchBarWithActivity.m:

1) Mostra / nascondi la "lente d'ingrandimento" icona quando appare l'indicatore di attività

2) Aggiungi profondità nella ricerca della gerarchia della vista per UITextField

@interface SearchBarWithActivity()

@property(nonatomic) UIActivityIndicatorView *activityIndicatorView;
@property(nonatomic) int startCount;

@end

@implementation SearchBarWithActivity

- (void)layoutSubviews {
    UITextField *searchField = nil;

    for(UIView* view in self.subviews){

        // on iOS 6, the UITextField is one-level deep
        if ([view isKindOfClass:[UITextField class]]){
            searchField= (UITextField *)view;
            break;
        }

        // on iOS 7, the UITextField is two-levels deep
        for (UIView *secondLevelSubview in view.subviews) {
            if([secondLevelSubview isKindOfClass:[UITextField class]]){
                searchField= (UITextField *)secondLevelSubview;
                break;
            }
        }
    }

    if(searchField) {
        if (!self.activityIndicatorView) {
            UIActivityIndicatorView *taiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            taiv.center = CGPointMake(searchField.leftView.bounds.origin.x + searchField.leftView.bounds.size.width/2,
                                      searchField.leftView.bounds.origin.y + searchField.leftView.bounds.size.height/2);
            taiv.hidesWhenStopped = YES;
            self.activityIndicatorView = taiv;
            _startCount = 0;

            [searchField.leftView addSubview:self.activityIndicatorView];
        }
    }

    [super layoutSubviews];
}

- (void)startActivity  {
    self.startCount = self.startCount + 1;
}

- (void)finishActivity {
    self.startCount = self.startCount - 1;
}

- (void)setStartCount:(int)startCount {
    _startCount = startCount;
    if (_startCount > 0) {
        [self.activityIndicatorView startAnimating];
        // Remove the "magnifying glass icon"
        [self setImage:[UIImage new] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    } else {
        [self.activityIndicatorView stopAnimating];
        // Restore the "magnifying glass icon"
        [self setImage:nil forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    }
}

@end

Ho implementato una categoria per UISearchBar che mostra un UIActivityIndicatorView , a seconda dello stato dell'operazione di richiesta di AFNetworking o dell'attività di sessione https://gist.github.com/nguyenhuy/a11d15c11200477b05a6 .

Solo per la cronaca:

for(UIView* view in self.subviews){
    if([view isKindOfClass:[UITextField class]]){
       searchField=view;
       break;
    }
}

if(searchField !=)) {
   searchField.leftView = myCustomView;
}

Puoi sottoclassare UISearchBar e chiamare questo codice nel metodo layoutSubview. chiamando questo codice in layoutSubview si assicura che le animazioni di ridimensionamento funzionino correttamente.

Aggiornamento risposta di jonsibley aggiungendo il supporto per i casi in cui una UISearchBar è incorporata in una UINavigationBar usando displaySearchBarInNavigationBar flag.

SearchBarWithActivity.h (aggiunta una nuova proprietà):

@interface SearchBarWithActivity : UISearchBar

- (void)startActivity;  // increments startCount and shows activity indicator
- (void)finishActivity; // decrements startCount and hides activity indicator if 0

@property (nonatomic,assign) UINavigationItem *navigationItem;

@end

SearchBarWithActivity.m (ottieni il campo di ricerca dall'elemento di navigazione se non nullo):

#import "SearchBarWithActivity.h"

@interface SearchBarWithActivity()

@property(nonatomic) UIActivityIndicatorView *activityIndicatorView;
@property(nonatomic) int startCount;

@end

@implementation SearchBarWithActivity

@synthesize navigationItem;

- (void)layoutSubviews {
    UITextField *searchField = nil;

    if(self.navigationItem) {
        searchField = (UITextField *)[self.navigationItem titleView];
    } else {
        for(UIView* view in self.subviews){

            // on iOS 6, the UITextField is one-level deep
            if ([view isKindOfClass:[UITextField class]]){
                searchField= (UITextField *)view;
                break;
            }

            // on iOS 7, the UITextField is two-levels deep
            for (UIView *secondLevelSubview in view.subviews) {
                if([secondLevelSubview isKindOfClass:[UITextField class]]){
                    searchField= (UITextField *)secondLevelSubview;
                    break;
                }

            }
        }
    }

    if(searchField) {
        if (!self.activityIndicatorView) {
            UIActivityIndicatorView *taiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
            taiv.center = CGPointMake(searchField.leftView.bounds.origin.x + searchField.leftView.bounds.size.width/2,
                                      searchField.leftView.bounds.origin.y + searchField.leftView.bounds.size.height/2);
            taiv.hidesWhenStopped = YES;
            self.activityIndicatorView = taiv;
            _startCount = 0;

            [searchField.leftView addSubview:self.activityIndicatorView];
        }
    }

    [super layoutSubviews];
}

- (void)startActivity  {
    self.startCount = self.startCount + 1;
}

- (void)finishActivity {
    self.startCount = self.startCount - 1;
}

- (void)setStartCount:(int)startCount {
    _startCount = startCount;
    if (_startCount > 0) {
        [self.activityIndicatorView startAnimating];
        // Remove the "magnifying glass icon"
        [self setImage:[UIImage new] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    } else {
        [self.activityIndicatorView stopAnimating];
        // Restore the "magnifying glass icon"
        [self setImage:nil forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
    }
}

@end

Nel ViewController:

#import "SearchBarWithActivity.h"

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Embed the search bar into NavigationBar and setup the navigation item in order to show the spinner
    [self.searchDisplayController setDisplaysSearchBarInNavigationBar:YES];
    [(SearchBarWithActivity *)self.searchDisplayController.searchBar setNavigationItem:self.navigationItem];
}

Spero che questo faccia risparmiare tempo a qualcuno.

Poiché sembra che la profondità di UITextField continui a cambiare, ho pensato che avrei aggiunto una soluzione ricorsiva.

-(NSArray * ) findAllSubviewsForView:(UIView * ) view{
    NSMutableArray * views = [[NSMutableArray alloc] init];

    for(UIView * subview in view.subviews){
        [views addObjectsFromArray:[self findAllSubviewsForView:subview]];
    }
    [views addObject:view];
    return views;
}

È possibile utilizzare questo array per trovare UITextField,

UITextField * searchField = nil;
for(UIView * view in [self findAllSubviewsForView:self]){
     if([view isKindOfClass:[UITextField class]]){
          searchField = (UITextField *) view;
      }
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top