Я использую UISearchBar для ввода адреса для установления сетевого подключения. Пока соединение сделано, я хочу показать индикатор активности вместо крошечного BookmarkButton в правой части панели поиска. Насколько я вижу, нет публичного объявленного свойства, которое дало бы мне доступ к правильному подсмотру поисковой панели. Я видел, как это было сделано, какие-то мысли?Заменить закладку с помощью ActivityInicator в UISearchBar
ответ
Как насчет замены значка поиска на левой стороне индикатором активности во время поиска или соединений?
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
Это не совсем сработало для меня - у моего UISearchBar было только одно subview (другое UIView), поэтому мне пришлось использовать рекурсивный (в ширину) поиск, чтобы найти UITextField. Не уверен, что это связано с тем, что компонент изменился, или я просто делаю что-то неправильно. Но спасибо, что указал мне в правильном направлении. –
Только для записи:
for(UIView* view in self.subviews){
if([view isKindOfClass:[UITextField class]]){
searchField=view;
break;
}
}
if(searchField !=)) {
searchField.leftView = myCustomView;
}
Вы можете создать подкласс UISearchBar и вызвать этот код в методе layoutSubview. вызывая этот код в layoutSubview, убедитесь, что анимация изменения размера работает правильно.
О, пожалуйста, используйте for-in цикл 'for (UIView * view в self.subviews) {if ([view isKindOfClass: [UITextField class]]) {searchField = view; break;}} '. – kennytm
Я обновил answer от @JohnLemberger работать с прошивкой 7 (примечание: Я проверил только это на прошивкой 7), а также сводка моих изменений:
ПРИМЕЧАНИЕ: это не очень надежный код для начала, поскольку Apple может изменить иерархию представлений UISearchBar
в любом выпуске (как и между iOS 6 и 7).
SearchBarWithActivity.h (ничего не изменилось):
@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) Показать/скрыть значок "увеличительное стекло", когда индикатор активности появляется
2) Добавить глубину в иерархии представлений Поиск по 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
К сожалению, это не работает на iOS 7, когда setDisplaysSearchBarInNavigationBar является истинным. Я не уверен, что в этом случае доступен поиск. – Gerhat
FYI, на iOS 8, текстовое поле имеет трехуровневую глубину. –
Я обновляю jonsibley's answer, добавив поддержку для случаев, когда UISearchBar встроен в UINavigationBar с использованием отображаетSearchBarInNavigationBar.
SearchBarWithActivity.h (добавлено новое свойство):
@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 (получить searchField от navigationItem, если не ноль):
#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
В вашем 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];
}
Надеюсь, это сэкономит время.
Я внедрил категорию для UISearchBar
, которая показывает UIActivityIndicatorView
, в зависимости от состояния операции запроса AFNetworking или задачи сеанса https://gist.github.com/nguyenhuy/a11d15c11200477b05a6.
Поскольку кажется, что глубина UITextField продолжает меняться, я решил, что добавлю рекурсивное решение.
-(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;
}
Вы можете использовать этот массив, чтобы найти UITextField,
UITextField * searchField = nil;
for(UIView * view in [self findAllSubviewsForView:self]){
if([view isKindOfClass:[UITextField class]]){
searchField = (UITextField *) view;
}
}
где вы видели это было сделано? –
Приложение «Википедия» (бесплатно) делает это. – Monobono
- это приложение для iphone для приложений или веб-приложение? –