SearchBarで検索文字列のテキストを変更したいアプリケーションを開発しています。 SearchBarの横に表示される[キャンセル]ボタンのテキストも変更したいと思いました。検索バーに文字列を入力する前に、デフォルトの文字列として検索文字列を取得します。その文字列のテキストを変更したいと思いました。その検索バーをクリックすると、検索バーの横にキャンセルボタンが表示され、そのキャンセルボタンのテキストを変更したいと思いました。
また、手順の前に「searchBar setShowsCancelButton」が必要です。
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
[theSearchBar setShowsCancelButton:YES animated:NO];
for (UIView *subView in theSearchBar.subviews){
if([subView isKindOfClass:[UIButton class]]){
[(UIButton*)subView setTitle:@"Done" forState:UIControlStateNormal];
}
}
}
注意:Appleの問題を回避するためにUIButtonを使用してください!
外観プロキシを使用します。
id barButtonAppearanceInSearchBar = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
[barButtonAppearanceInSearchBar setBackgroundImage:grayBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[barButtonAppearanceInSearchBar setTitleTextAttributes:@{
NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:20],
NSForegroundColorAttributeName : [UIColor blackColor]
} forState:UIControlStateNormal];
[barButtonAppearanceInSearchBar setTitle:@"X"];
IOS 7のソリューション。これに対するすべてのクレジットは Jesper Nielsen氏 に送られます-彼はコードを書きました。
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
UIButton *cancelButton;
UIView *topView = theSearchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
[cancelButton setTitle:@"YourTitle" forState:UIControlStateNormal];
}
}
「検索文字列」によってプレースホルダーを意味する場合は、次のようにします。
[searchBar setPlaceholder:@"Whatever you want"];
キャンセルボタンのテキストを変更することに関しては、それはもう少し難しいかもしれません。 Appleは、このために標準のUIBarButtonItem、または非標準のUIButtonも使用しません。代わりに、検索バーのキャンセルボタンにUINavigationButtonを使用します。これはドキュメント化されたパブリッククラスではないため、変更しようとすると、App Storeからアプリが拒否される可能性が非常に高くなります。拒否のリスクを冒したい場合は、searchBarのサブビューを検索できます。
for(UIView *view in [searchBar subviews]) {
if([view isKindOfClass:[NSClassFromString(@"UINavigationButton") class]]) {
[(UIBarItem *)view setTitle:@"Whatever you want"];
}
}
キャンセルボタンは遅延して読み込まれるため、ユーザーが検索バーをアクティブにしたときにこの変更を行う必要があります。
IOS 7では、UISearchBarを使用している場合は、このコードをsearchBarTextDidBeginEditing:メソッドに書き込むだけです。
searchBar.showsCancelButton = YES;UIView* view=searchBar.subviews[0];
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
UIButton *cancelButton = (UIButton*)subView;
[cancelButton setTitle:@"إلغاء" forState:UIControlStateNormal];
}
}
Yar1vnコードはXcode 5では機能しないため、UIAppearance手法を修正したいと思います。以下を使用すると、iOS 6とiOS 7の両方で完全に機能するコードが得られます。
まず、キャンセルボタンがプライベートUINavigationButton:UIButtonであることを理解する必要があります。したがって、UIBarButtonItemではありません。少し調べたところ、UINavigationButtonがこれらのUIAppearanceセレクターに応答するようです。
// inherited from UINavigationButton
@selector(setTintColor:)
@selector(setBackgroundImage:forState:style:barMetrics:)
@selector(setBackgroundImage:forState:barMetrics:)
@selector(setTitleTextAttributes:forState:)
@selector(setBackgroundVerticalPositionAdjustment:forBarMetrics:)
@selector(setTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundImage:forState:barMetrics:)
@selector(setBackButtonTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundVerticalPositionAdjustment:forBarMetrics:)
// inherited from UIButton
@selector(setTitle:forState:)
偶然にも、これらのセレクターはUIBarButtonItemのセレクターと一致しています。トリックの意味は、2つの個別のUIAppearanceを使用して、プライベートクラスUINavigationButtonを処理することです。
/* dual appearance technique by Cœur to customize a UINavigationButton */
Class barClass = [UISearchBar self];
UIBarButtonItem<UIAppearance> *barButtonItemAppearanceInBar = [UIBarButtonItem appearanceWhenContainedIn:barClass, nil];
[barButtonItemAppearanceInBar setTintColor:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... style:... barMetrics:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setTitleTextAttributes:... forState:...];
[barButtonItemAppearanceInBar setBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil];
[buttonAppearanceInBar setTitle:... forState:...];
現在、この手法は[キャンセル]ボタンで機能しますが、barClassを[UINavigationBar self]
に変更すると、[戻る]ボタンでも機能します。
このソリューションは私にとって有効です-iOs7およびiOs8:
@interface ... : ...
@property (strong, nonatomic) IBOutlet UISearchBar *search;
@end
そして
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
NSArray *searchBarSubViews = [[self.search.subviews objectAtIndex:0] subviews];
UIButton *cancelButton;
for (UIView *subView in searchBarSubViews) {
if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
break;
}
}
if (cancelButton) {
[cancelButton setTitle:@"New cancel" forState:UIControlStateNormal];
}
//insert this two lines below if you have a button appearance like this "Ne...cel"
[searchBar setShowsCancelButton:NO animated:YES];
[searchBar setShowsCancelButton:YES animated:YES];
}
JeremytrippのSwiftでの作業コード
Swiftで同じコードが見つからなかったので、自分で「翻訳」しました:
func searchDisplayControllerWillBeginSearch(controller: UISearchDisplayController) {
self.searchDisplayController?.searchBar.showsCancelButton = true
var cancelButton: UIButton
var topView: UIView = self.searchDisplayController?.searchBar.subviews[0] as UIView
for subView in topView.subviews {
if subView.isKindOfClass(NSClassFromString("UINavigationButton")) {
cancelButton = subView as UIButton
cancelButton.setTitle("My Custom Title", forState: UIControlState.Normal)
}
}
}
IOS 7でUISearchDisplayController
にdisplaysSearchBarInNavigationBar = YES
を設定した場合、サブビューの再帰または外観プロキシ機能しませんを使用してキャンセルボタンのタイトルを置き換えます。
代わりに、viewDidLoad
で独自のバーボタンを使用します。
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"A Custom Title", nil)
style:UIBarButtonItemStyleBordered
target:self
action:@selector(cancelButtonTapped:)];
// NB: Order is important here.
// Only do this *after* setting displaysSearchBarInNavigationBar to YES
// as that's when UISearchDisplayController creates it's navigationItem
self.searchDisplayController.navigationItem.rightBarButtonItem = barItem;
}
単にlocalizedキャンセルボタンのデフォルトの「キャンセル」タイトルにしたい場合は、CFBundleDevelopmentRegionキーの値をenからInfo.plistファイルのローカライズされたリージョンに変更しますプロジェクトで。
これが私の変更です
<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>
その後、デフォルトの「キャンセル」タイトルは中国語の「取消」として表示されます。この変更は、すべてのデフォルトのリージョン値にも影響します。たとえば、UITextField/UITextViewのペーストボード操作のアクションタイトルはローカライズされ、「選択」->「选择」、「貼り付け」->「粘贴」...となります。
ちなみに、Info.plistファイルは完全にローカライズできます。
楽しい!
searchBarがnavigationBarにある場合、コードは通常の回答とは異なります。代わりに、NavigationBarのサブビューを検索する必要があります。
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
UINavigationBar * navigationBar = self.navigationController.navigationBar;
for (UIView *subView in navigationBar.subviews){
if([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]){
[(UIButton*)subView setTitle:@"İptal" forState:UIControlStateNormal];
}
}}
そして、これはiOS7 +で動作しますが、それでもタイトルを設定できない場合は、ビューのデバッグを学ぶ必要があります-これが私がこの私の問題を解決した方法です。
この簡単なチュートリアルでは、ビューデバッグの要点を非常によく説明しています。
http://www.raywenderlich.com/98356/view-debugging-in-xcode-6
_ if #available(iOS 13.0, *) {
controller.searchBar.setValue("Done", forKey:"cancelButtonText")
} else {
controller.searchBar.setValue("Done", forKey:"_cancelButtonText")
}
_
???? ♂️
実際、controller.searchBar.setValue("Done", forKey:"cancelButtonText")
はすべてのiOSバージョンで機能します
非公開のUINavigationButtonクラスを参照する代わりに、次のようにしました。 App Storeのレビューでそれが実現することを願っています!
for (id subview in searchBar.subviews) {
if ([subview respondsToSelector:@selector(setTitle:)]) {
[subview setTitle:@"Map"];
}
}
IOS7で[キャンセル]ボタンを変更しても問題が解決しない場合は、現在、これでうまくいきます。
-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
self.searchDisplayController.searchBar.showsCancelButton = YES;
UIButton *cancelButton;
UIView *topView = self.searchDisplayController.searchBar.subviews[0];
for (UIView *subView in topView.subviews) {
if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
cancelButton = (UIButton*)subView;
}
}
if (cancelButton) {
//Set the new title of the cancel button
[cancelButton setTitle:@"Hi" forState:UIControlStateNormal];
}
}