24

に を追加UISearchBarUICollectionView、デリゲートsearchBar:textDidChange:フィルターでモデルを呼び出して を呼び出し[collectionView reloadData]ました。reloadData(reloadSection などと同様に) 検索バーのテキストフィールドから firstResponder を取り除き、キーボードを閉じたいと考えています。

「ライブ更新」フィルターを作成しようとしているので、文字を入力するたびにキーボードが消えるのが面倒です。

何か案は?

4

11 に答える 11

10

searchBarデリゲート関数では、performBatchUpdatesを使用し、最初にcollectionViewをリロードしてから[self.searchBar becomeFirstResponder]を呼び出してキーボードを表示します

- (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];
        }];
}
于 2015-03-17T10:58:43.783 に答える
6

私は最近同じ問題に遭遇し、それを修正するのにしばらく時間がかかりました. 問題は、テキスト フィールドが ReusableCollectionView にネストされている場合、以下が機能しないことです。

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

さらに、シミュレーターでは問題なく動作しましたが、デバイスでは動作しませんでした。

ビュー コントローラーをテキスト フィールド デリゲートとして設定し、実装する

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

結果コレクション ビューが更新されなかったため、機能しませんでした。私の推測では、ビュー コレクションをリロードする前に、ネストされたすべてのコントロールからフォーカスを削除しようとしますが、できません。テキスト フィールド デリゲート メソッドから NO を返します。

したがって、私にとっての解決策は、システムがテキストフィールドからフォーカスを削除し、リロード後に元に戻すことでした。問題は、実際にいつそれを行うかでした。

まず、私は

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

しかし、コレクションに項目がなかった場合 (フィルタリング中の通常のケース)、このメソッドは呼び出されませんでした。

最終的に私はこれを次の方法で解決しました。-prepareForReuse と -drawRect: の 2 つのメソッドを実装する UICollectionReusableView サブクラスを作成しました。最初のものには、次の描画サイクルで drawRect 呼び出しをスケジュールする -setNeedsDesplay 呼び出しが含まれています。2 つ目は、対応するフラグが YES に設定されている場合、[self.textField becomeFirstResponder] を呼び出してフォーカスを復元します。そのため、becomeFirstResponder を「後で」呼び出すというアイデアがありましたが、遅すぎることはありません。そうしないと、キーボードの奇妙な「ジャンプ」が発生します。

カスタムの再利用可能なコレクション ビューは次のようになります。

@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];
}

次に、私のView Controllerで:

- (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];
} 

おそらく最もエレガントなソリューションではありませんが、機能します。:)

于 2013-12-06T13:11:59.090 に答える
3

UISearchBarをヘッダーとして呼び出しに追加した場合UICollectionViewreloadDataを削除して再度追加することでヘッダーが「更新」され、UISearchBarが失われfirstResponderます。

UISearchBarヘッダーを使用せずに別の方法で追加するか、オーバーライドreloadDataして、検索バーが現在 firstResponder であるかどうかを確認し、その場合は を呼び出した後に次のようsuperにします。

// If we've lost first-responder, restore it.
if ((wasFirstResponder) && (![self.searchBar isFirstResponder])) {
    [self.searchBar becomeFirstResponder];
}
于 2013-03-24T06:49:55.453 に答える
2

答えは、テキスト フィールドがあるセクションをリロードしないことです。すべてのアイテムを単一の検索に配置することでこの問題を解決したため、その単一のセクションをリロードできました。

私が変更していた既存の画面では、右側にインデックスが表示され、各セクションに移動するための文字が表示されていました。これは、内部状態を台無しにすることなく、これらの各セクションをリロードする方法を知るのが難しくなる多くのセクションがあることを意味します。テキスト フィールドがファーストレスポンダーになったときに機能するようにするために、コレクション ビューの構成が変更され、すべての項目が単一のセクションに配置され、検索の実行時に再読み込みされます。上部のセクションはリロードされないため、フォーカスが失われません。

このようにして、この質問に対してリストされている他の回答のように、未定義の動作は必要ありません。

https://github.com/brennanMKE/PullDownSearch

于 2016-05-17T23:02:42.187 に答える
0

検索バーのデリゲートでメソッドを呼び出していると思います。-resignFirstResponderこれにより、値を入力するたびに却下されます

あなたはデータソースメソッドについて正しい道にあり、データをリロードします.配列を使用してすべての値を保存し、コレクションビューをロードするための別の配列を使用し、検索バーに入力されたすべての文字でフィルターを適用し、データソース配列をロードしてからリロードします

キーボードをそのままにしておく方が良いと思います。これは、検索するテキストを入力した後、手動で閉じることができる適切な UI スタイルです。ライブ更新フィルターのより良いオプションだと思います。

ボタンを使用して検索している場合は、そこにキーボード非表示オプションを含めることができます。ただし、そのようなオプションを使用すると、ライブ アップデートを実装できません。

于 2013-03-06T19:12:33.100 に答える
0

これが私がそれを管理した方法です。コレクション ビューのヘッダー補足ビューとして UISearchBar を使用しました。検索バーデリゲートのテキスト didchange で、検索がアクティブである (またはアクティブではない) フラグを設定し、コレクションビューをリロードしました

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

次に、cellForItemAtIndexPath で、キーボードがファーストレスポンダーで検索がアクティブかどうかを確認します。そうでない場合は、ファーストレスポンダーにします。

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

    if(activeSearch && ![searchBar isFirstResponder])
    {
        [searchBar becomeFirstResponder];
    }
}
于 2013-09-23T18:48:52.563 に答える
0

小さなテスト アプリケーションを作成しました。次のコードは、検索バーに文字を入力するときにキーボードを非表示にしません。とはいえ、[UITableView reloadData] はレスポンダーを辞任しません。

- (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];
}

本当に、どこかで辞任していませんか?

于 2013-03-06T19:30:54.263 に答える