UINavigationBar tintColor с градиентом - PullRequest
10 голосов
/ 30 января 2009

Я бы хотел программно изменить tintColor UINavigationBar и сохранить градиент как в Интерфейсном Разработчике.

Когда я изменяю tintColor в моем коде, градиент исчезает, но когда я изменяю tintColor в Интерфейсном Разработчике, градиент сохраняется.

Есть идеи?

Ответы [ 5 ]

20 голосов
/ 27 февраля 2013

Так что это старый вопрос, но я наткнулся на него, когда искал что-то похожее на этот вопрос, но другое. В надежде, что это поможет кому-то другому (или что кто-то другой покажет мне лучший путь) ...

Как реализовать пользовательский градиент на панели UINavigationBar?

Во-первых, давайте получим наш собственный градиент, как обычно (как CALayer):

- (CALayer *)gradientBGLayerForBounds:(CGRect)bounds
{
    CAGradientLayer * gradientBG = [CAGradientLayer layer];
    gradientBG.frame = bounds;
    gradientBG.colors = @[ (id)[[UIColor redColor] CGColor], (id)[[UIColor purpleColor] CGColor] ];
    return gradientBG;
}

Итак, градиент, который выглядит как сомнительный выбор грима панк-рокера, и это хорошо, так как этот код предназначен для гипотетического приложения У меня есть панк-рокер с сомнительными вкусами в моем кармане . Это имя меня будет слишком длинным ..

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

Вместо этого давайте рассмотрим замечательный удобный метод, который мы используем в iOS5 + для изменения внешнего вида всех UINavigationBar (s) в нашем приложении:

[[UINavigationBar appearance] setBackgroundImage:SOME_IMAGE
                                   forBarMetrics:UIBarMetricsDefault];

Единственная проблема здесь в том, что у нас нет UIImage, у нас есть CALayer. Что делать энтузиасту панк-рокера?

CALayer * bgGradientLayer = [self gradientBGLayerForBounds:ONE_OF_YOUR_NAV_CONTROLLERS.navigationBar.bounds];
UIGraphicsBeginImageContext(bgGradientLayer.bounds.size);
[bgGradientLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * bgAsImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Итак, теперь мы преобразовали наш CALayer в UIImage (надеюсь), поэтому осталось только установить его:

if (bgAsImage != nil)
{
    [[UINavigationBar appearance] setBackgroundImage:bgAsImage
                                       forBarMetrics:UIBarMetricsDefault];
}
else
{
    NSLog(@"Failded to create gradient bg image, user will see standard tint color gradient.");
}

Что мне нравится в этом решении

  • централизованный код (в AppDelegate) для всех UINavigationBar (s) в моем приложении
  • tintColor будет по-прежнему учитываться для всех кнопок UINavigation (назад, редактировать и т. Д.)
  • если создание UIImage завершится неудачно, мои UINavigationBar (s) по-прежнему будут учитывать tintColor
  • Мне не нужно зависеть от фактического ресурса изображения / его легко обновить

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

~ Спасибо

14 голосов
/ 08 февраля 2009

Установите для barStyle значение UIBarStyleBlackTranslucent Установите оттенок цвета следующим образом:

navigationBar.tintColor = [UIColor colorWithRed:.7 green:.5 blue:.2 alpha:1];

Это установит соответствующий градиент. Используйте любую нужную комбинацию.

1 голос
/ 21 сентября 2015

Я просто написал это как расширение UIImage для Swift 2.0. Может быть, это полезно.

extension UIImage {

    class func convertGradientToImage(colors: [UIColor], frame: CGRect) -> UIImage {

        // start with a CAGradientLayer
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = frame

        // add colors as CGCologRef to a new array and calculate the distances
        var colorsRef : [CGColorRef] = []
        var locations : [NSNumber] = []

        for i in 0 ... colors.count-1 {
            colorsRef.append(colors[i].CGColor as CGColorRef)
            locations.append(Float(i)/Float(colors.count))
        }

        gradientLayer.colors = colorsRef
        gradientLayer.locations = locations

        // now build a UIImage from the gradient
        UIGraphicsBeginImageContext(gradientLayer.bounds.size)
        gradientLayer.renderInContext(UIGraphicsGetCurrentContext()!)
        let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        // return the gradient image
        return gradientImage
    }
}

Назовите это так:

let colors = [
    UIColor.blueColor(),
    UIColor.greenColor()
    // and many more if you wish
]
let gradientImage = UIImage.convertGradientToImage(colors, frame: navigationBar.bounds)
navigationBar.setBackgroundImage(gradientImage, forBarMetrics: .Default)
0 голосов
/ 21 марта 2016

Хороший способ использования maskView

// create gradient view
let gradientView: UIView = UIView(frame: frame)
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = gradientView.bounds
gradient.colors = [UIColor.grayColor().CGColor, UIColor.clearColor().CGColor]
gradientView.layer.insertSublayer(gradient, atIndex: 0)

//set appearance 
UINavigationBar.appearance().maskView = gradientView
0 голосов
/ 03 апреля 2012
navigation.tintColor = [UIColor colorWithRed:0.47f green:0.23f blue:0.61f alpha:1.0f];
...