Remover texto do item da barra de guias, mostrar apenas imagem

89

Uma pergunta simples, como posso remover o texto do item da barra de guias e mostrar apenas a imagem?

Quero que os itens da barra gostem no aplicativo Instagram:

insira a descrição da imagem aqui

No inspetor no xcode 6, removo o título e escolho uma imagem @ 2x (50px) e @ 3x (75px). No entanto, a imagem não usa o espaço livre do texto removido. Alguma ideia de como obter a mesma imagem de item da barra de guias como no aplicativo instagram?

Voto positivo
fonte
1
usando ""para o título, talvez?
holex de
1
Definir offsets é apenas um truque, a resposta correta está um pouco abaixo. Você deve usar navigationItem.title = "algum título"
Davit Siradeghyan

Respostas:

129

Você deve jogar com imageInsetspropriedade de UITabBarItem. Aqui está o código de amostra:

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

Os valores internos UIEdgeInsetsdependem do tamanho da imagem. Aqui está o resultado desse código em meu aplicativo:

insira a descrição da imagem aqui

mustafa
fonte
25
Você também pode ajustar as inserções de imagem no inspetor.
voto positivo
Números mágicos são uma má ideia. Por favor, veja minha resposta para uma maneira universalmente compatível de realizar a mesma coisa.
Ezekiel Victor
4
Isso não funciona mais no iOS 11 - se você clicar duas vezes na guia ativa, as inserções dobrarão por algum motivo.
Ben Gotow
@BenGotow mesmo problema você tem alguma solução?
Dixit Akabari
@DixitAkabari outras pessoas já postaram algumas boas soluções para iOS 11
Pranav Kasetti
77
// 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
fonte
1
Em vez de remover o título, altere a cor do texto para limpar. O título pode ser útil.
Eduardo Mauro
1
Kodos para Eduardo! Me fez perceber que uma boa opção também é definir um UIOffset vertical no título do itemPositionAjustement
Julius
2
Onde você coloca isso em seu controlador TabBar personalizado?
UKDataGeek
69

Aqui está como você faz isso em um storyboard.

Limpe o texto do título e defina a inserção da imagem como a imagem abaixo

insira a descrição da imagem aqui

Lembre-se de que o tamanho do ícone deve seguir as diretrizes de design da apple

insira a descrição da imagem aqui

Isso significa que você deve ter 25px x 25px para @ 1x, 50px x 50px para @ 2x, 75px x 75px para @ 3x

Nuynait
fonte
45

Usar a abordagem com a definição de cada propriedade UITabBarItems titlepara "" e atualização imageInsetsnão funcionará corretamente se o controlador de visualização self.titleestiver definido. Por exemplo, se self.viewControllersUITabBarController estiverem incorporados UINavigationControllere você precisar que o título seja exibido na barra de navegação. Neste caso, defina UINavigationItemo título diretamente usando self.navigationItem.title, não self.title.

Stefan
fonte
2
Este parece ser um método mais limpo. +1 @Oleg isso deve ser marcado como a resposta.
akseli de
29

Versão rápida da resposta ddiego

Compatível com iOS 11

Chame esta função em viewDidLoad de cada primeiro filho dos viewControllers após definir o título do viewController

Melhor prática:

Alternativamente como @daspianist sugerido nos comentários

Faça uma subclasse como esta classe BaseTabBarController: UITabBarController, UITabBarControllerDelegate e coloque esta função no viewDidLoad da subclasse

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
fonte
2
Excelente função! Você poderia, alternativamente, fazer uma subclasse de assim class BaseTabBarController: UITabBarController, UITabBarControllerDelegatee colocar essa função na subclasseviewDidLoad
daspianista de
26

Se você estiver usando storyboards, esta seria sua melhor opção. Ele percorre todos os itens da barra de guias e para cada um deles define o título como nada e torna a imagem em tela inteira. (Você deve ter adicionado uma imagem no storyboard)

for tabBarItem in tabBar.items!
{
   tabBarItem.title = ""
   tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
}
Marcos Reboucas
fonte
É bom notar que, se você não definir as inserções superior e inferior, a imagem ficará distorcida.
Julius
16

O iOS 11 atrapalha muitas dessas soluções, então resolvi apenas meus problemas no iOS 11 criando uma subclasse de UITabBar e substituindo 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
fonte
esta é a única coisa que funcionou para mim, mas eu tive que colocar o código dentro de 'override func viewDidLayoutSubviews' da subclasse de MyTabBarController. Criei uma subclasse de tabBarController e chamei-o assim
Lance Samaria,
A solução funcionou bem para mim. Usei-o como extensão, então é mais simples de adicionar
Michal Gumny
@LanceSamaria isso funcionou sem que eu precisasse tocar na guia do código do controlador de barras
Pranav Kasetti
12

Usei o seguinte código no viewDidLoad do meu BaseTabBarController. Observe que no meu exemplo, eu tenho 5 guias, e a imagem selecionada sempre será 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)
}
Quatro
fonte
1
Em vez de usar for var i = 0; i < tabBar... , você poderia apenas ter dito; for tabBarItems in tabBar.items!
Jesse Onolemen de
10

Abordagem Swift 4

Consegui fazer o truque implementando uma função que pega um TabBarItem e faz alguma formatação nele.

Move a imagem um pouco para baixo para torná-la mais centralizada e também oculta o texto da Barra de guias. Funcionou melhor do que apenas definir seu título como uma string vazia, porque quando você tem uma NavigationBar também, a TabBar recupera o título do viewController quando selecionada

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)
}

Sintaxe mais recente

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)
    }
 }

E basta usá-lo em sua barra de tabulação como:

tabBarItem.setImageOnly()
Jose Tapizquent
fonte
6

Aqui está uma maneira melhor e mais segura de fazer isso, além da resposta principal:

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

Coloque-o em seu AppDelegate.didFinishLaunchingWithOptionspara que afete todos os botões da barra de guias ao longo da vida de seu aplicativo.

Ezekiel Victor
fonte
3
Isso apenas oculta o título e não ajusta a posição da imagem.
mustafa
2
Sim, mas a pergunta não dizia nada sobre como ajustar a imagem. Apenas escondendo o texto. E esconder bem o texto em detrimento de remover o título de um controlador de visualização parece errado. Especialmente quando você poderia usar esse título para mostrá-lo como parte de seu
controle de
6

Uma extensão UITabBarController mínima e segura em Swift (com base na resposta @ korgx9):

extension UITabBarController {
  func removeTabbarItemsText() {
    tabBar.items?.forEach {
      $0.title = ""
      $0.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
    }
  }
}
Federico Zanetello
fonte
2

Com base na resposta do ddiego , no 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)
        }
    }
}

E você só precisa chamar self.tabBarController?.cleanTitles()seu controlador de visualização.

j_gonfer
fonte
1

Com base em todas as ótimas respostas desta página, criei outra solução que também permite que você mostre o título novamente. Em vez de remover o conteúdo do título, apenas altero a cor da fonte para transparente.

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
fonte
0

insira a descrição da imagem aqui

código:

private func removeText() {
    if let items = yourTabBarVC?.tabBar.items {
       for item in items {
          item.title = ""
       }
    }
 }
Giang
fonte
0

Maneira mais fácil e sempre funciona:

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
fonte
0

No meu caso, o mesmo ViewController foi usado no TabBar e outro fluxo de navegação. Dentro do meu ViewController, eu defini o self.title = "Some Title"que estava aparecendo no TabBar independentemente da configuração do título nilou em branco ao adicioná-lo na barra de guias. Eu também defini imageInsetso seguinte:

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

Portanto, dentro do meu ViewController, tratei do título de navegação da seguinte maneira:

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"
}
Chintan Shah
fonte
0

faça uma subclasse de UITabBarController e atribua-a ao seu tabBar, em seguida, no método viewDidLoad coloque esta linha de código:

tabBar.items?.forEach({ (item) in
        item.imageInsets = UIEdgeInsets.init(top: 8, left: 0, bottom: -8, right: 0)
    })
Soheil Pakgohar
fonte
0

TabBar personalizado - iOS 13, Swift 5, XCode 11

  • Itens TabBar sem texto
  • Itens TabBar centralizados verticalmente
  • Vista de TabBar arredondada
  • Posição dinâmica TabBar e frames

Baseado em storyboard. Também pode ser alcançado facilmente de forma programática. Apenas 4 etapas a seguir:

  1. Os ícones da barra de guias devem ter 3 tamanhos, na cor preta. Normalmente, eu faço download em fa2png.io - tamanhos: 25x25, 50x50, 75x75. Os arquivos de imagem PDF não funcionam!

    insira a descrição da imagem aqui

  2. No Storyboard para o item da barra de guias, defina o ícone que deseja usar por meio do Attributes Inspector. (veja a imagem)

insira a descrição da imagem aqui

  1. TabBarController personalizado -> Novo arquivo -> Tipo: UITabBarController -> Definir no storyboard. (veja a imagem)

insira a descrição da imagem aqui

  1. Classe 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. Resultado insira a descrição da imagem aqui

Doci
fonte
0

Se você está olhando para centralizar as guias / alterar as inserções de imagem sem usar números mágicos, o seguinte funcionou para mim (no Swift 5.2.2):

Em uma subclasse UITabBarController , você pode adicionar as inserções de imagem após definir os controladores de visualização.

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)
    }
}

Várias das opções acima listam soluções para lidar com a ocultação do texto.

Campbell_Souped
fonte