Удалить текст элемента панели вкладок, показать только изображение

90

Простой вопрос: как удалить текст элемента панели вкладок и показать только изображение?

Я хочу, чтобы элементы бара нравились в приложении Instagram:

введите описание изображения здесь

В инспекторе в xcode 6 я удаляю заголовок и выбираю изображение @ 2x (50 пикселей) и @ 3x (75 пикселей). Однако изображение не использует свободное пространство удаленного текста. Есть идеи, как добиться того же изображения элемента панели вкладок, что и в приложении Instagram?

Голосовать за
источник
3
дублировать с помощью: stackoverflow.com/questions/11811831/only-image-as-uitabbaritem/…
algal
1
может использоваться ""для названия?
holex
1
Установка смещений - это всего лишь уловка, правильный ответ чуть ниже. Вы должны использовать navigationItem.title = "some title"
Давид Сирадегян

Ответы:

131

Вы должны поиграть со imageInsetsсвойством UITabBarItem. Вот пример кода:

let tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "more")
tabBarItem.imageInsets = UIEdgeInsets(top: 9, left: 0, bottom: -9, right: 0)

Значения внутри UIEdgeInsetsзависят от размера вашего изображения. Вот результат этого кода в моем приложении:

введите описание изображения здесь

Мустафа
источник
25
Вы также можете настроить вставки изображений в инспекторе.
Голосовать за
Магические числа - плохая идея. Пожалуйста, посмотрите мой ответ, чтобы узнать об универсально совместимом способе сделать то же самое.
Иезекииль Виктор
4
Это больше не работает в iOS 11 - если вы дважды щелкните активную вкладку, по какой-то причине вставки удвоятся.
Бен Готоу
@BenGotow такая же проблема, у вас есть решение?
Диксит Акабари
@DixitAkabari, другие люди уже опубликовали несколько хороших решений для iOS 11
Пранав Касетти
78
// Remove the titles and adjust the inset to account for missing title
for(UITabBarItem * tabBarItem in self.tabBar.items){
    tabBarItem.title = @"";
    tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
}
ddiego
источник
1
Вместо удаления заголовка измените цвет текста на чистый. Заголовок может быть полезен.
Эдуардо Мауро
1
Кодос Эдуардо! Я понял, что хорошим вариантом также является установка вертикального UIOffset для заголовка элементаPositionAjustement
Julius,
2
Где вы поместите это в свой собственный контроллер TabBar?
UKDataGeek
69

Вот как это сделать в раскадровке.

Очистите текст заголовка и установите вставку изображения, как на скриншоте ниже.

введите описание изображения здесь

Помните, что размер значка должен соответствовать руководству по дизайну Apple.

введите описание изображения здесь

Это означает, что у вас должно быть 25 пикселей x 25 пикселей для @ 1x, 50 пикселей x 50 пикселей для @ 2x, 75 пикселей x 75 пикселей для @ 3x

Nuynait
источник
47

Использование подхода с установкой каждого свойства UITabBarItems и update не будет работать должным образом, если установлен контроллер представления. Например, если UITabBarController встроен в, и вам нужно, чтобы заголовок отображался на панели навигации. В этом случае установить заголовок напрямую , а не .title""imageInsetsself.titleself.viewControllersUINavigationControllerUINavigationItemself.navigationItem.titleself.title

Стефан
источник
2
Это кажется более чистым методом. +1 @Oleg это следует отметить как ответ.
akseli
29

Быстрая версия ответа ddiego

Совместим с iOS 11

Вызовите эту функцию в viewDidLoad каждого первого дочернего элемента viewController после установки заголовка viewController

Лучшая практика:

В качестве альтернативы, как @daspianist предложил в комментариях

Создайте подкласс такого же класса BaseTabBarController: UITabBarController, UITabBarControllerDelegate и поместите эту функцию в viewDidLoad подкласса

func removeTabbarItemsText() {

    var offset: CGFloat = 6.0

    if #available(iOS 11.0, *), traitCollection.horizontalSizeClass == .regular {
        offset = 0.0
    }

    if let items = tabBar.items {
        for item in items {
            item.title = ""
            item.imageInsets = UIEdgeInsets(top: offset, left: 0, bottom: -offset, right: 0)
        }
    }
}
korgx9
источник
2
Отличная функция! Вы также можете создать подобный подкласс class BaseTabBarController: UITabBarController, UITabBarControllerDelegateи поместить эту функцию в подклассviewDidLoad
daspianist
26

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

for tabBarItem in tabBar.items!
{
   tabBarItem.title = ""
   tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
}
Маркос Ребукас
источник
Стоит отметить, что если вы не установите одновременно верхнюю и нижнюю вставки, изображение будет искажено.
Юлий
16

iOS 11 вносит излом во многие из этих решений, поэтому я просто исправил свои проблемы в iOS 11, создав подкласс UITabBar и переопределив layoutSubviews.

class MainTabBar: UITabBar {

    override func layoutSubviews() {
        super.layoutSubviews()

        // iOS 11: puts the titles to the right of image for horizontal size class regular. Only want offset when compact.
        // iOS 9 & 10: always puts titles under the image. Always want offset.
        var verticalOffset: CGFloat = 6.0

        if #available(iOS 11.0, *), traitCollection.horizontalSizeClass == .regular {
            verticalOffset = 0.0
        }

        let imageInset = UIEdgeInsets(
            top: verticalOffset,
            left: 0.0,
            bottom: -verticalOffset,
            right: 0.0
        )

        for tabBarItem in items ?? [] {
            tabBarItem.title = ""
            tabBarItem.imageInsets = imageInset
        }
    }
}
atlwx
источник
это единственное, что у меня сработало, но мне пришлось поместить код в 'override func viewDidLayoutSubviews' подкласса MyTabBarController. Я создал подкласс tabBarController и назвал его так
Lance
Решение сработало для меня, хорошо. Я использовал его как расширение, чтобы его было проще добавить
Michal Gumny
@LanceSamaria, это сработало, и мне не нужно было касаться кода контроллера вкладки
Пранав Касетти
12

Я использовал следующий код в viewDidLoad моего BaseTabBarController. Обратите внимание, что в моем примере у меня 5 вкладок, и выбранное изображение всегда будет base_image + "_selected".

// Get tab bar and set base styles
let tabBar = self.tabBar;
tabBar.backgroundColor = UIColor.whiteColor()

// Without this, images can extend off top of tab bar
tabBar.clipsToBounds = true

// For each tab item..
let tabBarItems = tabBar.items?.count ?? 0
for i in 0 ..< tabBarItems {
    let tabBarItem = tabBar.items?[i] as UITabBarItem

    // Adjust tab images (Like mstysf says, these values will vary)
    tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -6, 0);

    // Let's find and set the icon's default and selected states
    // (use your own image names here)
    var imageName = ""
    switch (i) {
    case 0: imageName = "tab_item_feature_1"
    case 1: imageName = "tab_item_feature_2"
    case 2: imageName = "tab_item_feature_3"
    case 3: imageName = "tab_item_feature_4"
    case 4: imageName = "tab_item_feature_5"
    default: break
    }
    tabBarItem.image = UIImage(named:imageName)!.imageWithRenderingMode(.AlwaysOriginal)
    tabBarItem.selectedImage = UIImage(named:imageName + "_selected")!.imageWithRenderingMode(.AlwaysOriginal)
}
Четыре
источник
1
Вместо использования for var i = 0; i < tabBar... вы могли бы просто сказать; for tabBarItems in tabBar.items!
Джесси Онолемен
10

Swift 4 подход

Мне удалось проделать трюк, реализовав функцию, которая принимает TabBarItem и выполняет для него некоторое форматирование.

Сдвигает изображение немного вниз, чтобы сделать его более центрированным, а также скрывает текст панели вкладок. Работает лучше, чем просто установка его заголовка на пустую строку, потому что, когда у вас также есть NavigationBar, TabBar восстанавливает заголовок viewController при выборе

func formatTabBarItem(tabBarItem: UITabBarItem){
    tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
    tabBarItem.setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.clear], for: .selected)
    tabBarItem.setTitleTextAttributes([NSAttributedStringKey.foregroundColor:UIColor.clear], for: .normal)
}

Последний синтаксис

extension UITabBarItem {
    func setImageOnly(){
        imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
        setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.clear], for: .selected)
        setTitleTextAttributes([NSAttributedString.Key.foregroundColor:UIColor.clear], for: .normal)
    }
 }

И просто используйте его в tabBar как:

tabBarItem.setImageOnly()
Хосе Тапизвент
источник
6

Вот лучший и более надежный способ сделать это, кроме основного ответа:

[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor clearColor]}
                                         forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor clearColor]}
                                         forState:UIControlStateHighlighted];

Поместите это в свой, AppDelegate.didFinishLaunchingWithOptionsчтобы он влиял на все кнопки панели вкладок на протяжении всего жизненного цикла вашего приложения.

Иезекииль Виктор
источник
3
Это только скрывает заголовок и не регулирует положение изображения.
mustafa
2
Да, но в вопросе ничего не говорилось о настройке изображения. Просто скрываю текст. И хорошо скрывать текст в ущерб удалению заголовка из контроллера представления кажется неправильным. Особенно, если вы можете использовать этот заголовок, чтобы показать его как часть вашего
контроллера
6

Минимальное безопасное расширение UITabBarController в Swift (на основе ответа @ korgx9):

extension UITabBarController {
  func removeTabbarItemsText() {
    tabBar.items?.forEach {
      $0.title = ""
      $0.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
    }
  }
}
Федерико Занетелло
источник
2

Основываясь на ответе ddiego в Swift 4.2 :

extension UITabBarController {
    func cleanTitles() {
        guard let items = self.tabBar.items else {
            return
        }
        for item in items {
            item.title = ""
            item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
        }
    }
}

И вам просто нужно вызвать self.tabBarController?.cleanTitles()свой контроллер представления.

j_gonfer
источник
1

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

extension UITabBarItem {

    func setTitleColorFor(normalState: UIColor, selectedState: UIColor) {
        self.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: normalState], for: .normal)
        self.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: selectedState], for: .selected)
    }

}


extension UITabBarController {

    func hideItemsTitle() {

        guard let items = self.tabBar.items else {
            return
        }

        for item in items {
            item.setTitleColorFor(normalState: UIColor(white: 0, alpha: 0), selectedState: UIColor(white: 0, alpha: 0))
            item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
        }

    }

    func showItemsTitle() {

        guard let items = self.tabBar.items else {
            return
        }

        for item in items {
            item.setTitleColorFor(normalState: .black, selectedState: .yellow)
            item.imageInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        }

    }

}
Ladislas
источник
0

введите описание изображения здесь

код:

private func removeText() {
    if let items = yourTabBarVC?.tabBar.items {
       for item in items {
          item.title = ""
       }
    }
 }
Giang
источник
0

Самый простой способ и всегда работает:

class TabBar: UITabBar {

    override func layoutSubviews() {
        super.layoutSubviews()

        subviews.forEach { subview in
            if subview is UIControl {
                subview.subviews.forEach {
                    if $0 is UILabel {
                        $0.isHidden = true
                        subview.frame.origin.y = $0.frame.height / 2.0
                    }
                }
            }
        }
    }
}
JulianKro
источник
0

В моем случае тот же ViewController использовался в TabBar и другом потоке навигации. Внутри моего ViewController я установил, self.title = "Some Title"что отображалось в TabBar независимо от установки заголовка nilили пустого поля при добавлении его в панель вкладок. Я также установил imageInsetsследующее:

item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)

Итак, внутри моего ViewController я обработал заголовок навигации следующим образом:

if isFromTabBar {
   // Title for NavigationBar when ViewController is added in TabBar
   // NOTE: Do not set self.title = "Some Title" here as it will set title of tabBarItem
   self.navigationItem.title = "Some Title"
} else {
   // Title for NavigationBar when ViewController is opened from navigation flow
   self.title = "Some Title"
}
Чинтан Шах
источник
0

создайте подкласс UITabBarController и назначьте его своему tabBar, затем в методе viewDidLoad поместите эту строку кода:

tabBar.items?.forEach({ (item) in
        item.imageInsets = UIEdgeInsets.init(top: 8, left: 0, bottom: -8, right: 0)
    })
Soheil Pakgohar
источник
0

Пользовательская панель вкладок - iOS 13, Swift 5, XCode 11

  • Элементы TabBar без текста
  • Элементы TabBar, центрированные по вертикали
  • Закругленный вид TabBar
  • TabBar Динамическое положение и рамки

Раскадровка на основе. Этого можно легко достичь и программно. Всего 4 шага, которым нужно следовать:

  1. Значки панели вкладок должны быть трех размеров черного цвета. Обычно качаю с fa2png.io - размеры: 25x25, 50x50, 75x75. Файлы изображений PDF не работают!

    введите описание изображения здесь

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

введите описание изображения здесь

  1. Пользовательский TabBarController -> Новый файл -> Тип: UITabBarController -> Установить на раскадровке. (см. скриншот)

введите описание изображения здесь

  1. UITabBarController класс

    class RoundedTabBarViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
        // Custom tab bar view
        customizeTabBarView()
    }
    
    private func customizeTabBarView() {
        let tabBarHeight = tabBar.frame.size.height
        self.tabBar.layer.masksToBounds = true
        self.tabBar.isTranslucent = true
        self.tabBar.barStyle = .default
        self.tabBar.layer.cornerRadius = tabBarHeight/2
        self.tabBar.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let viewWidth = self.view.bounds.width
        let leadingTrailingSpace = viewWidth * 0.05
    
        tabBar.frame = CGRect(x: leadingTrailingSpace, y: 200, width: viewWidth - (2 * leadingTrailingSpace), height: 49)
    }
    

    }

  2. Результат введите описание изображения здесь

Doci
источник
0

Если вы хотите центрировать вкладки / изменить вставки изображений без использования магических чисел, у меня сработало следующее (в Swift 5.2.2):

В подклассе UITabBarController вы можете добавить вставки изображений после установки контроллеров представления.

override var viewControllers: [UIViewController]? {
    didSet {
      addImageInsets()
    }
}

func addImageInsets() {
    let tabBarHeight = tabBar.frame.height

    for item in tabBar.items ?? [] where item.image != nil {
      let imageHeight = item.image?.size.height ?? 0
      let inset = CGFloat(Int((tabBarHeight - imageHeight) / 4))
      item.imageInsets = UIEdgeInsets(top: inset,
                                      left: 0,
                                      bottom: -inset,
                                      right: 0)
    }
}

В некоторых из приведенных выше вариантов перечислены решения, позволяющие скрыть текст.

Campbell_Souped
источник