Подтвердить что ты не робот

Пользовательская кнопка возврата iOS 7

Я хочу использовать пользовательскую кнопку возврата. в iOS 6 все идеально, но iOS 7 странно.

[[UIBarButtonItem appearance] setBackButtonBackgroundImage:[[UIImage imageNamed:@"back_button_normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0, 0, 12.0)] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

во-первых, у него нет стрелки iOS 7 и фонового изображения.

(русский язык)

initial state

тогда, если вы нажмете кнопку, появится фоновое изображение. Также у меня было фоновое изображение, установленное для состояния UIControlStateHighlighted, и когда вы удерживаете кнопку нажатой, появляется выделенное изображение. После того, как какая-либо кнопка назад нажата, все кнопки назад имеют фоновое изображение.

once pressed

НО! Если вы представляете контроллер модального просмотра, отпустите его, а затем нажмите любой контроллер представления - на каждой задней кнопке появится стрелка iOS 7.

Я использую DP5. Это ошибка UIKit?

PS Также я попытался создать кнопку возврата вручную, используя UIBarButtonItem, установить для него фоновое изображение, затем self.navigationItem.backBarButtonItem = barButtonItem; Не помогло. Затем я попытался установить фоновое изображение в отключенное состояние и изменить включенное свойство элемента панели бара, тоже не помогло.

enter image description here

4b9b3361

Ответ 1

Это не ошибка, как выглядит Back button в iOS 7. Например:

enter image description here

Вероятно, вы должны использовать новую концепцию для своего приложения, а не устанавливать фоновое изображение для кнопки "Назад" в iOS 7.

Если вы все еще хотите, чтобы кнопка возврата была такой же, как и в iOS6, вы должны, вероятно, создать эти кнопки назад вручную:

- (void)loadView
{
    [super loadView];

    UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 60.0f, 30.0f)];
    UIImage *backImage = [[UIImage imageNamed:@"back_button_normal.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0f, 0, 12.0f)];
    [backButton setBackgroundImage:backImage  forState:UIControlStateNormal];
    [backButton setTitle:@"Back" forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(popBack) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    self.navigationItem.leftBarButtonItem = backButtonItem;
}

-(void) popBack {
  [self.navigationController popViewControllerAnimated:YES];
}

Изменить: не разбивать жестов-прокрутки (Вот источник)

self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;

Ответ 2

Пользовательское фоновое изображение, не появившееся при первом нажатии, было исправлено в iOS 7 GM.

Чтобы скрыть стандартный задний индикатор, используйте этот код:

if ([UINavigationBar instancesRespondToSelector:@selector(setBackIndicatorImage:)]) { // iOS 7
    [navigationBarAppearance setBackIndicatorImage:[UIImage imageNamed:@"transparent_1px"]];
    [navigationBarAppearance setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"transparent_1px"]];
}

Ответ 3

Пользовательское фоновое изображение, не появившееся первоначально, не было исправлено в iOS7 GM или окончательном, насколько я могу судить. Я вижу ту же проблему. Кажется, это ошибка Apple; частный вид Apple использует просто не получает вызов setNeedsDisplay, когда он нуждается в нем при первоначальном отображении. Выполнение чего-либо, что вызывает этот вызов, должно исправлять его - например, нажатие на него (что, скорее всего, изменяет внутреннее состояние, так что он вызывает setNeedsDisplay сам по себе), или привносит модальный уровень (что, вероятно, заставляет повторно отобразить всю иерархию представлений на следующем viewWillAppear: call).

Использование leftBarItems также может работать, но это может вызвать множество проблем с обслуживанием существующего кода (некоторые экраны могут иметь свои собственные элементы слева, ожидая, что, когда они вернутся к нулю, они восстанавливают исходный задний элемент, например).

Как уже упоминалось, в идеале вы сможете перейти на внешний вид без полей на iOS7, что означает, что ошибка не является очевидной (поскольку фоновое изображение отсутствует). Однако для некоторых ситуаций перехода iOS6/iOS7 это может быть сложно (большое количество экранов и/или необходимость поддерживать более старые версии iOS на некоторое время и слишком сложно реализовать два взгляда, и он не выглядит хорошо без полей без других изменения). Если это произойдет, следующий патч должен работать:

#import <objc/runtime.h>

@implementation UINavigationBar (BackButtonDisplayFix)

+ (void)load
{
    if ([UIDevice currentDevice].systemVersion.intValue >= 7)
    {
        /*
         * We first try to simply add an override version of didAddSubview: to the class.  If it
         * fails, that means that the class already has its own override implementation of the method
         * (which we are expecting in this case), so use a method-swap version instead.
         */
        Method didAddMethod = class_getInstanceMethod(self, @selector(_displaybugfixsuper_didAddSubview:));
        if (!class_addMethod(self, @selector(didAddSubview:),
                             method_getImplementation(didAddMethod),
                             method_getTypeEncoding(didAddMethod)))
        {
            Method existMethod = class_getInstanceMethod(self, @selector(didAddSubview:));
            Method replacement = class_getInstanceMethod(self, @selector(_displaybugfix_didAddSubview:));
            method_exchangeImplementations(existMethod, replacement);
        }
    }
}

- (void)_displaybugfixsuper_didAddSubview:(UIView *)subview
{
    [super didAddSubview:subview];
    [subview setNeedsDisplay];
}

- (void)_displaybugfix_didAddSubview:(UIView *)subview
{
    [self _displaybugfix_didAddSubview:subview]; // calls the existing method
    [subview setNeedsDisplay];
}

@end

Примечание: UINavigationBar в настоящее время имеет переопределение рассматриваемого метода, поэтому я ожидаю, что будет использоваться стиль method_exchangeImplementations. Я просто добавил другой материал для безопасности, если Apple изменит свой код. Мы можем пойти без границ, но я нашел, что этот подход работал как опция (до более тщательного повышения UI), по крайней мере.

Примечание: эта ошибка исправлена ​​в iOS 7.1. Таким образом, исправление может быть обусловлено только установкой методов при запуске >= 7.0 и < 7.1.

Ответ 4

Существует лучшее решение, которое не включает метод swizzling.

Вам нужно добавить метод UINavigationViewControllerDelegate где-то в вашем приложении.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
dispatch_async(dispatch_get_main_queue(), ^{
    [[navigationController.navigationBar subviews] makeObjectsPerformSelector:@selector(setNeedsDisplay)];
});

}

Ответ 5

Мое решение для iOS 7 и выше.

Сначала сделайте кнопку возврата по умолчанию невидимой.

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

затем установите по умолчанию backIndicatorImage кнопки "Назад", используя пользовательское изображение.

[UINavigationBar appearance].backIndicatorImage = [[UIImage imageNamed:@"topbar_icon_back_n.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorTransitionMaskImage = [[UIImage imageNamed:@"topbar_icon_back_p.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

В этот момент создайте пользовательский UINavigationBar для изменения размера _UINavigationBarBackIndicatorView, который содержит выше backIndicatorImage.

const CGPoint SANavigationBarOffset = {-8, 11.5};

@implementation SANavigationBar

- (void)layoutSubviews
{
    [super layoutSubviews];

    // set back button position
    NSArray *classNamesToReposition = @[@"_UINavigationBarBackIndicatorView"];

    for (UIView *view in [self subviews]) {
        if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) {
            CGRect frame = [view frame];
            frame.origin.x = 0;
            frame.origin.y = 0;

            [view setFrame:frame];
        }
    }
}

@end

тогда установите его как мой navigationBar

// set custom NavagationBar for back button position
[self.navigationController setValue:[[SANavigationBar alloc] init] forKey:@"navigationBar"];

Ответ 6

Добавить кнопку в качестве элемента навигации в ios7, как показано ниже

 UIButton *btnAdd = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 30)];

        [btnAdd setContentMode:UIViewContentModeScaleAspectFit];

        [btnAdd setBackgroundImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal];

        [btnAdd addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

        UIBarButtonItem *btnAdd = [[UIBarButtonItem alloc] initWithCustomView:imView];

        self.navigationItem.rightBarButtonItem = btnAdd;

Ответ 7

С помощью Swift вы можете просто добавить расширение:

extension UIViewController: UIGestureRecognizerDelegate {
    func popBack() {
        self.navigationController?.popViewControllerAnimated(true)
    }

    func enableCustomBackButtom() {
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon-back"), style: UIBarButtonItemStyle.Plain, target: self, action:"popBack")

        self.navigationController?.interactivePopGestureRecognizer.delegate = self
    }
}

И в вашем UIViewController используйте вот так:

self.enableCustomBackButtom()

Ответ 8

Я просто сделал это с тем же поведением, что и в iOS6 (обратите внимание, что navigationBar является UINavigationBar), убедитесь, что navigationBar имеет topItem

UINavigationItem *topItemNavigation = [navigationBar topItem];

UIBarButtonItem *barButtonTopItemNavigation = [[UIBarButtonItem alloc] initWithTitle:topItemNavigation.title style:UIBarButtonItemStyleBordered target:nil action:nil];

[barButtonTopItemNavigation setBackButtonBackgroundImage:YOUR_IMAGE_BACKGROUND forState:UIControlStateNormal barMetrics:UIBarMetricsDefault ];
            [topItemNavigation setBackBarButtonItem: barButtonTopItemNavigation];
        }

Ответ 9

Мое решение состояло в том, чтобы написать категорию в UINavigationItem. Это для iOS7.

- (void)mdSetCustomBackButton:(UINavigationController *)navigationController
{
    MDBackButton *backButton = [[MDBackButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0) navigationController:navigationController];
    [backButton addTarget:self action:@selector(popBack:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    [self setLeftBarButtonItem:barButtonItem];
    [navigationController.interactivePopGestureRecognizer setDelegate:(id<UIGestureRecognizerDelegate>)self];
}

- (void)popBack:(MDBackButton *)sender
{
    [sender.navigationController popViewControllerAnimated:YES];
}

И подкласс UIButton для добавления свойства UINavigationController (чтобы поп и установить прокрутить обратно делегат).

@property (nonatomic, weak) UINavigationController *navigationController;

@implementation MDBackButton

- (id)initWithFrame:(CGRect)frame navigationController:(UINavigationController *)navigationController
{
    self = [super initWithFrame:frame];
    if(self){
        _navigationController = navigationController;
        [self setImage:[UIImage imageNamed:@"back_button"] forState:UIControlStateNormal];
    }
    return self;
}

Ответ 10

Это работа для меня:

- (void)setCustomNavigationBackButton
{    
  self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

  UIImage *myIcon = [self imageWithImage:[UIImage imageNamed:@"backbutton.png"] scaledToSize:CGSizeMake(20, 20)];

  self.navigationController.navigationBar.backIndicatorImage = myIcon;
  self.navigationController.navigationBar.backIndicatorTransitionMaskImage = myIcon;
}

- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize 
{
  //UIGraphicsBeginImageContext(newSize);
  // In next line, pass 0.0 to use the current device pixel scaling factor (and thus account for Retina resolution).
  // Pass 1.0 to force exact pixel size.
  UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
  [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
  UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return newImage;
}

Кроме того, пользовательский шрифт с пользовательским цветом:

//self.navigationController.navigationBar.tintColor = [UIColor whiteColor];

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:
 @{NSForegroundColorAttributeName:[UIColor whiteColor],
   NSFontAttributeName:[UIFont fontWithName:@"Signika-Bold" size:20]}

forState:UIControlStateNormal];

Ссылка: fooobar.com/questions/19407/...

Ответ 11

Я использую эти коды ниже, который работает в iOS 8

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
button.exclusiveTouch = YES;
button.titleLabel.font = [UIFont systemFontOfSize:14.0];
[button setTitleColor:kWhiteColor forState:UIControlStateNormal];
[button setTitleColor:[UIColor colorWithRed:1/255.0 green:36/255.0 blue:60/255.0 alpha:1.0] forState:UIControlStateHighlighted];
[button setTitle:@"Back" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"barbutton_back"] forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)];
CGSize fontSize = [button.titleLabel sizeThatFits:CGSizeMake(100.0, 30.0)];
button.frame = CGRectMake(0.0, 0.0, button.imageView.image.size.width+fontSize.width, 30.0);
UIBarButtonItem *barbtn = [[UIBarButtonItem alloc] initWithCustomView:button];
//fix iOS 7 left margin
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSpacer.width = -10;
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSpacer,barbtn, nil];

Ответ 12

-(void) viewWillAppear:(BOOL)animated
{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setFrame:CGRectMake(0, 0, 30, 44)];
    [btn setImage:[UIImage imageNamed:@"btnBack.png"] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(PopToView) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *btnBack = [[UIBarButtonItem alloc] initWithCustomView:btn];
    [btnBack setTintColor:[UIColor whiteColor]];
    [[self.navigationController navigationItem] setLeftBarButtonItem:btnBack];

}