如何过滤UICollectionView并保持键盘?

Mik*_*atz 20 keyboard uisearchbar reloaddata ios uicollectionview

我已经添加了UISearchBar一个UICollectionView和一个委托searchBar:textDidChange:过滤器我的模型和调用[collectionView reloadData].reloadData(以及reloadSection等)想要从搜索栏的文本字段中取走firstResponder,从而解雇键盘.

我正在尝试构建一个"实时更新"过滤器,因此在键入每个字符后让键盘消失是很烦人的.

有任何想法吗?

Tra*_*ieu 9

在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];
        }];
}
Run Code Online (Sandbox Code Playgroud)

  • 其实这个答案是最完美的:http://stackoverflow.com/a/25796944/501439 (2认同)

小智 6

我最近遇到了同样的问题,需要一段时间才能解决问题.问题是当文本字段嵌套在ReusableCollectionView中时,以下方法不起作用.

[self.collectionView reloadData];
[self.textField becomeFirstResponder];
Run Code Online (Sandbox Code Playgroud)

此外,对我来说,它在模拟器上工作正常,但在设备上无法正常工作.

将视图控制器设置为文本字段委托和实现

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    return NO;
}
Run Code Online (Sandbox Code Playgroud)

没有工作,因为结果集合视图没有刷新.我的猜测是 - 在重新加载其视图集合之前尝试从所有嵌套控件中删除焦点但它不能 - 我们从文本字段委托方法返回NO.

因此,我的解决方案是让系统从文本字段中移除焦点,然后在重新加载后将其恢复.问题是实际上是什么时候这样做的.

首先,我已经尝试过了

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
Run Code Online (Sandbox Code Playgroud)

但是当集合中没有项目时(在过滤期间这是正常情况),此方法未被调用.

最终我通过以下方式解决了这个问题.我创建了UICollectionReusableView子类,实现了两个方法:-prepareForReuse和-drawRect:.第一个包含-setNeedsDesplay调用,它在下一个绘图周期调度drawRect调用.如果相应的标志设置为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];
}
Run Code Online (Sandbox Code Playgroud)

然后在我的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];
} 
Run Code Online (Sandbox Code Playgroud)

可能不是最优雅的解决方案,但它的工作原理.:)


Lit*_*T.V 0

我认为您正在调用-resignFirstResponder搜索栏委托中的方法,这会导致每次您输入值时它都会被忽略

您处于关于数据源方法并重新加载数据的正确路径中。使用数组存储所有值,另一个数组用于加载集合视图以及在搜索栏过滤器上输入的每个字母并加载数据源数组,然后重新加载

嗯,我认为最好保留键盘。这是正确的 UI 风格,在输入文本进行搜索后,您可以手动关闭它。我认为这是实时更新过滤器的更好选择。

如果您使用按钮进行搜索,则可以在其中包含键盘隐藏选项。但是使用此类选项时无法实现实时更新