SearchBar の検索文字列のテキストを変更したいアプリケーションを開発しています。SearchBar の横に表示される Cancel Button Also のテキストを変更したかったのです。検索バーに文字列を入力する前に、検索文字列をデフォルトの文字列として取得します。その文字列のテキストを変更したかったのですが、その検索バーをクリックすると、検索バーの横にキャンセル ボタンが表示され、そのキャンセル ボタンのテキストを変更したかったのです。
15 に答える
外観プロキシを使用します。
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"];
手順の前に「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 を使用してください!
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を使用します。これは文書化されたパブリッククラスではないため、変更しようとすると、アプリがAppStoreから拒否される可能性があります。拒否のリスクを冒したい場合は、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]
。
iOS 7 でdisplaysSearchBarInNavigationBar = YES
onを設定した場合UISearchDisplayController
、サブビューの再帰または外観プロキシを介してキャンセル ボタンのタイトルを置き換えても機能しません。
代わりに、独自のバー ボタンを使用します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;
}
キャンセル ボタンのデフォルトの「Cancel」タイトルをローカライズしたいだけの場合は、 CFBundleDevelopmentRegionキーの値を en からプロジェクトの Info.plist ファイルのローカライズされたリージョンに変更することをお勧めします。
これが私の変更です。
<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>
その後、デフォルトの「キャンセル」のタイトルは中国語の「取消」として表示されます。この変更は、すべてのデフォルトのリージョン値にも影響します。たとえば、UITextField/UITextView のペーストボード操作のアクション タイトルはローカライズされ、「選択」->「選択」、「貼り付け」->「粘贴」...
ちなみに、Info.plist ファイルは完全にローカライズできました。
楽しみ!
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];
}
}
Swift 2.1 でショートコードを動作させる (iOS7-9 テスト済み)
@IBOutlet weak var searchBar: UISearchBar!
func enableSearchBarCancelButton(enable: Bool, title: String? = nil) {
searchBar?.showsCancelButton = enable
if enable {
if let _cancelButton = searchBar?.valueForKey("_cancelButton"),
let cancelButton = _cancelButton as? UIButton {
cancelButton.enabled = enable //comment out if you want this button disabled when keyboard is not visible
if title != nil {
cancelButton.setTitle(title, forState: UIControlState.Normal)
}
}
}
}