Dodanie UILabel do UIToolbar

97

Próbuję dodać etykietę do mojego paska narzędzi. Przycisk działa świetnie, jednak kiedy dodaję obiekt etykiety, zawiesza się. Jakieś pomysły?

UIBarButtonItem *setDateRangeButton = [[UIBarButtonItem alloc] initWithTitle:@"Set date range"
                                                                       style:UIBarButtonItemStyleBordered
                                                                      target:self
                                                                      action:@selector(setDateRangeClicked:)];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 20, 20)];
label.text = @"test";

[toolbar setItems:[NSArray arrayWithObjects:setDateRangeButton,label, nil]];

// Add the toolbar as a subview to the navigation controller.
[self.navigationController.view addSubview:toolbar];

// Reload the table view
[self.tableView reloadData];
user8359
źródło

Odpowiedzi:

128

Spójrz na to

[[UIBarButtonItem alloc] initWithCustomView:yourCustomView];

Zasadniczo każdy element musi być „przyciskiem”, ale można go utworzyć w dowolnym widoku. Oto przykładowy kod. Uwaga, ponieważ inne przyciski zwykle znajdują się na pasku narzędzi, po obu stronach przycisku tytułu znajdują się odstępniki, dzięki czemu pozostaje on wyśrodkowany.

NSMutableArray *items = [[self.toolbar items] mutableCopy];

UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[items addObject:spacer];
[spacer release];

self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0 , 11.0f, self.view.frame.size.width, 21.0f)];
[self.titleLabel setFont:[UIFont fontWithName:@"Helvetica-Bold" size:18]];
[self.titleLabel setBackgroundColor:[UIColor clearColor]];
[self.titleLabel setTextColor:[UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:157.0/255.0 alpha:1.0]];
[self.titleLabel setText:@"Title"];
[self.titleLabel setTextAlignment:NSTextAlignmentCenter];

UIBarButtonItem *spacer2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[items addObject:spacer2];
[spacer2 release];

UIBarButtonItem *title = [[UIBarButtonItem alloc] initWithCustomView:self.titleLabel];
[items addObject:title];
[title release];

[self.toolbar setItems:items animated:YES];
[items release];
Answerbot
źródło
10
Zauważ, że jeśli zdecydujesz się na tę trasę, musisz odpowiednio stylizować swoją etykietę (label.backgroundColor = [UIColor clearColor] itp.). Możesz również zainicjować UIBarButtonItem, który ma być stylizowany na Zwykły, który da ci podobny wygląd
wisequark
Wiem, że to naprawdę stary post, ale mam pytanie dotyczące tej odpowiedzi. Gdy to zrobisz, czy jest jakiś sposób, aby później uzyskać dostęp do titleLabel, aby ją zmienić, czy też jest to niemożliwe, ponieważ wszystko zostało wydane?
Ryan
Ryan, UILabel prawdopodobnie nadal istnieje - to self.titleLabel. Ten przykład wymaga zadeklarowania i zsyntetyzowania właściwości dla UILabel * titleLabel, ale ten kod nie jest wyświetlany. Jeśli masz dostęp do obiektu (prawdopodobnie UIViewController), który uruchamia ten kod, możesz uzyskać dostęp do jego titleLabel. Na przykład, możesz dodać metodę do kontrolera widoku, przekazać nowy tytuł, który chcesz, a następnie wywołać [self.titleLabel setText: newTitle].
Steve Liddle
7
Czy nie chciałbyś, aby drugi odstępnik został dodany po elemencie paska przycisku tytułu?
len
121

Dla tych, którzy używają Interface Builder do zaprojektowania twojego UIToolBar, jest to również możliwe przy użyciu samego Interface Builder.

Aby dodać a UILabeldo a UIToolBar, musisz dodać ogólny UIViewobiekt do swojego UIToolBarw IB, przeciągając nowy UIViewobiekt nad UIToolBar. IBautomatycznie utworzy plik, UIBarButtonItemktóry zostanie zainicjowany Twoim niestandardowym UIView. Następnie dodaj a UILabeldo UIViewi edytuj UILabelgraficznie, aby dopasować preferowany styl. Następnie możesz wizualnie ustawić stałe i / lub zmienne podkładki dystansowe według potrzeb, aby UILabelodpowiednio ustawić .

Musisz również ustawić tło zarówno UILabeli UIViewdo clearColoruzyskać UIToolBarpokazać poprzez prawidłowo pod UILabel.

Matt R
źródło
2
Niezła sztuczka, nie wiedziałem, że możesz to zrobić w Interface Builder. Dziękuję Ci bardzo.
Rafael Bugajewski
Czy istnieje sposób na dodanie UIButton z niestandardowym obrazem przy użyciu tej metody? Mogę dodać UIButton, ale obraz się nie pojawia.
cannyboy
4
Nie wydaje mi się, żeby to działało. Kiedy przeciągam UIView na pasek narzędzi, kończy się umieszczenie go wewnątrz kontrolera widoku, a nie na pasku narzędzi. Czy robimy to również w kontrolerze nawigacji czy w kontrolerze widoku?
guptron
1
To nie wydaje się działać. Gdyby to działało dawno temu, już nie w XCode 6 ...
Frédéric Adda
1
Powinieneś zaktualizować swoją odpowiedź, aby zaznaczyć, że działa to tylko z paskami narzędzi dodanymi do kontrolera widoku ręcznie; nie działa z dodanym paskiem narzędzi.
James Bush
32

Odpowiedź answerBota okazała się bardzo przydatna, ale myślę, że znalazłem jeszcze łatwiejszy sposób w Interface Builder:

  • utwórz UIBarButtonItem i dodaj go do paska narzędzi w programie Interface Builder

wprowadź opis obrazu tutaj

  • Usuń zaznaczenie „włączone” dla tego BarButtonItem

wprowadź opis obrazu tutaj

  • podłącz to BarButtonItem do właściwości w swojej klasie (to jest w języku Swift, ale byłoby bardzo podobne w Obj-C):

    @IBOutlet private weak var lastUpdateButton: UIBarButtonItem! // Dummy barButtonItem whose customView is lastUpdateLabel
  • dodaj kolejną właściwość dla samej etykiety:

    private var lastUpdateLabel = UILabel(frame: CGRectZero)
  • in viewDidLoad, dodaj następujący kod, aby ustawić właściwości etykiety, i dodaj go jako customView swojego BarButtonItem

    // Dummy button containing the date of last update
    lastUpdateLabel.sizeToFit()
    lastUpdateLabel.backgroundColor = UIColor.clearColor()
    lastUpdateLabel.textAlignment = .Center
    lastUpdateButton.customView = lastUpdateLabel
  • Aby zaktualizować UILabeltekst:

    lastUpdateLabel.text = "Updated: 9/12/14, 2:53"
    lastUpdateLabel.sizeToFit() 

Wynik:

wprowadź opis obrazu tutaj

Musisz dzwonić za lastUpdateLabel.sizetoFit()każdym razem, gdy aktualizujesz tekst etykiety

Frederic Adda
źródło
1
I stworzył UIBarButtonItem samo jak ty, lewy włączona, a nałożony etykietę za pomocą następującego kodu: UILabel* label = [[UILabel alloc] init]; label.text = @"Hello"; label.font = [UIFont systemFontOfSize:16]; [label sizeToFit]; self.barItem.customView = label;
Brett Donald
6

Jedną z rzeczy, do których używam tej sztuczki, jest utworzenie instancji UIActivityIndicatorViewna wierzchu UIToolBar, coś, co w przeciwnym razie nie byłoby możliwe. Na przykład tutaj mam a UIToolBarz 2 UIBarButtonItem, a FlexibleSpaceBarButtonItem, a następnie inny UIBarButtonItem. Chcę wstawić UIActivityIndicatorViewliterę UIToolBarpomiędzy elastyczną przestrzenią a ostatnim (prawym) przyciskiem. Więc w moim RootViewControllerrobię co następuje,

- (void)viewDidLoad {
[super viewDidLoad];// Add an invisible UIActivityViewIndicator to the toolbar
UIToolbar *toolbar = (UIToolbar *)[self.view viewWithTag:767];
NSArray *items = [toolbar items];

activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 20.0f, 20.0f)];
[activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];    

NSArray *newItems = [NSArray arrayWithObjects:[items objectAtIndex:0],[items objectAtIndex:1],[items objectAtIndex:2],
                     [[UIBarButtonItem alloc] initWithCustomView:activityIndicator], [items objectAtIndex:3],nil];
[toolbar setItems:newItems];}
Alasdair Allan
źródło
Ten kod przecieka pamięć przydzieloną dla UIBarButtonItem z widokiem wskaźnika aktywności niestandardowej. (Wycieka również pamięć wskaźnika aktywności, ale zakładam, że jest on uwalniany poniżej końca fragmentu kodu.
erikprice
3

Detale

  • Xcode 10.2.1 (10E1001), Swift 5

Pełna próbka

import UIKit

class ViewController: UIViewController {

    private weak var toolBar: UIToolbar?

    override func viewDidLoad() {
        super.viewDidLoad()

        var bounds =  UIScreen.main.bounds
        let bottomBarWithHeight = CGFloat(44)
        bounds.origin.y = bounds.height - bottomBarWithHeight
        bounds.size.height = bottomBarWithHeight
        let toolBar = UIToolbar(frame: bounds)
        view.addSubview(toolBar)

        var buttons = [UIBarButtonItem]()
        buttons.append(UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(ViewController.action)))
        buttons.append(UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(ViewController.action)))
        buttons.append(UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil))
        buttons.append(UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil))
        buttons.append(ToolBarTitleItem(text: "\(NSDate())", font: .systemFont(ofSize: 12), color: .lightGray))
        buttons.append(UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil))
        buttons.append(UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action:  #selector(ViewController.action)))
        toolBar.items = buttons

        self.toolBar = toolBar
    }
    @objc func action() { print("action") }
}

class ToolBarTitleItem: UIBarButtonItem {

    init(text: String, font: UIFont, color: UIColor) {
        let label =  UILabel(frame: UIScreen.main.bounds)
        label.text = text
        label.sizeToFit()
        label.font = font
        label.textColor = color
        label.textAlignment = .center
        super.init()
        customView = label
    }
    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
}

Wynik

wprowadź opis obrazu tutaj

Wasilij Bodnarczuk
źródło
Podoba mi się to, ale co jeśli mam TableView, to przewinie się z tym paskiem. Jak to naprawić?
Maksim Kniazev
Witaj Maxim, nie rozumiem twojego problemu. Opisz wynik, jaki chcesz uzyskać.
Wasilij Bodnarchuk
Ok, używam UITableViewController i jeśli ustawię view.addSubview (toolBar!) I przewinie mój tableview pasek będzie przewijał się za pomocą tableView, chcę, aby miał stałą dolną pozycję
Maksim Kniazev
Myślę, że powinieneś użyć UIViewController z UITableView (zamiast UITableViewController) jako podwidoku.
Wasilij Bodnarchuk
Ok spasibo. Spróbuję tego
Maksim Kniazev
2

Podobnie jak Matt RI używał konstruktora interfejsu. Ale UIWebViewzamiast tego chciałem mieć 1 w środku, aby móc pogrubić niektóre teksty, a inne nie (jak w aplikacji pocztowej). Więc

  1. Zamiast tego dodaj widok internetowy.
  2. Odznacz nieprzezroczyste
  3. Upewnij się, że tło ma wyraźny kolor
  4. Połącz wszystko z IBOutlet
  5. Użyj poniższego, htmlaby uzyskać przezroczyste tło, dzięki czemu pasek narzędzi prześwituje

Kod:

NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSString *html = [NSString stringWithFormat:@"<html><head><style>body{font-size:11px;text-align:center;background-color:transparent;color:#fff;font-family:helvetica;vertical-align:middle;</style> </head><body><b>Updated</b> 10/11/12 <b>11:09</b> AM</body></html>"];
[myWebView loadHTMLString:html baseURL:baseURL];
Todd Horst
źródło
1

Jeśli chcesz dodać widok do widoku paska narzędzi, możesz spróbować tego:

[self.navigationController.tabBarController.view addSubview:yourView];
mrhevor
źródło
1

Spróbuj tego:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(140 , 0, 50, 250)];
[label setBackgroundColor:[UIColor clearColor]];
label.text = @"TEXT";
UIView *view = (UIView *) label;
[self.barItem setCustomView:view];

Uwaga: self.barItemjest UIBarButtonItemdodawana z biblioteki obiektów i umieszczana między dwoma elastycznymi przestrzeniami.

innym sposobem jest usunięcie [self.barItem setCustom:view]linii i zmiana parametrów label(width) tak, aby wypełniała cały pasek narzędzi i samodzielnie ustawiła wyrównanie do środka i czcionkę w kodzie,

user1938695
źródło