una suscripciones suscripcion hbo eliminar desde cómo compra como cancelar apple app iphone objective-c cocoa-touch

iphone - suscripciones - Diseñando el botón de cancelar en una barra de UISearch



como eliminar una compra en app store (19)

Aunque esto podría no ser exactamente relevante para la pregunta original, la solución sigue siendo aplicable en el sentido más amplio de intentar personalizar el botón Cancelar en la barra de UISearch. Pensé que esto ayudará a otros que están atrapados en tal escenario.

Mi situación fue cambiar el título del botón de cancelación, pero con un giro, en el que no quería mostrar el botón de cancelación de forma predeterminada, sino que solo quería que apareciera cuando el usuario entra en el modo de búsqueda (haciendo clic dentro del campo de texto de búsqueda ). En este instante, quería que el botón de cancelar mostrara el título "Listo" ("Cancelar" estaba dando un significado diferente a mi pantalla, de ahí la personalización).

Sin embargo, esto es lo que hice (una combinación de soluciones de Caelavel y Arenim):

Subclasificado UISearchBar como MyUISearchBar con estos dos métodos:

-(void) setCloseButtonTitle: (NSString *) title forState: (UIControlState)state { [self setTitle: title forState: state forView:self]; } -(void) setTitle: (NSString *) title forState: (UIControlState)state forView: (UIView *)view { UIButton *cancelButton = nil; for(UIView *subView in view.subviews){ if([subView isKindOfClass:UIButton.class]) { cancelButton = (UIButton*)subView; } else { [self setTitle:title forState:state forView:subView]; } } if (cancelButton) [cancelButton setTitle:title forState:state]; }

Y en el controlador de visualización que usa esta barra de búsqueda, el siguiente fragmento de código se encarga de mostrar el botón de cancelación y de personalizar su título:

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { MyUISearchBar *sBar = (MyUISearchBar *)searchBar; [sBar setShowsCancelButton:YES]; [sBar setCloseButtonTitle:@"Done" forState:UIControlStateNormal]; }

Por extraño que parezca, no tuve que hacer nada para ocultar el botón de cancelar, ya que está oculto de forma predeterminada cuando se sale del modo de búsqueda.

Tengo una barra UISearchBar que tiene un botón de cancelación (se muestra con -(void)setShowsCancelButton:animated ). He cambiado el tintColor de la barra de búsqueda de esta manera en un intento por obtener una barra de búsqueda grisácea:

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)]; searchBar.tintColor = [UIColor colorWithWhite:0.8 alpha:1.0];

Esto es lo que parece ahora, observe que el botón de cancelación también está gris: http://twitpic.com/c0hte

¿Hay alguna manera de establecer el color del botón de cancelación por separado para que se vea más así: http://twitpic.com/c0i6q


Bueno, aquí está la función, que puede cambiar la etiqueta del botón de Cancelar. Modifícalo, si quieres. El uso es:

nStaticReplaceStringInView(mySearchBar, @"Cancel", @"NewCancelButtonLabel"); void nStaticReplaceStringInView(UIView * view, NSString * haystack, NSString * needle) { for(int i=0; i<[view.subviews count]; i++) { nStaticReplaceStringInView([view.subviews objectAtIndex:i], haystack,needle); } if([view respondsToSelector:@selector(titleForState:)]) { //NSLog(@"%@ || %@",[view titleForState:UIControlStateNormal], haystack); if(NSStrEq([view titleForState:UIControlStateNormal] , haystack)) { [view setTitle: needle forState: UIControlStateNormal]; } } }


Cambia el título del botón ''Cancelar'':

[[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:@"newTitle" forState:UIControlStateNormal];

Swift equivalente:

let cancelButton = UIButton.appearance(whenContainedInInstancesOf: [UISearchBar.self]) cancelButton?.setTitle("cancel".localized, for: .normal)


Daré una respuesta detallada sobre la técnica UIAppearance. Primero, debe comprender que el botón de cancelación es un UINavigationButton privado: UIButton. Después de una inspección, parece que UINavigationButton responderá a esos selectores de apariencia UIA:

// 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:)

Casualmente, esos selectores coinciden con los de un UIBarButtonItem. Lo que significa que el truco es usar dos UIAppearance separadas para manejar la clase privada 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:...]; // only for a backButton in an UINavigationBar, not for a cancelButton in an UISearchBar //[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...]; //[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...]; //[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...]; UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil]; // warning: doesn''t work for iOS7+ [buttonAppearanceInBar setTitle:... forState:...];

Esto te permitirá personalizar el botón Cancelar tanto como quieras.


En iOS 5.0+, puedes usar el proxy de appearnce .

Antes de que se muestre la barra de búsqueda:

UIBarButtonItem *searchBarButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil]; [searchBarButton setBackgroundImage:myCancelButtonImageNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [searchBarButton setBackgroundImage:myCancelButtonImageHighlighted forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault]; [searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesNormal forState:UIControlStateNormal]; [searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesHighlighted forState:UIControlStateHighlighted];

Si utiliza [UIButton appearanceWhenContainedIn:[UISearchBar class], nil] , afectará a otros botones (por ejemplo, botón de borrar). Por lo tanto, es mejor que no uses la UIButton de UIButton. Pruebe UIBarButtonItem .


En primer lugar, me gustaría agradecer a @Eliott de esta https://.com/a/37381821/1473144

Tuve que hacer algunos ajustes para que su respuesta funcionara en mis especificaciones que se detallan a continuación. Por favor, le pido al OP que actualice la respuesta aceptada ya que está MUY desactualizada.

Swift 3, iOS 10 y Xcode 8.2.1

searchBar.showsCancelButton = true var cancelButton: UIButton let topView: UIView = self.searchBar.subviews[0] as UIView for subView in topView.subviews { if let pvtClass = NSClassFromString("UINavigationButton") { if subView.isKind(of: pvtClass) { cancelButton = subView as! UIButton cancelButton.setTitle("", for: .normal) cancelButton.tintColor = UIColor.black cancelButton.setImage(#imageLiteral(resourceName: "searchX"), for: .normal) } } }


Lo que quieres hacer es bastante duro. No hay un gancho incorporado para llegar al botón de cancelar.

Sin embargo, hay un par de opciones si está dispuesto a abrir el capó.

En primer lugar, UISearchBar es una UIView, y el botón Cancelar también es una vista, que se agrega a la barra de búsqueda como una subvista, tal como lo esperaría.

Experimenté un poco y puedo decirle que cuando el botón está en pantalla tiene un tamaño de 48,30.

Entonces, en viewWillAppear, puedes hacer algo como esto:

  1. Encuentre la vista del botón cancelar en [searchbar subviews] buscando uno con tamaño 48,30. (Parece que solo hay uno, esto podría cambiar ...) Puede ser doblemente cuidadoso y buscar uno que esté aproximadamente en la posición correcta (difiere en el paisaje y el retrato).

  2. Añadir una subvista al botón de cancelar.

  3. La subvista debe ser un UIControl (para que pueda configurar habilitado = NO, para asegurarse de que los eventos táctiles lleguen al botón de cancelación real)

  4. Necesita tener el color correcto y las esquinas redondeadas; tendrá que modificar el tamaño por razones que aún no entiendo (55,30 parece funcionar)

  5. Esto funcionará si searchBar.showsCancelButton siempre es YES; Si desea que desaparezca cuando no esté editando la cadena de búsqueda, deberá encontrar un enlace para agregar la superposición cada vez que aparezca el botón Cancelar.

  6. Como puedes ver, esto es un poco de feo retoño. Hazlo con los ojos bien abiertos.


Para iOS 11 y Swift 4. Cree una subclase de UISearchController. Método de anulación:

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() print("layout") if let btn = searchBar.subviews[0].subviews[2] as? UIButton { btn.frame = CGRect(x: 306, y: 20, width: 53, height: 30) } }


Puede encontrar el botón de cancelación recorriendo las subvistas de la barra de búsqueda y comprobando el tipo de clase (en lugar del tamaño):

UIButton *cancelButton = nil; for(UIView *subView in yourSearchBar.subviews){ if([subView isKindOfClass:UIButton.class]){ cancelButton = (UIButton*)subView; } }

Y luego cambiar el color del tinte:

[cancelButton setTintColor:[UIColor colorWithRed:145.0/255.0 green:159.0/255.0 blue:179.0/255.0 alpha:1.0]];


Puede usar UIAppearance para UIAppearance el botón de cancelación sin iterar subvistas de UISearchBar , pero el encabezado UIButton no tiene actualmente ningún método anotado con UI_APPEARANCE_SELECTOR .

EDITAR: profundice las subvistas hasta que obtenga el botón de cancelar

Pero esto generalmente devuelve nil hasta que se searchBar.setShowsCancelButton(true, animated: true) .

extension UISearchBar { var cancelButton : UIButton? { if let view = self.subviews.first { for subView in view.subviews { if let cancelButton = subView as? UIButton { return cancelButton } } } return nil } }


Si desea configurar su botón de cancelación en UISearchBar , debe obtener el objeto UIButton de su objeto UISearchBar . Ejemplo abajo

UISearchBar *s_bar = [[UISearchBar alloc] initWithFrame:CGRectMake(50,20,300,30)]; s_bar.delegate = self; s_bar.barStyle = UIBarStyleDefault; s_bar.showsCancelButton = YES; UIButton *cancelButton; for (id button in s_bar.subviews) { if ([button isKindOfClass:[UIButton class]]) { cancelButton=(UIButton*)button; break; } }


Tengo muchos elementos de UISearchBar en mi aplicación, así que escribí esta categoría para agregar una propiedad para que pueda acceder a mySearchBar.cancelButton . (Si eres nuevo en las categorías, lee más sobre cómo extender objetos con categorías aquí ).

Tenga en cuenta que solo debe acceder a este cuando el botón Cancelar está visible porque UISearchBar parece crear un nuevo objeto de botón cada vez que se muestra. No guarde el puntero en el botón de cancelación, solo consígalo cuando sea necesario:

@interface UISearchBar (cancelButton) @property (readonly) UIButton* cancelButton; - (UIButton *) cancelButton; @end @implementation UISearchBar (cancelButton) - (UIButton *) cancelButton { for (UIView *subView in self.subviews) { //Find the button if([subView isKindOfClass:[UIButton class]]) { return (UIButton *)subView; } } NSLog(@"Error: no cancel button found on %@", self); return nil; } @end


UISearchBar personalizado y método de reemplazo -addSubview:

- (void) addSubview:(UIView *)view { [super addSubview:view]; if ([view isKindOfClass:UIButton.class]) { UIButton *cancelButton = (UIButton *)view; [cancelButton setBackgroundImage:[UIImage imageNamed:@"xxxx.png"] forState:UIControlStateNormal]; [cancelButton setBackgroundImage:[UIImage imageNamed:@"yyyy.png"] forState:UIControlStateHighlighted]; } }


Una vez que haya inicializado su UISearchBar, puede explorar sus subvistas y personalizar cada una de ellas. Ejemplo:

for (UIView *view in searchBar.subviews) { //if subview is the button if ([[view.class description] isEqualToString:@"UINavigationButton"]) { //change the button images and text for different states [((UIButton *)view) setEnabled:YES]; [((UIButton *)view) setTitle:nil forState:UIControlStateNormal]; [((UIButton *)view) setImage:[UIImage imageNamed:@"button image"] forState:UIControlStateNormal]; [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button"] forState:UIControlStateNormal]; [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateSelected]; [((UIButton *)view) setBackgroundImage:[UIImage imageNamed:@"button_pressed"] forState:UIControlStateHighlighted]; //if the subview is the background }else if([[view.class description] isEqualToString:@"UISearchBarBackground"]) { //put a custom gradient overtop the background CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = view.bounds; gradient.colors = [NSArray arrayWithObjects:(id)[[some uicolor] CGColor], (id)[[another uicolor] CGColor], nil]; [view.layer insertSublayer:gradient atIndex:0]; //if the subview is the textfield }else if([[view.class description] isEqualToString:@"UISearchBarTextField"]){ //change the text field if you wish } }

Funcionó muy bien para mí! Especialmente el gradiente :)


manera estúpida

for(id cc in [SearchBar subviews]) { if([cc isKindOfClass:[UIButton class]]) { UIButton *btn = (UIButton *)cc; ...... Do whatever you want ....... } }


Swift 2.1.1:

No hay una forma sencilla de enlazar y diseñar la barra de búsqueda, debe capturar la subvista manualmente desde la barra de búsqueda y luego aplicar los cambios.

var cancelButton: UIButton let topView: UIView = self.customSearchController.customSearchBar.subviews[0] as UIView for subView in topView.subviews { if subView.isKindOfClass(NSClassFromString("UINavigationButton")!) { cancelButton = subView as! UIButton cancelButton.enabled = true cancelButton.setTitle("TestTitle", forState: UIControlState.Normal) // Change to set the title cancelButton.setBackgroundImage(UIImage(named: "ImageName"), forState: .Normal) // Change this to set a custom cancel button image, set the title to "" to remove ''Cancel'' text } }


- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar { NSArray *arr = [theSearchBar subviews]; UIButton *cancelButton = [arr objectAtIndex:3]; [cancelButton setTitle:@"yourtitle" forState:UIControlStateNormal]; }

Simplemente tome un registro de arr y vea en qué control del índice se encuentra. De la misma manera u puede establecer UITextField propiedades de UITextField :

NSArray *arr = [searchbar subviews]; UITextField *searchfield = [arr objectAtIndex:2]; [searchfield setTextAlignment:UITextAlignmentRight];


UISearchBar *searchBar; [searchBar setShowsCancelButton:YES animated:YES]; UIButton *cancelButton = YES == [searchBar respondsToSelector:NSSelectorFromString(@"cancelButton")] ? [searchBar valueForKeyPath:@"_cancelButton"] : nil; cancelButton.titleEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10); [cancelButton setTitle:@"New :)" forState:UIControlStateNormal];


extension UISearchBar { var cancelButton : UIButton? { let topView: UIView = self.subviews[0] as UIView if let pvtClass = NSClassFromString("UINavigationButton") { for v in topView.subviews { if v.isKind(of: pvtClass) { return v as? UIButton } } } return nil } }