Usuń tekst elementu paska kart, pokaż tylko obraz

90

Proste pytanie, jak mogę usunąć tekst elementu paska kart i wyświetlić tylko obraz?

Chcę, aby elementy paska polubiły w aplikacji Instagram:

wprowadź opis obrazu tutaj

W inspektorze w xcode 6 usuwam tytuł i wybieram obraz @ 2x (50px) i @ 3x (75px). Jednak obraz nie wykorzystuje wolnego miejsca usuniętego tekstu. Jakieś pomysły, jak osiągnąć taki sam obraz elementu paska kart, jak w aplikacji Instagram?

Głosuj za
źródło
1
może używając ""tytułu?
holex
1
Ustawianie offsetów to tylko sztuczka, prawidłowa odpowiedź znajduje się nieco poniżej. Powinieneś użyć navigationItem.title = "jakiś tytuł"
Davit Siradeghyan

Odpowiedzi:

129

Powinieneś bawić się imageInsetswłaściwością UITabBarItem. Oto przykładowy kod:

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

Wartości wewnątrz UIEdgeInsetszależą od rozmiaru obrazu. Oto wynik tego kodu w mojej aplikacji:

wprowadź opis obrazu tutaj

mustafa
źródło
25
W Inspektorze można również dostosować wstawki obrazu.
Głosuj za
Magiczne liczby to zły pomysł. Zapoznaj się z moją odpowiedzią na temat uniwersalnego sposobu osiągnięcia tego samego.
Ezekiel Victor
4
To już nie działa w iOS 11 - jeśli klikniesz dwukrotnie aktywną kartę, z jakiegoś powodu podwoi to wstawki.
Ben Gotow,
@BenGotow ten sam problem, masz jakieś rozwiązanie?
Dixit Akabari
@DixitAkabari inni ludzie opublikowali już kilka dobrych rozwiązań dla iOS 11
Pranav Kasetti
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
źródło
1
Zamiast usuwać tytuł zmień kolor tekstu na wyczyść. Tytuł może być przydatny.
Eduardo Mauro
1
Kodos do Eduardo! Uświadomiłem sobie, że dobrym rozwiązaniem jest również ustawienie pionowego ustawienia UIOffset w tytule pozycjiPozycja Dostosowanie
Julius
2
Gdzie umieścisz to w swoim niestandardowym kontrolerze TabBar?
UKDataGeek
69

Oto, jak to zrobić w scenorysie.

Wyczyść tekst tytułu i ustaw wstawkę obrazu jak na poniższym zrzucie ekranu

wprowadź opis obrazu tutaj

Pamiętaj, że rozmiar ikony powinien być zgodny z wytycznymi dotyczącymi projektowania jabłek

wprowadź opis obrazu tutaj

Oznacza to, że powinieneś mieć 25 pikseli x 25 pikseli dla @ 1x, 50 pikseli x 50 pikseli dla @ 2x, 75 pikseli x 75 pikseli dla @ 3x

nuynait
źródło
45

Użycie podejścia z ustawieniem każdej właściwości UITabBarItems titlena "" i aktualizacji imageInsetsnie będzie działać poprawnie, jeśli w widoku kontroler self.titlejest ustawiony. Na przykład, jeśli self.viewControllersUITabBarController są osadzone UINavigationControlleri chcesz, aby tytuł był wyświetlany na pasku nawigacyjnym. W tym przypadku ustaw UINavigationItemtytuł bezpośrednio, używając self.navigationItem.title, nie self.title.

Stefan
źródło
2
Wydaje się, że jest to o wiele czystsza metoda. +1 @Oleg to powinno być oznaczone jako odpowiedź.
akseli
29

Szybka wersja odpowiedzi ddiego

Zgodny z iOS 11

Wywołaj tę funkcję w viewDidLoad każdego pierwszego dziecka elementu viewControllers po ustawieniu tytułu elementu viewController

Najlepsze praktyki:

Alternatywnie, jak sugerował @daspianist w komentarzach

Utwórz podklasę podobną do tej klasy BaseTabBarController: UITabBarController, UITabBarControllerDelegate i umieść tę funkcję w pliku viewDidLoad podklasy

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
źródło
2
Świetna funkcja! Możesz alternatywnie utworzyć taką podklasę class BaseTabBarController: UITabBarController, UITabBarControllerDelegatei umieścić tę funkcję w podklasieviewDidLoad
daspianist
26

Jeśli używasz scenorysów, będzie to najlepsza opcja. Przechodzi przez wszystkie elementy paska kart i dla każdego ustawia tytuł na zero i wyświetla obraz na pełnym ekranie. (Musisz dodać obraz w serii ujęć)

for tabBarItem in tabBar.items!
{
   tabBarItem.title = ""
   tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)
}
Marcos Reboucas
źródło
Warto zauważyć, że jeśli nie ustawisz zarówno górnych, jak i dolnych wstawek, obraz zostanie wypaczony.
Julius
16

iOS 11 rzuca załamanie w wielu z tych rozwiązań, więc właśnie naprawiłem swoje problemy w iOS 11, podklasując UITabBar i nadpisując 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
źródło
jest to jedyna rzecz, która działała dla mnie, ale musiałem umieścić kod w podklasie MyTabBarController w „override func viewDidLayoutSubviews”. Podklasowałem tabBarController i nazwałem go tak
Lance Samaria
Rozwiązanie działało na mnie, ładnie. Użyłem go jako rozszerzenia, więc łatwiej jest dodać
Michal Gumny
@LanceSamaria to działało bez konieczności dotykania kodu kontrolera paskowego karty
Pranav Kasetti
12

Użyłem następującego kodu w widokuDidLoad mojego BaseTabBarControllera. Zauważ, że w moim przykładzie mam 5 zakładek, a wybrany obraz zawsze będzie 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)
}
Cztery
źródło
1
Zamiast używać for var i = 0; i < tabBar... , mógłbyś po prostu powiedzieć; for tabBarItems in tabBar.items!
Jesse Onolemen
10

Szybkie podejście 4

Udało mi się załatwić sprawę, implementując funkcję, która pobiera TabBarItem i formatuje ją.

Przesuwa obraz nieco w dół, aby był bardziej wyśrodkowany, a także ukrywa tekst paska kart. Działało lepiej niż tylko ustawienie tytułu na pusty ciąg, ponieważ gdy masz również NavigationBar, TabBar odzyskuje tytuł viewController po wybraniu

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

Najnowsza składnia

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

I po prostu użyj go w swoim tabBar jako:

tabBarItem.setImageOnly()
Jose Tapizquent
źródło
6

Oto lepszy, bardziej niezawodny sposób na zrobienie tego, inny niż najlepsza odpowiedź:

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

Umieść to w swoim AppDelegate.didFinishLaunchingWithOptions, aby miało wpływ na wszystkie przyciski paska kart przez cały okres użytkowania aplikacji.

Ezekiel Victor
źródło
3
To tylko ukrywa tytuł i nie dostosowuje pozycji obrazu.
mustafa
2
Tak, ale pytanie nie mówiło nic o dostosowaniu obrazu. Po prostu ukrywam tekst. A dobrze ukrywanie tekstu ze szkodą dla usunięcia tytułu z kontrolera widoku wydaje się niewłaściwe. Zwłaszcza, jeśli możesz użyć tego tytułu, aby pokazać go jako część
kontrolera
6

Minimalne, bezpieczne rozszerzenie UITabBarController w Swift (oparte na odpowiedzi @ korgx9):

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

Na podstawie odpowiedzi ddiego w 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)
        }
    }
}

Wystarczy wywołać self.tabBarController?.cleanTitles()kontroler widoku.

j_gonfer
źródło
1

Opierając się na wszystkich świetnych odpowiedziach na tej stronie, stworzyłem kolejne rozwiązanie, które pozwala również ponownie wyświetlić tytuł. Zamiast usuwać treść tytułu, po prostu zmieniam kolor czcionki na przezroczysty.

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
źródło
0

wprowadź opis obrazu tutaj

kod:

private func removeText() {
    if let items = yourTabBarVC?.tabBar.items {
       for item in items {
          item.title = ""
       }
    }
 }
Giang
źródło
0

Najłatwiejszy sposób i zawsze działa:

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
źródło
0

W moim przypadku ten sam ViewController został użyty w TabBar i innym przepływie nawigacji. W moim ViewController ustawiłem, self.title = "Some Title"który pojawiał się w TabBar niezależnie od ustawienia tytułu nillub pustego podczas dodawania go na pasku kart. Ustawiłem również imageInsets:

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

Więc w moim ViewController, obsłużyłem tytuł nawigacji w następujący sposób:

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
źródło
0

stwórz podklasę UITabBarController i przypisz ją do swojego tabBar, a następnie w metodzie viewDidLoad umieść ten wiersz kodu:

tabBar.items?.forEach({ (item) in
        item.imageInsets = UIEdgeInsets.init(top: 8, left: 0, bottom: -8, right: 0)
    })
soheil pakgohar
źródło
0

Niestandardowy pasek zakładek - iOS 13, Swift 5, XCode 11

  • Elementy TabBar bez tekstu
  • Elementy TabBar wyśrodkowane w pionie
  • Zaokrąglony widok TabBar
  • TabBar Dynamiczne położenie i ramki

Oparte na scenorysie. Można to również łatwo osiągnąć programowo. Tylko 4 kroki do wykonania:

  1. Ikony paska kart muszą mieć 3 rozmiary, w kolorze czarnym. Zwykle pobieram z fa2png.io - rozmiary: 25x25, 50x50, 75x75. Pliki graficzne PDF nie działają!

    wprowadź opis obrazu tutaj

  2. W serii ujęć dla elementu paska kart ustaw ikonę, której chcesz użyć, za pośrednictwem Inspektora atrybutów. (patrz zrzut ekranu)

wprowadź opis obrazu tutaj

  1. Custom TabBarController -> New File -> Type: UITabBarController -> Set on storyboard. (patrz zrzut ekranu)

wprowadź opis obrazu tutaj

  1. UITabBarController, klasa

    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. Wynik wprowadź opis obrazu tutaj

Doci
źródło
0

Jeśli chcesz wyśrodkować zakładki / zmienić wstawki obrazu bez używania magicznych liczb, zadziałało dla mnie (w Swift 5.2.2):

W podklasie UITabBarController można dodać wstawki obrazu po ustawieniu kontrolerów widoku.

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

Kilka z powyższych opcji zawiera listę rozwiązań radzenia sobie z ukrywaniem tekstu.

Campbell_Souped
źródło