uinavigationcontroller - La alineación de UIBarButtonItem personalizada está desactivada con iOS7
uibutton (4)
Así que tengo el mismo problema que muchos otros están experimentando al crear un UIBarButtonItem con un UIButton como una vista personalizada.
Básicamente, el botón es de aproximadamente 10 píxeles a la izquierda o la derecha. Cuando uso un elemento BarButtonIt regular sin una vista personalizada, esto no sucede.
Esta publicación proporcionó una solución parcial: UIBarButton con vista personalizada
Aquí está mi código que he creado subclasificando UIButton (como se indica en la otra publicación)
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF ITS A RIGHT BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
Esto funciona muy bien, pero cuando vuelvo a colocar un controlador de vista desde el controlador de navegación en esta vista principal, el botón todavía está colocado incorrectamente durante aproximadamente .3 segundos, y luego encaja en el recuadro correcto.
Esta es una gran monstruosidad y no tengo idea de cómo evitar que se rompa de esa manera. ¿Alguna idea? ¡Gracias!
Alternativamente, puede ajustar los marcos de los contenidos de su vista personalizada (-5 para las subvistas a la izquierda, +5 para las subvistas a la derecha), y siempre que su vista personalizada no tenga clipsToBounds
configurados en YES
se clipsToBounds
. No es la más limpia, pero otras soluciones sugeridas pueden ser incluso más intrépidas de IMO.
Las subvistas aparecerán cortadas por 5 puntos en IB, pero el contenido completo se mostrará cuando ejecute la aplicación en el simulador.
No es un gran fanático de subclasificar UIButton
o método swizzling de la respuesta de Marius: https://.com/a/19317105/287403
Solo utilicé una envoltura simple y moví la x del marco del botón en una dirección negativa hasta que encontré la posición correcta. El toque del botón también parece estar bien (aunque puede ampliar el ancho del botón para que coincida con el desplazamiento negativo si lo necesita).
Aquí está el código que utilizo para generar un nuevo botón de retroceso:
- (UIBarButtonItem *) newBackButton {
// a macro for the weak strong dance
@weakify(self);
UIButton *backButton = [[UIButton alloc] init];
[backButton setTitle:@"Back" forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont systemFontOfSize:17];
CGFloat width = [@"Back" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:nil].size.width + 27;
backButton.frame = CGRectMake(-17.5, 0, width + 17.5, 44);
[backButton setImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] forState:UIControlStateNormal];
[backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 14, 0, 0)];
[backButton setTitleColor:mTCOrangeColor forState:UIControlStateNormal];
backButton.contentEdgeInsets = UIEdgeInsetsZero;
backButton.imageEdgeInsets = UIEdgeInsetsZero;
[backButton addEventHandler:^(id sender) {
// a macro for the weak strong dance
@strongify(self);
// do stuff here
} forControlEvents:UIControlEventTouchUpInside];
UIView *buttonWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
[buttonWrapper addSubview:backButton];
return [[UIBarButtonItem alloc] initWithCustomView:buttonWrapper];
}
No he probado este código para varios elementos del botón de navegación, pero parece que funciona para botones individuales. He sobrescrito la barra UINavigation y su método layoutSubviews.
Primero, se define una constante para el desplazamiento horizontal en la parte superior del archivo. Modificar es como desees:
static CGFloat const kNavBarButtonHorizontalOffset = 10;
layoutSubviews:
- (void)layoutSubviews{
[super layoutSubviews];
//Do nothing on iOS6
if ( ![[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f){return;}
UINavigationItem * navigationItem = [self topItem];
for(UIBarButtonItem * item in [navigationItem rightBarButtonItems]){
UIView * subview = [item customView];
CGFloat width = CGRectGetWidth(subview.frame);
CGRect newRightButtonRect = CGRectMake(CGRectGetWidth(self.frame) - width - kNavBarButtonHorizontalOffset,
CGRectGetMinY(subview.frame),
width,
CGRectGetHeight(subview.frame));
[subview setFrame:newRightButtonRect];
}
for(UIBarButtonItem * item in [navigationItem leftBarButtonItems]){
UIView * subview = [item customView];
CGRect newRightButtonRect = CGRectMake(kNavBarButtonHorizontalOffset,
CGRectGetMinY(subview.frame),
CGRectGetWidth(subview.frame),
CGRectGetHeight(subview.frame));
[subview setFrame:newRightButtonRect];
}
}
Tuve el mismo problema que tú y muchos otros. Después de mucho tiempo tratando de arreglarlo, finalmente lo hice. Esta es la categoría que debe incluir en su archivo * -Prefix.pch. ¡Y eso es todo!
UINavigationItem + iOS7Spacing.h
#import <Foundation/Foundation.h>
@interface UINavigationItem (iOS7Spacing)
@end
UINavigationItem + iOS7Spacing.m
#import "UINavigationItem+iOS7Spacing.h"
#import <objc/runtime.h>
@implementation UINavigationItem (iOS7Spacing)
- (BOOL)isIOS7
{
return ([[[UIDevice currentDevice] systemVersion] compare:@"7" options:NSNumericSearch] != NSOrderedAscending);
}
- (UIBarButtonItem *)spacer
{
UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
space.width = -11;
return space;
}
- (void)mk_setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem
{
if ([self isIOS7] && leftBarButtonItem) {
[self mk_setLeftBarButtonItem:nil];
[self mk_setLeftBarButtonItems:@[[self spacer], leftBarButtonItem]];
} else {
[self mk_setLeftBarButtonItem:leftBarButtonItem];
}
}
- (void)mk_setLeftBarButtonItems:(NSArray *)leftBarButtonItems
{
if ([self isIOS7] && leftBarButtonItems && leftBarButtonItems.count > 0) {
NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:leftBarButtonItems.count + 1];
[items addObject:[self spacer]];
[items addObjectsFromArray:leftBarButtonItems];
[self mk_setLeftBarButtonItems:items];
} else {
[self mk_setLeftBarButtonItems:leftBarButtonItems];
}
}
- (void)mk_setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem
{
if ([self isIOS7] && rightBarButtonItem) {
[self mk_setRightBarButtonItem:nil];
[self mk_setRightBarButtonItems:@[[self spacer], rightBarButtonItem]];
} else {
[self mk_setRightBarButtonItem:rightBarButtonItem];
}
}
- (void)mk_setRightBarButtonItems:(NSArray *)rightBarButtonItems
{
if ([self isIOS7] && rightBarButtonItems && rightBarButtonItems.count > 0) {
NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:rightBarButtonItems.count + 1];
[items addObject:[self spacer]];
[items addObjectsFromArray:rightBarButtonItems];
[self mk_setRightBarButtonItems:items];
} else {
[self mk_setRightBarButtonItems:rightBarButtonItems];
}
}
+ (void)mk_swizzle:(SEL)aSelector
{
SEL bSelector = NSSelectorFromString([NSString stringWithFormat:@"mk_%@", NSStringFromSelector(aSelector)]);
Method m1 = class_getInstanceMethod(self, aSelector);
Method m2 = class_getInstanceMethod(self, bSelector);
method_exchangeImplementations(m1, m2);
}
+ (void)load
{
[self mk_swizzle:@selector(setLeftBarButtonItem:)];
[self mk_swizzle:@selector(setLeftBarButtonItems:)];
[self mk_swizzle:@selector(setRightBarButtonItem:)];
[self mk_swizzle:@selector(setRightBarButtonItems:)];
}
@end