Szukaj…


Wprowadzenie

Prosty, szeroko stosowany, ale bardzo wydajny widok, który może prezentować dane w formie listy przy użyciu wierszy i pojedynczej kolumny. Użytkownicy mogą przewijać elementy w widoku tabeli w pionie oraz opcjonalnie manipulować i wybierać zawartość.

Składnia

  • - (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (CGFloat) tableView: (UITableView *) tableView heightForHeaderInSection: sekcja (NSInteger);

  • - (CGFloat) tableView: (UITableView *) tableView heightForFooterInSection: sekcja (NSInteger);

  • - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: sekcja (NSInteger);

  • - (UIView *) tableView: (UITableView *) tableView viewForFooterInSection: sekcja (NSInteger);

  • - (UITableViewCellAccessoryType) tableView: (UITableView *) tableView akcesoriaTypeForRowWithIndexPath: (NSIndexPath *) indexPath

  • - (void) tableView: (UITableView *) tableView accessoriesButtonTappedForRowWithIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView willSelectRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView willDeselectRowAtIndexPath: (NSIndexPath *) indexPath

  • - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView didDeselectRowAtIndexPath: (NSIndexPath *) indexPath

  • - (UITableViewCellEditingStyle) tableView: (UITableView *) tableView editStyleForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSString *) tableView: (UITableView *) tableView titleForDeleteConfirmationButtonForRowAtIndexPath: (NSIndexPath *) indexPath

  • - (BOOL) tableView: (UITableView *) tableView shouldIndentWhileEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView willBeginEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView didEndEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView targetIndexPathForMoveFromRowAtIndexPath: (NSIndexPath *) sourceIndexPath toProposedIndexPath: (NSIndexPath *) proponowaneDestinationIndexPath;

  • - (NSInteger) tableView: (UITableView *) tableView indentationLevelForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: sekcja (NSInteger);

  • - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView;

  • - (NSString *) tableView: (UITableView *) tableView titleForHeaderInSection: sekcja (NSInteger); // naprawiono styl czcionki. użyj widoku niestandardowego (UILabel), jeśli chcesz czegoś innego

  • - (NSString *) tableView: (UITableView *) tableView titleForFooterInSection: sekcja (NSInteger);

  • - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSArray *) sekcjaIndexTitlesForTableView: (UITableView *) tableView;

  • - (NSInteger) tableView: (UITableView *) tableView sectionForSectionIndexTitle: (NSString *) tytuł atIndex: (NSInteger) indeks;

  • - (void) tableView: (UITableView *) tableView commitEditingStyle: (UITableViewCellEditingStyle) editStyle forRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView moveRowAtIndexPath: (NSIndexPath *) sourceIndexPath toIndexPath: (NSIndexPath *) destinationIndexPath;

Uwagi

UITableView jest podklasą UIScrollView . Klasy zgodne z protokołem UITableViewDelegate również zgodne z protokołem UIScrollViewDelegate . UITableView może być przydatny do wyświetlania długich lub nieokreślonych list przez jego komórki, podczas gdy UIScrollView jest lepszy, gdy znany jest rozmiar wyświetlanych widoków.

Komórki samoprzylepne

W iOS 8 Apple wprowadziło komórkę samowyrównującą. Ułóż swoje komórki UITableViewCell za pomocą Autolayout, a UITableView zajmie się resztą za Ciebie. Wysokość wiersza jest obliczana automatycznie, domyślnie wartość rowHeight to UITableViewAutomaticDimension.

Właściwość UITableView estimatedRowHeight jest używana podczas obliczania komórki o samorozmiaru.

Podczas tworzenia komórki z dopasowanym widokiem tabeli należy ustawić tę właściwość i użyć ograniczeń, aby zdefiniować rozmiar komórki.

- Apple, dokumentacja UITableView

self.tableView.estimatedRowHeight = 44.0

Zauważ, że Tableview za delegata za heightForRowAtIndexPath jest konieczne, jeśli chcemy mieć wysokość dynamiczne dla wszystkich komórek. W razie potrzeby po prostu ustaw powyższą właściwość, a następnie ponownie załaduj lub załaduj widok tabeli. Można jednak ustawić wysokość określonych komórek, a inne dynamicznie, za pomocą następującej funkcji:

Szybki

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch indexPath.section {
    case 1:
        return 60
    default:
        return UITableViewAutomaticDimension
    }
}

Cel C

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  switch (indexPath.section) {
      case 1:
        return 60;
      default:
        return UITableViewAutomaticDimension;
    }  
}

Tworzenie UITableView

Widok tabeli to lista wierszy, które można wybrać. Każdy wiersz jest wypełniany ze źródła danych. Ten przykład tworzy prosty widok tabeli, w którym każdy wiersz jest pojedynczą linią tekstu.

Zrzut ekranu z UITableView

Dodaj UITableView do swojej Storyboard

Chociaż istnieje wiele sposobów tworzenia UITableView , jednym z najprostszych jest dodanie jednego do Storyboard. Otwórz Storyboard i przeciągnij UITableView na UIViewController . Pamiętaj, aby użyć automatycznego układu, aby poprawnie wyrównać stół (przypnij wszystkie cztery strony).

Wypełnianie tabeli danymi

Aby dynamicznie wyświetlać zawartość (tj. Ładować ją ze źródła danych, takiego jak tablica, model Core Data, serwer sieciowy itp.) W widoku tabeli, musisz skonfigurować źródło danych.

Tworzenie prostego źródła danych

Jak podano powyżej, źródłem danych może być cokolwiek z danymi. Od Ciebie zależy, jak ją sformatować i co w niej jest. Jedynym wymogiem jest to, że musisz być w stanie odczytać go później, aby w razie potrzeby można było zapełnić każdy wiersz tabeli danymi.

W tym przykładzie po prostu ustawimy tablicę z niektórymi ciągami (tekstem) jako naszym źródłem danych:

Szybki

let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

Cel C

// You'll need to define this variable as a global variable (like an @property) so that you can access it later when needed.
NSArray *myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];

Konfigurowanie źródła danych w kontrolerze widoku

Upewnij się, że kontroler widoku jest zgodny z protokołem UITableViewDataSource .

Szybki

class ViewController: UIViewController, UITableViewDataSource {

Cel C

@interface ViewController : UIViewController <UITableViewDataSource>

Tak szybko, jak kontroler widok ogłosił będzie to zgodne z UITableViewDataSource (to co mamy tylko zrobić powyżej), które są wymagane do realizacji co najmniej jednej z następujących metod w klasie widok kontrolera:

  • tableView:numberOfRowsInSection , pyta o to, ile wierszy powinien mieć widok tabeli.

    // Swift    
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return self.myDataArray.count
    }
    
  • tableView:cellForRowAtIndexPath , żądania utworzenia i zwrócenia komórki dla każdego wiersza określonego w tableView:numberOfRowsInSection . Tak więc, jeśli powiedziałeś, że potrzebujesz 10 wierszy, ta metoda będzie wywoływana dziesięć razy dla każdego wiersza i musisz utworzyć komórkę dla każdego z tych wierszy.

    // Swift    
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         // Create a new cell here. The cellReuseIdentifier needs to match the reuse identifier from the cell in your Storyboard
         let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!
    
         // Set the label on your cell to the text from your data array
         cell.textLabel?.text = self.myDataArray[indexPath.row]
         
         return cell
     }
    

OSTRZEŻENIE : NIE możesz zwrócić zero dla żadnych komórek w cellForRowAtIndexPath: Spowoduje to awarię aplikacji i zobaczysz następujący błąd w konsoli:

Uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

Podłączanie źródła danych widoku tabeli do kontrolera widoku

Możesz to zrobić za pomocą kodu, ustawiając właściwość dataSource tabeli na self na kontrolerze widoku. Lub możesz wybrać widok tabeli w serii ujęć, otworzyć Inspektora atrybutów, wybrać panel „ dataSource ” i przeciągnąć z dataSource do kontrolera widoku ( UWAGA : upewnij się, że łączysz się z UIViewCONTROLLER, a nie UIView lub innym obiektem w twoim UIViewController).

Obsługa wyboru wierszy

Gdy użytkownik stuknie w wiersz w widoku tabeli, na ogół będziesz chciał coś zrobić - odpowiedzieć. W wielu aplikacjach po dotknięciu wiersza wyświetlane są dodatkowe informacje na temat wybranego elementu. Pomyśl o aplikacji Wiadomości: po dotknięciu wiersza zawierającego jeden z kontaktów rozmowa z tą osobą jest następnie wyświetlana na ekranie.

Aby to zrobić, musisz być zgodny z protokołem UITableViewDelegate . Takie postępowanie jest podobne do zgodnego z protokołem źródła danych. Tym razem jednak po prostu dodasz go do UITableViewDataSource i oddzielisz przecinkiem. Powinno więc wyglądać tak:

Szybki

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

Cel C

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

Nie ma żadnych wymaganych metod do wdrożenia dla delegata widoku tabeli. Aby jednak obsłużyć zaznaczenia wierszy, musisz użyć następującej metody:

  • tableView:didSelectRowAtIndexPath , jest to wywoływane za każdym razem, gdy zostanie naciśnięty wiersz, co pozwala zrobić coś w odpowiedzi. W naszym przykładzie po prostu wydrukujemy potwierdzenie w dzienniku Xcode.

    // Swift    
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
         print("You tapped cell number \(indexPath.row).")
     }
    
    // Objective-C    
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
         NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
    }
    

Ostateczne rozwiązanie

Zobacz poniżej pełną konfigurację z samym kodem, bez wyjaśnienia.

Szybki

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // Data model: These strings will be the data for the table view cells
    let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

    // cell reuse id (cells that scroll out of view can be reused) 
    let cellReuseIdentifier = "cell"

    // don't forget to hook this up from the storyboard
    @IBOutlet var myTableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Register the table view cell class and its reuse id
        myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)

        // This view controller itself will provide the delegate methods and row data for the table view.
        myTableView.delegate = self
        myTableView.dataSource = self
    }
    
    // number of rows in table view
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.myDataArray.count
    }
    
    // create a cell for each table view row
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        // create a new cell if needed or reuse an old one
        let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!

        // set the text from the data model
        cell.textLabel?.text = self.myDataArray[indexPath.row]
        
        return cell
    }
    
    // method to run when table view cell is tapped
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
}

Cel C

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> {
    IBOutlet UITableView *myTableView;
    NSArray *myDataArray;
}

@end

ViewController.m

#import "ViewController.h"

// cell reuse id (cells that scroll out of view can be reused)
NSString * _Nonnull cellReuseIdentifier = @"cell";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Data model: These strings will be the data for the table view cells
    myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];
    
    // Register the table view cell class and its reuse id
    [myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellReuseIdentifier];
    
    // This view controller itself will provide the delegate methods and row data for the table view.
    myTableView.delegate = self;
    myTableView.dataSource = self;
}

// number of rows in table view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return myDataArray.count;
}

// create a cell for each table view row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // create a new cell if needed or reuse an old one
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
        
    // set the text from the data model
    cell.textLabel.text = myDataArray[indexPath.row];
    
    return cell;
}
    
// method to run when table view cell is tapped
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
}

@end

Deleguj i źródło danych

UITableViewDelegate służy do kontrolowania sposobu wyświetlania tabeli, a UITableViewDataSource służy do definiowania danych UITableView . Istnieją dwie wymagane metody i wiele opcjonalnych, których można użyć do dostosowania rozmiaru, sekcji, nagłówków i komórek w UITableView .


UITableViewDataSource

Wymagane metody

numberOfRowsInSection: Ta metoda określa liczbę komórek, które będą wyświetlane w każdej sekcji widoku tabeli.

Cel C

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows for the table view. Usually populated from an array,
    // or can be statically defined.
    return self.myArray.count;
}

Szybki 3

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of rows for the table view. Usually populated from an array, 
    // or can be statically defined.
    return self.myArray.count
}

cellForRowAtIndexPath: tej metodzie tworzone są i konfigurowane komórki UITableView . Powinny zwrócić UITableViewCell lub niestandardową podklasę.

Uwaga: Korzystanie z dequeueReusableCellWithIdentifier:forIndexPath: wymaga, aby klasa lub stalówka została zarejestrowana dla tego identyfikatora za pomocą registerClass:forCellReuseIdentifier: UITableView registerClass:forCellReuseIdentifier: lub registerNib:forCellReuseIdentifier: metody. Zazwyczaj będzie to miało miejsce w UIViewController „s viewDidLoad metody.

Cel C

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCustomCell" 
                                                         forIndexPath:indexPath];
    
    // All additional customization goes here
    cell.titleLabel.text = [NSString stringWithFormat:@"Title Row %lu", indexPath.row];

    return cell;
}

Szybki 3

func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("MyCustomCell", forIndexPath:indexPath)
    
    // All additional customization goes here
    cell.titleLabel.text = String(format:"Title Row %lu", indexPath.row)
    
    return cell
}
Metody opcjonalne

titleForHeaderInSection: Definiuje ciąg znaków jako tytuł każdego nagłówka sekcji w widoku tabeli. Ta metoda pozwala jedynie na zmianę tytułu, dalszą personalizację można wykonać, definiując widok nagłówka.

Cel C

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    switch(section) {
        case 0:
            return @"Title 1";
            break;

        case 1:
            return @"Title 2";
            break;

        default:
            return nil;
            break;
    }
}

Szybki 3

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch section {
        case 0:
            return "Title 1"
        case 1:
            return "Title 2"
        default:
            return nil
    }
}

titleForFooterInSection: Definiuje ciąg znaków jako tytuł każdego nagłówka sekcji w widoku tabeli.

Cel C

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    return @"Footer text";
}

Szybki 3

func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
    return "Footer text"
}

canEditRowAtIndexPath: Służy do określenia, czy interfejs użytkownika edycji powinien być wyświetlany dla określonego wiersza. Powinien zwrócić YES jeśli określony wiersz można usunąć lub dodać.

Cel C

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

Szybki 3

func tableView(_ tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

commitEditingStyle:forRowAtIndexPath Powinien wykonać pracę wymaganą do obsługi dodania lub usunięcia określonego wiersza. Na przykład usuń komórkę z UITableView z animacją i usuń powiązany obiekt z modelu danych tabeli.

Cel C

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    switch (editingStyle) {
        case UITableViewCellEditingStyleInsert:
            // Insert new data into the backing data model here
            [self insertNewDataIntoDataModel];
            [tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case UITableViewCellEditingStyleDelete:
            [self removeDataFromDataModelAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        default:
            // Nothing to perform if the editingStyle was neither Insert or Delete
            break;

    }
}

Szybki 3

func tableView(_ tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    switch editingStyle {
        case .Insert:
            self.insertNewDataIntoDataModel()
            tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
        case .Delete:
            self.removeDataFromDataModelAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
        default:
            // Nothing to perform if the editingStyle was neither Insert or Delete
    }
}

editActions:forRowAt Umożliwia dodawanie dodatkowych akcji lub przycisków do trybu edycji wiersza w UITableview . Na przykład, jeśli chcesz dwa przyciski, przycisk edycji i usuwania, gdy użytkownik przesuwa palcem, aby edytować wiersz, wówczas skorzystasz z tej metody.

Szybki 3

override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    // In the handler you will get passed the action as well as the indexPath for 
    // the row that is being edited 
    let editAction = UITableViewRowAction(style: .normal, title: "Edit", handler: { [unowned self] action, indexPath in
        // Do something when edit is tapped
    })
    
    // Change the color of the edit action
    editAction.backgroundColor = UIColor.blue
        
    let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete", handler: { [unowned self] action, indexPath in
        // Handel the delete event
    })
        
        
    return [deleteAction, editAction]
}

UITableViewDelegate

Wszystkie metody w UITableViewDelegate są opcjonalne, ale delegat, który je implementuje, umożliwi dodatkowe funkcje dla UITableView .

numberOfSectionsInTableView: Domyślnie zwraca 1, ale obsługa wielu sekcji jest włączona przez zwrócenie innej liczby sekcji.

Cel C

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.numSections;
}

Szybki 3

func numberOfSectionsInTableView(_ tableView: UITableView) -> Int {
    return self.numSections
}

viewForHeaderInSection Umożliwia konfigurację widoku niestandardowego jako nagłówka sekcji.

Cel C

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(tableView.frame), 22)];
    view.backgroundColor = [UIColor groupTableViewBackgroundColor];
    
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:12];
    label.textColor = [UIColor darkGrayColor];
    
    switch (section) {
        case 1: {
            label.text = @"Title";
            label.frame = labelFrame;
            
            UIButton *more = [[UIButton alloc] initWithFrame:btnFrame];
            [more setTitle:@"See more" forState:UIControlStateNormal];
            [more.titleLabel setFont:[UIFont systemFontOfSize:12]];
            [view addSubview:more];
        }   break;
            
        default:
            label.frame = CGRectMake(0, 0, 0, 0);
            break;
    }
    
    [view addSubview:label];
    return view;
}

Szybki 3

func tableView(_ tableView: UITableView,  viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 22))
    view.backgroundColor = UIColor.groupTableViewBackgroundColor()
    
    let label = UILabel()
    label.font = UIFont.systemFontOfSize(12)
    label.textColor = UIColor.darkGrayColor()
    
    switch section {
        case 1:
            label.text = "Title"
            label.frame = labelFrame
            
            let more = UIButton(frame: btnFrame)
            more.setTitle("See more", forState:.Normal)
            view.addSubview(more)
            
        default:
            label.frame = CGRect.zero
    }
    
    view.addSubview(label)
    return view;
}

heightForRowAtIndexPath: Zdefiniuj wysokość każdej komórki w widoku tabeli.

Cel C

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 44;
}

Szybki 3

func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 44
}

heightForHeaderInSection: and heightForFooterInSection Zdefiniuj wysokość nagłówka i stopki każdej sekcji w widoku tabeli

Cel C

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 33;
}

Szybki 3

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 33
}

Niestandardowe komórki

Dostosowanie UITableViewCell może pozwolić na bardzo potężne, dynamiczne i responsywne interfejsy. Dzięki szerokiemu dostosowaniu i w połączeniu z innymi technikami możesz wykonywać następujące czynności: aktualizować określone właściwości lub elementy interfejsu, gdy zmieniają się, animować lub rysować w komórce, wydajnie ładować wideo podczas przewijania przez użytkownika, a nawet wyświetlać zdjęcia podczas pobierania z sieć. Możliwości tutaj są prawie nieograniczone. Poniżej znajduje się prosty przykład tego, jak może wyglądać niestandardowa komórka.

Przykład niestandardowego UITableViewCell

Ta sekcja obejmuje podstawy i, mam nadzieję, zostanie rozszerzona o szczegóły bardziej złożonych procesów, takich jak te opisane powyżej.

Tworzenie niestandardowej komórki

Najpierw utwórz nową podklasę UITableViewCell (utwórz nową klasę Cocoa Touch w Xcode i ustaw UITableViewCell jako nadklasę). Poniżej może wyglądać twój kod po podklasowaniu.

Szybki

class CustomTableViewCell: UITableViewCell {
    static var identifier: String {
        return NSStringFromClass(self)
    }

    var customLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        customLabel = UILabel(frame: CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height))
        customLabel.textAlignment = .center
        contentView.addSubview(customLabel)
    }
}

Opcjonalnie zaznacz „Utwórz także plik XIB” podczas tworzenia nowego pliku, aby dostosować go za pomocą Konstruktora interfejsów. W takim przypadku podłącz customLabel jako @IBOutlet

Utwórz także plik XIB

W UIViewController zawierającym tableView zarejestruj nową klasę komórki niestandardowej (patrz poniżej). Uwaga: jest to konieczne tylko wtedy, gdy nie zaprojektujesz komórki z Storyboard w interfejsie widoku tabeli.

Szybki

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Register Cell Class
    tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: CustomTableViewCell.identifier)
}

Jeśli zdecydujesz się użyć pliku XIB, zamiast tego registerNib :

Szybki

// Register Nib
tableView.register(UINib(nibName: CustomTableViewCell.identifier, bundle: nil), forCellReuseIdentifier: CustomTableViewCell.identifier)

Teraz, gdy twoja tableView wie o twojej komórce niestandardowej, możesz ją cellForRowAtIndexPath kolejki w cellForRowAtIndexPath :

Szybki

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Load the CustomTableViewCell. Make sure the identifier supplied here matches the one from your cell
    let cell: CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier(CustomTableViewCell.identifier) as! CustomTableViewCell

    // This is where the magic happens - setting a custom property on your very own cell
    cell.customLabel.text = "My Custom Cell"

    return cell
}

Rozwijanie i zwijanie komórek UITableViewCells

W swoim Storyboard dodaj obiekt UITableView do UIViewController i pozwól, aby obejmował cały widok. Skonfiguruj połączenia UITableviewDataSource i UITableviewDelegate .

Cel C

W twoim pliku .h

NSMutableArray *arrayForBool;
NSMutableArray *sectionTitleArray;

W twoim pliku .m

- (void)viewDidLoad  {
    [super viewDidLoad];

    arrayForBool = [[NSMutableArray alloc] init];
    sectionTitleArray = @[@"Sam",@"Sanju",@"John",@"Staffy"];
           
    for (int i=0; i<[sectionTitleArray count]; i++) {
        [arrayForBool addObject:[NSNumber numberWithBool:NO]];
    }

    _tableView.dataSource = self;
    _tableView.delegate = self;
}  

 // Declare number of rows in section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     if ([[arrayForBool objectAtIndex:section] boolValue]) {
         return section+2;
    } else {
         return 0; 
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
static NSString *cellid=@"hello";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellid];
if (cell==nil) {
    cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellid];
}
   BOOL manyCells  = [[arrayForBool objectAtIndex:indexPath.section] boolValue];

         /** If the section supposed to be closed******/
    if(!manyCells){
        cell.backgroundColor=[UIColor clearColor];   
        cell.textLabel.text=@"";
    }
      /** If the section supposed to be Opened******/
    else{
        cell.textLabel.text=[NSString stringWithFormat:@"%@ %d",[sectionTitleArray objectAtIndex:indexPath.section],indexPath.row+1];
        cell.backgroundColor=[UIColor whiteColor];
        cell.selectionStyle=UITableViewCellSelectionStyleNone ;
    }
cell.textLabel.textColor=[UIColor blackColor];

 /** Add a custom Separator with cell*/
  UIView* separatorLineView = [[UIView alloc]initWithFrame:CGRectMake(15, 40, _expandableTableView.frame.size.width-15, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:separatorLineView];
return cell;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [sectionTitleArray count];
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath  *)indexPath
{

/*************** Close the section, once the data is selected ***********************************/
[arrayForBool replaceObjectAtIndex:indexPath.section withObject:[NSNumber numberWithBool:NO]];

 [_expandableTableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic];

 }

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[arrayForBool objectAtIndex:indexPath.section] boolValue]) {
    return 40;
}
return 0;

   }

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{

UIView *sectionView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 280,40)];
sectionView.tag=section;
UILabel *viewLabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 0, _expandableTableView.frame.size.width-10, 40)];
viewLabel.backgroundColor=[UIColor clearColor];
viewLabel.textColor=[UIColor blackColor];
viewLabel.font=[UIFont systemFontOfSize:15];
viewLabel.text=[NSString stringWithFormat:@"List of %@",[sectionTitleArray objectAtIndex:section]];
[sectionView addSubview:viewLabel];
         /********** Add a custom Separator with Section view *******************/
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(15, 40, _expandableTableView.frame.size.width-15, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[sectionView addSubview:separatorLineView];

/********** Add UITapGestureRecognizer to SectionView   **************/

UITapGestureRecognizer  *headerTapped   = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
[sectionView addGestureRecognizer:headerTapped];

return  sectionView;


}

- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer{

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];
if (indexPath.row == 0) {
    BOOL collapsed  = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
    for (int i=0; i<[sectionTitleArray count]; i++) {
        if (indexPath.section==i) {
            [arrayForBool replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:!collapsed]];
        }
    }
    [_expandableTableView reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
    
   }
 }

Przesuń, aby usunąć wiersze

Zawsze myślę, że miło jest mieć bardzo prosty, samodzielny przykład, aby nic nie było zakładane, gdy uczę się nowego zadania. Ta odpowiedź brzmi: do usuwania wierszy UITableView . Projekt działa w następujący sposób:

animowany gif pokazujący przeciągnięcie i usunięcie

Ten projekt jest oparty na przykładzie UITableView dla Swift .

Dodaj kod

Utwórz nowy projekt i zamień kod ViewController.swift na następujący.

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // These strings will be the data for the table view cells
    var animals: [String] = ["Horse", "Cow", "Camel", "Pig", "Sheep", "Goat"]
    
    let cellReuseIdentifier = "cell"
    
    @IBOutlet var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // It is possible to do the following three things in the Interface Builder
        // rather than in code if you prefer.
        self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
        tableView.delegate = self
        tableView.dataSource = self
    }
    
    // number of rows in table view
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.animals.count
    }
    
    // create a cell for each table view row
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!
        
        cell.textLabel?.text = self.animals[indexPath.row]
        
        return cell
    }
    
    // method to run when table view cell is tapped
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
    
    // this method handles row deletion
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        
        if editingStyle == .Delete {
            
            // remove the item from the data model
            animals.removeAtIndex(indexPath.row)
            
            // delete the table view row
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            
        } else if editingStyle == .Insert {
            // Not used in our example, but if you were adding a new row, this is where you would do it.
        }
    }

}

Metoda jednego klucza w powyższym kodzie, która umożliwia usuwanie wierszy, jest ostatnią. Tutaj jeszcze raz do podkreślenia:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    
    if editingStyle == .Delete {
        
        // remove the item from the data model
        animals.removeAtIndex(indexPath.row)
        
        // delete the table view row
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    }
}

Storyboard

Dodaj UITableView do kontrolera widoku w serii ujęć. Użyj automatycznego układu, aby przypiąć cztery strony widoku tabeli do krawędzi kontrolera widoku. Przeciągnij kontrolę z widoku tabeli w serii ujęć do @IBOutlet var tableView: UITableView! wiersz w kodzie.

Skończone

To wszystko. Powinieneś być teraz w stanie uruchomić aplikację i usunąć wiersze, przesuwając palcem w lewo i stukając „Usuń”.

Notatki

  • Jest to dostępne tylko w systemie iOS 8. Aby uzyskać więcej informacji, zobacz tę odpowiedź .
  • Jeśli chcesz zmienić liczbę wyświetlanych przycisków lub tekst przycisku, zobacz tę odpowiedź, aby uzyskać więcej informacji.

Dalsza lektura

Linie separatora

Edycja szerokości linii oddzielających

Możesz ustawić, aby linie separatora widoku tabeli rozciągały się na różne szerokości w całej tabeli, zmieniając właściwość layoutMargins: w komórkach. Można to osiągnąć na wiele sposobów.

Zmiana linii separatora dla określonych komórek

W metodzie cellForRowAtIndexPath: źródła danych widoku tabeli lub metodzie willDisplayCell: ustaw właściwość layoutMargins: komórki na UIEdgeInsetsZero (rozciąga się na całą szerokość tabeli) lub na cokolwiek, co chcesz tutaj.

Cel C

[cell setLayoutMargins:UIEdgeInsetsZero];

// May also use separatorInset
[cell setSeparatorInset:UIEdgeInsetsZero];

Szybki

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
}

Usuń wszystkie linie separatora

Cienkie szare linie między każdą komórką mogą nie wyglądać dokładnie tak, jak chcesz. Ukrywanie ich przed wzrokiem jest dość proste.

W obejmującej UIViewController viewDidLoad: dodaj następujący kod. Możesz także ustawić tę właściwość w dowolnym momencie przed załadowaniem lub przeładowaniem widoku tabeli (niekoniecznie musi to być metoda viewDidLoad: .

Szybki:

 tableView.separatorStyle = .None

Cel C:

tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

Alternatywnie właściwość można zmienić w Storyboard lub XIB, wybierając tableView i ustawiając separator (pod inspektorem atrybutów) na None .

Ukryj nadmiar linii separatora

Możesz ukryć linie separatora UITableViewCell dla pustych komórek, ustawiając pusty widok stopki na dole UITableView:

Szybki

tableView.tableFooterView = UIView()

Cel C

tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

Dwa UITableViews obok siebie. Lewa strona obrazu pokazuje puste komórki z separatorem, prawa strona obrazu pokazuje komórki bez separatora.

Zdjęcie pochodzi od Raya Wenderlicha .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow