uisearchbarは、キャンセルボタンの自動無効化を無効にします
-
30-09-2019 - |
質問
USearchBarをテーブルビューに実装しましたが、1つの小さなものを除いてほとんどすべてが機能しています。テキストを入力して、キーボードの検索ボタンを押すと、キーボードが消えます。検索結果はテーブルに表示される唯一のアイテムです。テキストはuisearchbarにとどまりますが、キャンセルボタンは無効になります。
私はリストをApple Contactsアプリの機能に近づけようとしており、そのアプリで検索を押すと、キャンセルボタンが無効になりません。
uisearchbarヘッダーファイルを見たとき、_searchbarflags structの下でautodisablecancelbuttonのフラグに気づきましたが、プライベートです。
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;
}
}
}
}
これを簡単に達成する方法は2つあります
- (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;
}
}
2番目のものを使用する必要があります。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をターゲットにしていますが、答えが見つかりました。
私がしようとしているのは、Twitter iOSアプリのようなものです。 [タイムライン]タブの拡大ガラスをクリックすると、 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
そして、そのサブビューをむき出しにしました。常に1つだけがあり、タイプです UIView
(私の変数 searchBarSubview
).
それから、それ UIView
保持します NSArray
呼び出されました subviewCache
そして、私は最後の要素(3番目)がタイプであることに気付きました UINavigationButton
, 、パブリックAPIではありません。そこで、代わりにキー価値コーディングを使用することに着手しました。私はそれをチェックしました UINavigationButton
に応答します setEnabled:
, 、そして幸運なことに、そうです。だから私はプロパティをに設定します @YES
. 。それはそうだと思う UINavigationButton
は キャンセルボタン。
これは、Appleがの実装を変更することを決定した場合に破ることになります。 UISearchBar
'nenards、しかし一体何。今のところ機能します。
に従って ここでの私の答え, 、これをSearchBar Delegateに配置します。
- (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の場合、iOS 7およびiOS 8で動作する次のC#ソリューションがあります。
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以来、SearchBarの下には追加のレベルのサブビューがあります
- キャンセルボタンを有効にするのに適した場所があります
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
}
}
}
}