UISearchBar Отключить автоматическое отключение кнопки отмены
-
30-09-2019 - |
Вопрос
Я реализовал UISearchBar на табличное представление, и почти все работает, кроме одной маленькой вещи: когда я вхожу в текст, а затем нажимаете кнопку поиска на клавиатуре, клавиатура исчезает, результаты поиска являются единственными элементами, показанными в таблице, Текст остается в UISearchBar, но кнопка «Отмена» отключена.
Я пытался получить свой список как можно ближе к функциональности приложения Apple Contaction Contaction, и когда вы нажмете поиск в этом приложении, он не отключает кнопку «Отмена».
Когда я посмотрел в файл заголовка UISearchBar, я заметил флаг для AutodisableCancelbutton под структурой _earchBarflags, но он является частным.
Есть ли что-то, что я скучаю, когда я настроил UISearchBar?
Решение
Я нашел решение. Вы можете использовать эту петлю для цикла по субпроизводителю панели поиска и включить его, когда нажата кнопка поиска на клавиатуре.
for (UIView *possibleButton in searchBar.subviews)
{
if ([possibleButton isKindOfClass:[UIButton class]])
{
UIButton *cancelButton = (UIButton*)possibleButton;
cancelButton.enabled = YES;
break;
}
}
Другие советы
Я должен был настроить это немного, чтобы поработать для меня в iOS7
- (void)enableCancelButton:(UISearchBar *)searchBar
{
for (UIView *view in searchBar.subviews)
{
for (id subview in view.subviews)
{
if ( [subview isKindOfClass:[UIButton class]] )
{
[subview setEnabled:YES];
NSLog(@"enableCancelButton");
return;
}
}
}
}
Есть два способа достичь этого легко
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
// The small and dirty
[(UIButton*)[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];
// The long and safe
UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
if ([cancelButton respondsToSelector:@selector(setEnabled:)]) {
cancelButton.enabled = YES;
}
}
Вы должны идти со вторым, он не разбит ваше приложение, если Apple изменит его на заднем плане.
Кстати, я проверил его от IOS 4.0 до 8.2, и никаких изменений, а также я использую его в моем магазине, утвержденном приложении без каких-либо проблем.
Это то, что сделало его на работу на IOS 6 для меня:
searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];
Вот мое решение, которое работает для всех ситуаций во всех версиях IOS.
Т.е. другие решения не обрабатывают, когда клавиатура уволен, потому что пользователь перетаскивал вид прокрутки.
- (void)enableCancelButton:(UIView *)view {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view setEnabled:YES];
} else {
for (UIView *subview in view.subviews) {
[self enableCancelButton:subview];
}
}
}
// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
[self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}
// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];
Ни один из ответов не работал для меня вообще. Я нацелен на iOS 7. Но я нашел ответ.
Что я пытаюсь, это что-то вроде приложения в Твиттере IOS. Если вы нажмете на увеличительное стекло на вкладке TimeLines, UISearchBar
Появится с активированной кнопкой «Отмена», отображаемой клавиатурой и недавним экраном поиска. Прокрутите последние поиски экрана и скрывают клавиатуру, но она сохраняет кнопку «Отмена».
Это мой рабочий код:
UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
[subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}
Я прибыл в это решение, установив точку останова на моем столе scrollViewWillBeginDragging:
. Отказ Я посмотрел в мой UISearchBar
и обнажены свои субпроизводитеки. У него всегда есть только один, который имеет тип UIView
(моя переменная searchBarSubview
).
Тогда это UIView
Держит А.Н. NSArray
называется subviewCache
И я заметил, что последний элемент, который третий, имеет тип UINavigationButton
, не в публичном API. Поэтому я установил, чтобы использовать кодирование ключа-значения вместо этого. Я проверил, если UINavigationButton
отвечает setEnabled:
, И, к счастью, это делает. Итак, я установил свойство в @YES
. Отказ Оказывается, что UINavigationButton
является кнопка отмены.
Это связано с нарушением, если Apple решит изменить реализацию UISearchBar
внутренности, но что, черт возьми. Это работает на данный момент.
Согласно Мой ответ здесь, Поместите это в свой поиск делегата:
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
dispatch_async(dispatch_get_main_queue(), ^{
__block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
void (^ensureCancelButtonRemainsEnabled)(UIView *);
weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIControl class]]) {
[(UIControl *)subview setEnabled:YES];
}
weakEnsureCancelButtonRemainsEnabled(subview);
}
};
ensureCancelButtonRemainsEnabled(searchBar);
});
}
Для Monotouch или Xamarin iOS у меня есть следующее решение C # Работа для iOS 7 и iOS 8:
foreach(UIView view in searchBar.Subviews)
{
foreach(var subview in view.Subviews)
{
//Console.WriteLine(subview.GetType());
if(subview.GetType() == typeof(UIButton))
{
if(subview.RespondsToSelector(new Selector("setEnabled:")))
{
UIButton cancelButton = (UIButton)subview;
cancelButton.Enabled = true;
Console.WriteLine("enabledCancelButton");
return;
}
}
}
}
Этот ответ основан на Дэвид Дуглас решение.
Более полный ответ:
- Поскольку iOS 7, существует дополнительный уровень подзвучащихся под панелью поиска
- Хорошее место, чтобы включить кнопку Отмена в
searchBarTextDidEndEditing
.
extension MyController: UISearchBarDelegate {
public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
// you need that since the disabling will
// happen after searchBarTextDidEndEditing is called
searchBar.subviews.forEach({ view in
view.subviews.forEach({ subview in
// ios 7+
if let cancelButton = subview as? UIButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
return
}
})
// ios 7-
if let cancelButton = subview as? UIButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
return
}
})
}
}
}
Вот решение SWIFT 3, которое использует расширения, чтобы легко получить кнопку отмены:
extension UISearchBar {
var cancelButton: UIButton? {
for subView1 in subviews {
for subView2 in subView1.subviews {
if let cancelButton = subView2 as? UIButton {
return cancelButton
}
}
}
return nil
}
}
Теперь для использования:
class MyTableViewController : UITableViewController, UISearchBarDelegate {
var searchBar = UISearchBar()
func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.tableHeaderView = searchBar
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
DispatchQueue.main.async {
if let cancelButton = searchBar.cancelButton {
cancelButton.isEnabled = true
cancelButton.isUserInteractionEnabled = true
}
}
}
}