Creación de un botón de flecha izquierda (como el estilo & # 8220; atrás & # 8221; de UINavigationBar) en una barra de herramientas

StackOverflow https://stackoverflow.com/questions/227078

Pregunta

Me encantaría crear un " Volver " botón de bizel de flecha izquierda en un UIToolbar .

Por lo que puedo decir, la única forma de obtener uno de estos es dejar UINavigationController en la configuración predeterminada y usa uno para el elemento de la barra izquierda. Pero no hay forma de encontrar uno como UIBarButtonItem , por lo que no puedo crear uno en un UIToolbar estándar, aunque son muy similares a UINavigationBar s.

Podría crearlo manualmente con imágenes de botones, pero no puedo encontrar las imágenes de origen en ningún lugar. Tienen bordes de canal alfa, por lo que las capturas de pantalla y el corte no obtendrán resultados muy versátiles.

¿Alguna idea más allá de la captura de pantalla para cada tamaño y combinación de colores que pretendo usar?

Actualización: POR FAVOR, DEJE DE esquivar la pregunta y sugiera que no debería preguntar esto y debería usar UINavigationBar . Mi aplicación es Instapaper Pro. Solo muestra una barra de herramientas inferior (para ahorrar espacio y maximizar el área de contenido legible), y deseo colocar un botón Atrás con forma de flecha izquierda en la parte inferior.

Decirme que no debo hacer esto no es una respuesta y ciertamente no merece una recompensa.

¿Fue útil?

Solución

Utilicé el siguiente psd que obtuve de http://www.teehanlax.com / blog /? p = 447

http://www.chrisandtennille.com/pictures/backbutton.psd

Luego, acabo de crear una UIView personalizada que uso en la propiedad customView del elemento de la barra de herramientas.

Funciona bien para mí.


Editar: Como lo señaló PrairieHippo , maralbjo encontró que el siguiente código simple hizo el truco (requiere una imagen personalizada en el paquete ) debe combinarse con esta respuesta. Así que aquí está el código adicional:

// Creates a back button instead of default behaviour (displaying title of previous screen)
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_arrow.png"]
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(backAction)];

tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
[backButton release];

Otros consejos

El método Unicode

Creo que es mucho más fácil usar un carácter Unicode para hacer el trabajo. Puede mirar a través de las flechas buscando en Google Triángulos Unicode o < a href = "http://www.fileformat.info/info/unicode/block/arrows/list.htm" rel = "nofollow noreferrer"> Flechas Unicode . A partir de iOS6, Apple cambió el carácter para que fuera un personaje emoji con un borde. Para deshabilitar el borde, agrego el 0xFE0E Selector de variación Unicode .

NSString *backArrowString = @"\U000025C0\U0000FE0E"; //BLACK LEFT-POINTING TRIANGLE PLUS VARIATION SELECTOR

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.leftButtonItem = backBarButtonItem;

El bloque de código es solo para la demostración. Funcionaría en cualquier botón que acepte una NSString.

Para obtener una lista completa de los caracteres, busque en Google el carácter Unicode y lo que desea. Aquí está la entrada para Triángulo negro a la izquierda .

Resultado

El resultado

ADVERTENCIA: Hay informes de que esto no funcionará en iOS 6. Esto podría funcionar solo en versiones anteriores del sistema operativo. Evidentemente, al menos un desarrollador ha rechazado su aplicación por usar este truco (vea los comentarios). Úselo bajo su propio riesgo. Usar una imagen (ver la respuesta anterior) podría ser una solución más segura.

Esto se puede hacer sin agregar sus propios archivos de imagen usando el botón sekr1t tipo 101 para obtener la forma correcta. Para mí, el truco fue descubrir que podía usar initWithCustomView para crear el BarButtonItem . Personalmente lo necesitaba para una barra de navegación dinámica en lugar de una toolbar , pero la probé con una barra de herramientas y el código es casi el mismo:

// create button
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"Back" forState:UIControlStateNormal];

// create button item -- possible because UIButton subclasses UIView!
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

// add to toolbar, or to a navbar (you should only have one of these!)
[toolbar setItems:[NSArray arrayWithObject:backItem]];
navItem.leftBarButtonItem = backItem;

Si estás haciendo esto en una barra de herramientas, tendrás que modificar la forma en que configuras los elementos, pero eso depende del resto de tu código y lo dejo como un ejercicio para el lector. : P Esta muestra funcionó para mí (compilado y ejecutado).

Blah blah, lee el HIG, no uses funciones no documentadas, y todo eso. Solo hay seis tipos de botones compatibles y este no es uno de ellos.

ingrese la descripción de la imagen aquí

Primero que todo, debes encontrar una imagen del botón Atrás. Utilicé una buena aplicación llamada Extractor que extrae todos los gráficos del iPhone. En iOS7 logré recuperar la imagen llamada UINavigationBarBackIndicatorDefault y estaba en color negro, ya que necesitaba un tinte rojo cambié el color a rojo con Gimp.

EDITAR:

Como mencionó btate en su comentario, no es necesario cambiar el color con el editor de imágenes. El siguiente código debería hacer el truco:

imageView.tint = [UIColor redColor];
imageView.image = [[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Luego creé una vista que contiene una imageView con esa flecha, una etiqueta con el texto personalizado y en la parte superior de la vista tengo un botón con una acción. Luego agregué una animación simple (desvanecimiento y traducción).

El siguiente código simula el comportamiento del botón Atrás, incluida la animación.

-(void)viewWillAppear:(BOOL)animated{
        UIImageView *imageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"]];
        [imageView setTintColor:[UIColor redColor]];
        UILabel *label=[[UILabel alloc] init];
        [label setTextColor:[UIColor redColor]];
        [label setText:@"Blog"];
        [label sizeToFit];

        int space=6;
        label.frame=CGRectMake(imageView.frame.origin.x+imageView.frame.size.width+space, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
        UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0, label.frame.size.width+imageView.frame.size.width+space, imageView.frame.size.height)];

        view.bounds=CGRectMake(view.bounds.origin.x+8, view.bounds.origin.y-1, view.bounds.size.width, view.bounds.size.height);
        [view addSubview:imageView];
        [view addSubview:label];

        UIButton *button=[[UIButton alloc] initWithFrame:view.frame];
        [button addTarget:self action:@selector(handleBack:) forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:button];

        [UIView animateWithDuration:0.33 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            label.alpha = 0.0;
            CGRect orig=label.frame;
            label.frame=CGRectMake(label.frame.origin.x+25, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
            label.alpha = 1.0;
            label.frame=orig;
        } completion:nil];

        UIBarButtonItem *backButton =[[UIBarButtonItem alloc] initWithCustomView:view];
}

- (void) handleBack:(id)sender{
}

EDIT:

En lugar de agregar el botón, en mi opinión, el mejor enfoque es utilizar un reconocedor de gestos.

UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBack:)];
[view addGestureRecognizer:tap];
[view setUserInteractionEnabled:YES];

No estoy seguro de si esto funcionaría, pero podría intentar crear un UINavigationController con la configuración predeterminada para crear el botón, busque el botón en la jerarquía de subvistas del controlador de navegación, llame removeFromSuperview en él, destruye el controlador de navegación y luego agrega el botón como una subvista de tu barra de herramientas. Es posible que también deba retener y el botón antes de llamar a removeFromSuperview (y luego liberar después de agregarlo como subvista de su barra de herramientas) para evitarlo siendo desasignado durante el proceso.

Para hacer un UIButton con una flecha muy cerca (no soy un diseñador;) a la flecha trasera del sistema iOS 7:

Estándar:

Flecha de retroceso del sistema estándar

Apple SD Gothic Neo

Apple SD Gothic Neo <character

En Xcode:

  • Enfóquese en el campo de valor del título del botón (o cualquier otra vista / control con contenido de texto)
  • Abrir Edición - > Caracteres especiales
  • Seleccione el grupo Paréntesis y haga doble clic en '<' carácter
  • Cambie la fuente a: Apple SD Gothic Neo, Regular con el tamaño deseado (por ejemplo, 20)
  • Cambia el color como quieras

Ref. respuesta de @ staticVoidMan a la flecha de retroceso en iOS 7

 flecha hacia atrás

Si no quieres molestarte con los archivos de imagen, la forma de la flecha se puede dibujar en una subclase UIView con el siguiente código:

- (void)drawRect:(CGRect)rect {
    float width = rect.size.width;
    float height = rect.size.height;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextBeginPath(context);
    CGContextMoveToPoint(context, width * 5.0/6.0, height * 0.0/10.0);
    CGContextAddLineToPoint(context, width * 0.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 5.0/6.0, height * 10.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 9.0/10.0);
    CGContextAddLineToPoint(context, width * 2.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 1.0/10.0);
    CGContextClosePath(context);

    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillPath(context);
}

donde la vista de flecha es proporcional a un ancho de 6.0 y una altura de 10.0

    self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;

Funciona para mí. Utilicé esto cuando tenía más pestañas y luego cabía en la barra de pestañas, y un controlador de vista pulsado desde la tecla " Más " anuló el leftBarButtonItem en su viewDidLoad.

Puede encontrar las imágenes de origen extrayéndolas de Other.artwork en UIKit $ {SDKROOT} /System/Library/Frameworks/UIKit.framework/Other.artwork. La comunidad de modding tiene algunas herramientas para extraerlos, here . Una vez que extraiga la imagen, puede escribir algo de código para cambiar el color según sea necesario y establecerla como la imagen del botón. Si puede o no enviar una cosa así (ya que está incorporando ilustraciones derivadas) puede ser un poco arriesgado, así que tal vez quiera hablar con un abogado.

La biblioteca Three20 tiene una forma de hacer esto:

  UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle: @"Title" style:UIBarButtonItemStylePlain 
                                                                target:self action:@selector(foo)];

  UIColor* darkBlue = RGBCOLOR(109, 132, 162);

  TTShapeStyle* style = [TTShapeStyle styleWithShape:[TTRoundedLeftArrowShape shapeWithRadius:4.5] next:
    [TTShadowStyle styleWithColor:RGBCOLOR(255,255,255) blur:1 offset:CGSizeMake(0, 1) next:
    [TTReflectiveFillStyle styleWithColor:darkBlue next:
    [TTBevelBorderStyle styleWithHighlight:[darkBlue shadow]
                                     shadow:[darkBlue multiplyHue:1 saturation:0.5 value:0.5]
                                      width:1 lightSource:270 next:
    [TTInsetStyle styleWithInset:UIEdgeInsetsMake(0, -1, 0, -1) next:
    [TTBevelBorderStyle styleWithHighlight:nil shadow:RGBACOLOR(0,0,0,0.15)
                                        width:1 lightSource:270 next:nil]]]]]];

  TTView* view = [[[TTView alloc] initWithFrame:CGRectMake(0, 0, 80, 35)] autorelease];
  view.backgroundColor = [UIColor clearColor];
  view.style = style;
  backButton.customView = view;


  self.navigationItem.leftBarButtonItem = backButton;

Descubrí que al usar el siguiente código simple se logró el truco (requiere una imagen personalizada en el paquete):

// Creates a back button instead of default behaviour (displaying title of previous screen)
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_arrow.png"]
                                                                   style:UIBarButtonItemStyleBordered
                                                                  target:self
                                                                  action:@selector(backAction)];

    tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
    [backButton release];

Esto es lo que terminé haciendo después de buscar todas estas soluciones y otras. Utiliza un png estirable extraído de las imágenes de stock de UIKit. De esta manera, puedes configurar el texto para lo que quieras

// Generate the background images
UIImage *stretchableBackButton = [[UIImage imageNamed:@"UINavigationBarDefaultBack.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0];
UIImage *stretchableBackButtonPressed = [[UIImage imageNamed:@"UINavigationBarDefaultBackPressed.png"] stretchableImageWithLeftCapWidth:13 topCapHeight:0];
// Setup the UIButton
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setBackgroundImage:stretchableBackButton forState:UIControlStateNormal];
[backButton setBackgroundImage:stretchableBackButtonPressed forState:UIControlStateSelected];
NSString *buttonTitle = NSLocalizedString(@"Back", @"Back");
[backButton setTitle:buttonTitle forState:UIControlStateNormal];
[backButton setTitle:buttonTitle forState:UIControlStateSelected];
backButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 2, 1); // Tweak the text position
NSInteger width = ([backButton.titleLabel.text sizeWithFont:backButton.titleLabel.font].width + backButton.titleEdgeInsets.right +backButton.titleEdgeInsets.left);
[backButton setFrame:CGRectMake(0, 0, width, 29)];
backButton.titleLabel.font = [UIFont boldSystemFontOfSize:13.0f];
[backButton addTarget:self action:@selector(yourSelector:) forControlEvents:UIControlEventTouchDown];
// Now add the button as a custom UIBarButtonItem
UIBarButtonItem *backButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];
self.navigationItem.leftBarButtonItem = backButtonItem;

Es fácil de hacer con Interface Builder en Xcode 5.x

Result

  • use Barra de herramientas y Elemento del botón de barra de Biblioteca de objetos

    Components

  • en el botón Atributos inspector edita Imagen con su imagen del botón de retroceso

    Inspector de atributos

Hecho !

Estaba tratando de hacer lo mismo, pero quería que el botón Atrás estuviera en la barra de navegación. (Realmente necesitaba un botón de retroceso, eso haría más que solo regresar, así que tuve que usar la propiedad leftBarButtonItem). Intenté lo que AndrewS sugirió, pero en la barra de navegación no se vería como debería, ya que el UIButton se convirtió en un UIBarButtonItem.

Pero encontré una manera de evitar esto. De hecho, simplemente coloqué una vista UIV debajo del botón UIB y configuré la vista personalizada para el artículo UIBarButtonItem. Aquí está el código, si alguien lo necesita:

// initialize button and button view
UIButton *backButton = [UIButton buttonWithType:101];
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, backButton.frame.size.width, backButton.frame.size.height)];

[backButton addTarget:self action:@selector(backButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"Back" forState:UIControlStateNormal];
[backButtonView addSubview:backButton];

// set buttonview as custom view for bar button item
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButtonItem;

// push item to navigationbar items
[self.navigationController.navigationBar setItems:[NSArray arrayWithObject:backButtonItem]];

Para crear una imagen para la barra de herramientas de la UIT, cree un png en photoshop y DONDE NUNCA HAY CUALQUIER color que lo ponga blanco, y donde sea alfa = 0, entonces lo deja en paz.

El SDK en realidad pone el borde alrededor del icono que has creado y lo vuelve blanco sin que tengas que hacer nada.

Mira, esto es lo que hice en Photoshop para mi botón de avance (obviamente, lo cambié por el botón de atrás):

http://twitpic.com/1oanv

y esto es lo que parecía en Interface Builder

http://twitpic.com/1oaoa

Solución SIN usar un png. Basado en esta respuesta SO: Agregar la pequeña flecha al lado derecho de una celda en una celda TableView de iPhone

¡Solo volteando el UITableViewCell horizontalmente!

UIButton *btnBack = [[UIButton alloc] initWithFrame:CGRectMake(0, 5, 70, 20)];

// Add the disclosure
CGRect frm;
UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.transform = CGAffineTransformScale(CGAffineTransformIdentity, -1, 1);
frm = self.btnBack.bounds;
disclosure.frame = CGRectMake(frm.origin.x, frm.origin.y, frm.size.width-25, frm.size.height);
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
disclosure.userInteractionEnabled = NO;
[self.btnBack addSubview:disclosure];

// Add the label
UILabel *lbl = [[UILabel alloc] init];
frm = CGRectOffset(self.btnBack.bounds, 15, 0);
lbl.frame = frm;
lbl.textAlignment = NSTextAlignmentCenter;
lbl.text = @"BACK";
[self addSubview:lbl];

Si desea evitar dibujarlo usted mismo, puede usar la clase no documentada: Botón de navegación con estilo 1. Esto, por supuesto, podría impedir que su solicitud sea aprobada ... / John

Bueno, no tienes que tener un botón diferente para cada tamaño, puedes usar [UIImage stretchableImageWithLeftCapWidth: topCapHeight:] , pero lo único que he encontrado son imágenes personalizadas.

Tuve un problema similar y salí de una biblioteca PButton . Y la muestra es el botón de navegación hacia atrás, como el botón, que se puede utilizar en cualquier lugar como un botón personalizado.

Algo como esto: ingrese la descripción de la imagen aquí

Ejemplo en Swift 3, con un botón anterior y otro en la parte superior derecha.

let prevButtonItem = UIBarButtonItem(title: "\u{25C0}", style: .plain, target: self, action: #selector(prevButtonTapped))
let nextButtonItem = UIBarButtonItem(title: "\u{25B6}", style: .plain, target: self, action: #selector(nextButtonTapped))
self.navigationItem.rightBarButtonItems = [nextButtonItem, prevButtonItem]

Swift

// create button
    var backButton = UIButton(type: 101)

    // left-pointing shape!
    backButton.addTarget(self, action: #selector(self.backAction), for: .touchUpInside)
    backButton.setTitle("Back", for: .normal)

    // create button item -- possible because UIButton subclasses UIView!
    var backItem = UIBarButtonItem(customView: backButton)

    // add to toolbar, or to a navbar (you should only have one of these!)
    toolbar.items = [backItem]
    navItem.leftBarButtonItem = backItem

Prueba esto. Estoy seguro de que no necesita una imagen del botón Atrás para crear una de estas.

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back"
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(yourSelectorGoesHere:)];
self.navigationItem.backBarButtonItem = backButton;

Eso es todo lo que tienes que hacer :)

¿Por qué haces esto? Si quieres algo que se parezca a una barra de navegación, usa UINavigationBar.

Las barras de herramientas tienen un estilo visual específico asociado a ellas. Las directrices de interfaz humana para el estado del iPhone:

  

Aparece una barra de herramientas en el borde inferior de la pantalla y contiene botones que realizan acciones relacionadas con los objetos en la vista actual.

Luego da varios ejemplos visuales de iconos aproximadamente cuadrados sin texto. Les insto a seguir el HIG en esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top