如何筛选UICollectionView并保持键盘吗?(How to filter UICollec

2019-08-17 08:57发布

我添加了一个UISearchBarUICollectionView和委托searchBar:textDidChange:我过滤模型,并调用[collectionView reloadData] reloadData (以及reloadSection等),要采取从搜索栏的文本框离开firstResponder,从而驳回键盘。

我想建立一个“活更新”过滤器,所以它很烦人有键盘,请每个字符键入之后。

有任何想法吗?

Answer 1:

在搜索栏委托功能,我使用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];
        }];
}


Answer 2:

我最近遇到了同样的问题,并花了一段时间才能得到它固定。 问题是,当嵌套在ReusableCollectionView文本字段以下不起作用。

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

此外,对我来说做了仿真工作正常,但在设备上没有工作。

设置视图控制器为文本字段代表和执行

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

没有,因为作为结果集合视图没有刷新工作。 我的猜测是 - 重装其观点集合之前试图从所有嵌套控件移除焦点,但它不能 - 我们从文本字段的委托方法不归路。

所以我的解决办法是让系统从文本字段上移除焦点,但再赚回来重装后。 现在的问题是,当真正做到这一点。

首先,我一直试图做的

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

但是当在收集没有任何项目(这是过滤在正常情况下),这种方法并没有被调用。

最后,我在下面的方法解决了这个。 我创建UICollectionReusableView子类实现两个方法:-prepareForReuse和-drawRect :. 第一个包含-setNeedsDesplay调用它的drawRect上一次抽取循环调用时间表。 第二个通过调用[self.textField becomeFirstResponder]如果相应标志被设置为YES恢复焦点。 这样的想法是“后来”,而不是叫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];
}

然后在我的视图控制器:

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

也许不是最完美的解决方案,但它的工作原理。 :)



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


Answer 4:

解决它:

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


Answer 5:

答案是不会重新加载具有文本字段的部分。 我通过把所有项目都放到一个单一的搜索,这样有可能重新加载单节解决了这个问题。

现有的屏幕,我被修改为显示与字母的正确导航到,这意味着有许多部分,这使得它更难知道如何重新加载每个这些板块的不搞乱内部状态各部分的指标。 为了当文本字段将成为第一个响应的集合视图改变该组织的所有项目放入一个单一的部分运行搜索时重新加载它。 现在,顶部没有重新加载,因此它不会失去焦点。

这样,没有未定义的行为是必要像这个问题列出的其他答案。

https://github.com/brennanMKE/PullDownSearch



Answer 6:

我刚刚创建了一个小的测试应用程序。 下面的代码不会隐藏在搜索栏输入字符键盘。 这就是说,[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];
}

你确定,你不辞职它的地方?



Answer 7:

我想,您呼叫的-resignFirstResponder在搜索栏委托造成每次输入值时它就会被驳回方法

你是在对数据源的方法对路,重装data.Use数组存储在搜索栏输入滤波器另一个数组用于装载的CollectionView和每一个字母的所有值并加载数据源数组,然后重装

那么我认为这是更好地保持键盘。那是正确的UI风格,你完成输入要搜索的文本,可以关闭它manually.I认为这是实时更新过滤器是更好的选择了。

如果你正在使用一个按钮来进行搜索,那么您可以使用这种选项时,包括键盘隐藏选项there.but实时更新无法实施



Answer 8:

下面是我怎么做的。 我有我的UISearchBar在我的收藏查看标题补充视图。 文本didchange为搜索栏委托我设置一个标志,搜索是活动的(或不),并重新加载的CollectionView

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


Answer 9:

我只是说

    [searchBar becomeFirstResponder];

打完电话后

    [collectionView reloadData];


文章来源: How to filter UICollectionView and keep keyboard up?