2013-03-06 11 views
16

Dodałem numer UISearchBar do UICollectionView, a na przedstawiciela searchBar:textDidChange: przefiltruj mój model i zadzwoń pod numer [collectionView reloadData]. reloadData (podobnie jak reloadSection, itp.) Chce zabrać firstResponder z pola tekstowego paska wyszukiwania, tym samym odrzucając klawiaturę.Jak filtrować UICollectionView i utrzymywać klawiaturę w górze?

Próbuję zbudować filtr "na bieżąco aktualizujący" i denerwuje się, aby klawiatura zniknęła po wpisaniu każdego znaku.

Wszelkie pomysły?

+0

Dziękuję za zadanie tego pytania. – GeneCode

Odpowiedz

0

Myślę, że wywołanie metody w delegata searchbar które powodują za każdym razem wpisać wartość to zostanie odwołany

jesteś na właściwej ścieżce temat metod DataSource i przeładować data.Use tablicę do przechowywania -resignFirstResponder wszystkie wartości kolejnej tablicy do ładowania widoku kolekcji i każdej litery wpisanej w filtrze paska wyszukiwania i ładowania tablicy źródeł danych, a następnie ponownie załadować

Cóż, myślę, że lepiej jest trzymać klawiaturę. To jest właściwy styl interfejsu użytkownika po Po wprowadzeniu tekstu do wyszukania możesz go odrzucić ręcznie. Myślę, że jest to lepsza opcja dla filtra aktualizującego na żywo.

Jeśli używasz przycisku, aby wyszukać następnie można dołączyć klawiaturę hide opcję there.but żywych aktualizacji nie mogą być realizowane przy użyciu takiej opcji

0

Właśnie stworzył małą aplikację testową. Poniższy kod nie ukrywa klawiatury podczas wpisywania znaków na pasku wyszukiwania. Powiedział, że [UITableView reloadData] nie rezygnuje z respondenta.

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 
    return arc4random() % 10; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {  
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; 
    return cell; 
} 

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { 
    [self.collectionView reloadData]; 
} 

Czy jesteś pewien, że nie rezygnujesz gdzieś?

3

Jeśli dodasz UISearchBar jako nagłówek do UICollectionView rozmowy reloadData będzie „odświeżyć” nagłówek poprzez usunięcie i ponowne dodanie UISearchBar powodując jej stracić firstResponder.

Można też dodać swój UISearchBar w inny sposób, nie używając nagłówek lub zastąpić reloadData, sprawdź czy pasek wyszukiwania jest obecnie firstResponder, a jeśli tak, to po wywołaniu super, zrobić:

// If we've lost first-responder, restore it. 
if ((wasFirstResponder) && (![self.searchBar isFirstResponder])) { 
    [self.searchBar becomeFirstResponder]; 
} 
+0

Niezłe wyjaśnienie. Zastanawiam się jednak, dlaczego TableView nie cierpi z powodu tego problemu. – GeneCode

0

Oto jak ja udało się. Posiadałem swój UISearchBar jako dodatkowy widok nagłówka w moim widoku kolekcji.Na didchange tekstowym delegata searchbar ustawić flagę, że wyszukiwanie jest aktywna (lub nie) i przeładował CollectionView

- (void)searchBar:(UISearchBar *)_searchBar textDidChange:(NSString *)searchText 
{ 
    if([searchText isEqualToString:@""]) 
    { 
     activeSearch = FALSE; 
    } 
    else 
    { 
     activeSearch = TRUE; 
    } 
    [self filterContentForSearchText:searchText scope:nil]; 
    [self.collectionView reloadData]; 
} 

Następnie w cellForItemAtIndexPath sprawdzić czy klawiatura jest pierwszy responder i wyszukiwania jest aktywny, jeśli nie , robię to pierwszy responder:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    ... 

    if(activeSearch && ![searchBar isFirstResponder]) 
    { 
     [searchBar becomeFirstResponder]; 
    } 
} 
0

właśnie dodałem

[searchBar becomeFirstResponder]; 

po wywołaniu

[collectionView reloadData]; 
2

rozwiązać go:

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 726.0f, 44.0f)]; 
    [_collectionView addSubview:searchBar]; 
    searchBar.delegate = self; 
    [(UICollectionViewFlowLayout *)_collectionView.collectionViewLayout setSectionInset:UIEdgeInsetsMake(64, 20, 20, 20)]; 


- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { 
    [_collectionView reloadData]; 
    [searchBar becomeFirstResponder]; 
} 
6

biegnę na ten sam problem niedawno i zajęło to trochę czasu, aby to naprawić. Problem polega na tym, że gdy pole tekstowe jest zagnieżdżone w ReusableCollectionView, poniższe elementy nie działają.

[self.collectionView reloadData]; 
[self.textField becomeFirstResponder]; 

Co więcej, dla mnie działa dobrze na symulatorze, ale nie działa na urządzeniu.

ustawienie widoku kontrolera jako delegat pola tekstowego i wdrażaniu

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { 
    return NO; 
} 

nie działa, bo jak widok kolekcja wynik nie odświeżyć. Zgaduję, że - przed ponownym wczytaniem jego kolekcji kolekcja próbuje usunąć fokus ze wszystkich zagnieżdżonych kontrolek, ale nie może - zwracamy NO z metody delegowania pola tekstowego.

Rozwiązaniem dla mnie było umożliwienie systemowi usunięcia fokusu z pola tekstowego, a następnie odzyskanie go po ponownym załadowaniu. Pytanie brzmiało, kiedy faktycznie to zrobić.

Najpierw próbowałem to zrobić w

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 

ale kiedy nie było żadnych przedmiotów w kolekcji (co jest normalne przypadek podczas filtrowania) metoda ta nie sprawdzony.

Ostatecznie rozwiązałem to w następujący sposób. Utworzona podklasa UICollectionReusableView implementuje dwie metody: -prepareForReuse i -drawRect :. Pierwsza zawiera -setNeedsDesplay wywołanie, które planuje wywołanie drawRect w następnym cyklu rysowania. Drugi przywraca fokus poprzez wywołanie [self.textField sięFirstResponder], jeśli odpowiednia flaga jest ustawiona na YES. Tak więc pomysł polegał na tym, aby zadzwonić do "przyszłego", ale nie za późno, bo w przeciwnym razie dzieje się dziwne "skakanie" klawiatury.

Mam zwyczaj wielokrotnego użytku widok kolekcja wygląda następująco:

@interface MyCollectionReusableView : UICollectionReusableView 

@property (nonatomic, assign) BOOL restoreFocus; 
@property (nonatomic, strong) UITextField *textField; 

@end 


@implementation MyCollectionReusableView 
@synthesize restoreFocus; 
@synthesize textField; 

- (void)setTextField:(UITextField *)value { 
    textField = value; 
    [self addSubview:textField]; 
} 

- (void)drawRect:(CGRect)rect { 
    [super drawRect:rect]; 
    if (self.restoreFocus) { 
     [self.textField becomeFirstResponder]; 
    } 
} 

- (void)prepareForReuse { 
    [self setNeedsDisplay]; 
} 

Wtedy moim zdaniem Kontroler:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self.collectionView registerClass:[MyCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderReuseIdentifier]; 

    [self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 
} 

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 
    if (UICollectionElementKindSectionHeader == kind) { 
     MyCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader                   withReuseIdentifier:HeaderReuseIdentifier                     forIndexPath:indexPath]; 

     //add textField to the reusable view 
     if (nil == view.textField) { 
      view.textField = self.textField; 
     } 
     //set restore focus flag to the reusable view 
     view.restoreFocus = self.restoreFocus; 
     self.restoreFocus = NO; 
     return view; 
    } 
    return nil; 
} 

- (void)textFieldDidChange:(UITextField *)textField { 
    self.restoreFocus = YES; 
    [self.collectionView reloadData]; 
} 
nie

Prawdopodobnie najbardziej eleganckie rozwiązanie, ale działa. :)

+0

Dzięki, sprawdzę to. –

7

W funkcji delegowania searchBar używam performBatchUpdates, najpierw przeładuj collectionView, a następnie wywołaj [self.searchBar staje sięFirstResponder] aby wyświetlić klawiaturę

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{ 
    [self setEditing:NO animated:YES]; 
    [searchBar setShowsCancelButton:YES animated:YES]; 

     [self.collectionView performBatchUpdates:^{ 
      [self.collectionView reloadData]; 
     } completion:^(BOOL finished) { 
      [self.searchBar becomeFirstResponder]; 
     }]; 
} 
+0

To powinno być poprawne anwser –

+0

To zasługuje na więcej awansów niż ma –

+0

Właściwie ta odpowiedź jest najdoskonalsza: http://stackoverflow.com/a/25796944/501439 – GeneCode

0

Odpowiedź jest taka, aby nie przeładowywać sekcji, która ma pole tekstowe. Rozwiązałem ten problem, umieszczając wszystkie elementy w jednym wyszukiwaniu, aby można było ponownie załadować tę pojedynczą sekcję.

Istniejący ekran, który modyfikowałem, pokazywał indeks po prawej stronie z literami do nawigacji w każdej sekcji, co oznacza, że ​​było wiele sekcji, co utrudnia zapoznanie się z tym, jak przeładować każdą z tych sekcji bez zakłócania stanu wewnętrznego . Aby działał, gdy pole tekstowe staje się pierwszym responderem, organizacja widoku kolekcji zmienia się, umieszczając wszystkie elementy w jednej sekcji, która jest ponownie ładowana po uruchomieniu wyszukiwania . Teraz górna sekcja nie jest ponownie ładowana, więc nie traci ostrości.

W ten sposób nie jest konieczne żadne niezdefiniowane zachowanie, podobnie jak inne odpowiedzi wymienione dla tego pytania.

https://github.com/brennanMKE/PullDownSearch

Powiązane problemy