it-roy-ru.com

Как плавно перейти от полупрозрачного к непрозрачному UINavigationBar iOS?

Я сталкиваюсь с проблемами перенастройки UINavigationBar на iOS 7 и 8 при переходе между представлениями.

В настоящее время мое приложение содержит следующий поток UIViewController:

VC1 -> VC2 -> VC3

В этом потоке

  • VC1 является домашним экраном и имеет непрозрачный UINavigationBar
  • VC2 имеет полупрозрачный UINavigationBar
  • VC3 возвращается к наличию непрозрачного UINavigationBar

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

в VC2

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // configure appearance
    [self.navigationController.navigationBar configureTranslucentAppearance];
}

И в VC1 и VC3

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // configure appearance
    [self.navigationController.navigationBar restoreDefaultAppearance];
}

Вот реализации двух вспомогательных функций, перечисленных выше:

- (void)restoreDefaultAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor JTTextNavBar]}];
    [self setTintColor:[UIColor JTTextNavBar]];
    [self setBarTintColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor JTBackgroundNavBarWithAlpha:1.0]];
    [self setShadowImage:[UIImage navigationBarShadowImage]];
    [self setTranslucent:NO];
}

- (void)configureTranslucentAppearance {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

    [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    [self setBackgroundColor:[UIColor clearColor]];
    [self setShadowImage:[UIImage new]];
    [self setTranslucent:YES];
}

Это самый основной способ обработки этого перехода. Имеет следующие визуальные артефакты:

  • При переходе от VC1 -> VC2 в тот момент, когда вы начинаете переход, панель навигации становится черной. Анимация завершается нормально enter image description here
  • При переходе от VC2 -> VC1 навигационная панель мгновенно меняет цвет приложения по умолчанию, прежде чем завершится переход. enter image description here
  • При переходе от VC2 -> VC3 панель навигации мгновенно переходит из полупрозрачного в цвет панели навигации приложения, а затем анимируются элементы меню и тело VC. enter image description here
  • При переходе от VC3 -> VC2 навигационная панель мгновенно становится черной и остается такой до завершения перехода. enter image description here

Ни один из этих переходов не выглядит хорошо вообще. В идеале я хотел бы, чтобы представления плавно переходили вместе с их новой UINavigationBar, но единственный способ, которым я видел, чтобы сделать это успешно, это вручную добавить панель инструментов для каждой xib.

Какие-либо предложения? Извиняюсь, если это описание сбивает с толку :(

Правка: Добавлены обрезанные изображения UINavigationBar и верхней части UIViewController для каждого из перечисленных переходов.

27
alexgophermix

Я наконец нашел достойное решение!

Похоже, что нет правильного способа плавного перехода от непрозрачного к прозрачному UINavigationBar, НО вы можете плавно перейти от контроллера представления с видимой строкой состояния к контроллеру со скрытой строкой состояния.

Это открывает возможный обходной путь, который заключается в добавлении следующего в viewWillAppear of VC2 сверху:

[self.navigationController setNavigationBarHidden:YES animated:YES];

Получив это, вручную добавьте UINavigationBar в xib и настройте его как прозрачный (и добавьте все необходимые UIBarButtonItem и представления).

Если все правильно подключено, переход от VC1 к VC2 будет скрывать UINavigationBar с той же скоростью, что и переход представления, и VC2 будет отображаться со встроенным UINavigationBar

Примечание: Для правильной работы вам необходимо убедиться, что в viewWillAppear View Controllers, к которым можно получить доступ из VC2 вы сбросили UINavigationBar, чтобы он был виден (при необходимости) через:

[self.navigationController setNavigationBarHidden:NO animated:YES];

TL; DR - вручную добавить UINavigationBar к вашему контроллеру прозрачной навигационной панели и в viewWillAppear скрыть значение по умолчанию через setNavigationBarHidden:animated:

14
alexgophermix

Черный цвет, который вы видите, является цветом фона представления UINavigationController's. Один из способов минимизировать видимость - это манипулировать цветом фона этого вида с цветом представления контроллера исходящего/входящего представления. Это хорошо работает, если вы работаете со сплошными цветами. Другой подход заключается в расширении ваших представлений за непрозрачной панелью навигации с помощью UIViewController.extendedLayoutIncludesOpaqueBars = YES;

14
TomSwift

Установите цвет фона UIWindow для tintColor панели навигации.

4
user501836

всегда использовать полупрозрачный, плюс добавить пользовательский интерфейс с цветом под ним и анимировать его альфа?

3
dOM

Вы можете создать свою собственную панель навигации, используя только UIView, и таким образом у вас будет полный контроль над ее внешним видом, макетом, выцветанием и т.д Я недавно отказался от использования UINavigationBar, поскольку работать с ним может быть затруднительно, поскольку вы открывают, и теперь я никогда этим не пользуюсь. 

У меня есть контроллер корневого представления, который имеет UIView, который представляет панель навигации. Если я хочу сделать что-то вроде добавления кнопки «Назад», изменения цвета, отображения панели навигации или скрытия, изменения прозрачности и т.д., Все это контролируется RVC, и другие контроллеры представления вызывают методы в RVC для изменения навигации бар в зависимости от их требований к внешнему виду.

RVC имеет контейнерное представление, которое является полным размером представления контроллера, и другие контроллеры представления загружаются в это . Немного конфигурации, чтобы настроить все, но как только это сделано, это структура, которую можно использовать в каждый проект, который использует панель навигации очень быстро.

1
Gruntcakes

Так что я тоже с этим боролся.

К сожалению, я не смог добавить свою собственную панель навигации через раскадровку. Вместо этого (и я предупреждаю вас, что это неправильно) я добавляю представление в ViewController с непрозрачной панелью навигации, которая имеет отрицательное поле и простирается под панелью навигации.

Когда ViewController с прозрачной панелью навигации нажимается, панель сразу становится прозрачной, но из-за идентично окрашенного представления, которое я поместил прямо за ним, изменение не заметно. И вуаля.

Код, который я имею, довольно простой и написан на C # (Xamarin), но по причинам полноты ....

  var backing = new UIView(new CGRect(0, -68, this.View.Frame.Width, 64f));
  backing.BackgroundColor = UIColor.Green;
  this.View.AddSubview(backing);
1
James Mundy

Я боролся с почти идентичной проблемой. Там действительно нет плавных переходов, использующих панель навигации или панель инструментов в качестве размытия. Лучший вариант, который я нашел *, - сделать изображение из вида, а затем использовать это изображение для перехода. Особенно, если вам просто нужно это для переходов, это почти самый дешевый вариант, который все еще обеспечивает отличный UI/UX.

* Единственное предостережение в том, что некоторые эффекты пользовательского интерфейса на панели навигации и панели инструментов не отображаются, когда вы делаете снимок, снимок экрана или растеризацию UIView в качестве изображения. Это незначительно, если используется для перехода.

1
Fennelouski

Изменить цвет фона работы для меня

window?.backgroundColor = Color.red.toUIColor()
0
luhuiya

У меня есть еще одно решение ... для тех, кто сейчас проводит рефакторинг проекта и не может добавить панель навигации везде ... Это не идеальное решение, как @alexgophermix. Но это тоже неплохо:

let transition = CATransition()
        transition.duration = 0.6
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        transition.type = kCATransitionFade
        navigationController?.navigationBar.shadowImage = UIImage()
        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.layer.add(transition, forKey: nil)
        navigationController?.view.backgroundColor = .clear

Я устанавливаю свою навигационную панель в viewDidLoad (), так что это работает везде и дает немного другой переход. В моем случае я где-то устанавливал четкие фоны и отдыхал с градиентным изображением. Так что это небольшое изменение хорошо для всех. Этот переход не очень заметен, но не выглядит плохо :)

0
Amber K