Gibt es eine Möglichkeit, statische Tableview-Zellen (statischer Inhalt) mit dynamischen Tableview-Zellen (Prototyp-Inhalt) mithilfe des Storyboards zu kombinieren?
Ich schlage vor, Sie behandeln Ihre Tabelle als dynamisch, schließen jedoch die Zellen ein, die Sie immer oben möchten. Platzieren Sie im Storyboard eine UITableViewController
und verwenden Sie eine dynamische Tabelle. Fügen Sie der Tabelle beliebig viele UITableViewCell
-Prototypen hinzu. Sagen Sie jeweils eine für Ihre statischen Zellen und eine für die Darstellung der variablen Zellen.
In Ihrer UITableViewDataSource
-Klasse:
#define NUMBER_OF_STATIC_CELLS 3
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dynamicModel count] + NUMBER_OF_STATIC_CELLS;
}
und dann
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row < NUMBER_OF_STATIC_CELLS) {
// dequeue and configure my static cell for indexPath.row
NSString *cellIdentifier = ... // id for one of my static cells
} else {
// normal dynamic logic here
NSString *cellIdentifier = @"DynamicCellID"
// dequeue and configure for [self.myDynamicModel objectAtIndex:indexPath.row]
}
}
Ich hatte ein Problem, obwohl dies eine leichte Variante war. Ich wollte eigentlich dynamische und statische Zellen mischen, aber in verschiedenen Gruppen. Bedeutet Gruppe 1 nur statische Zellen und Gruppe 2 dynamische Zellen.
Dies wurde erreicht, indem statische Zellwerte (basierend auf ihren Prototyp-Zellkennungen) hart kodiert wurden. Die dynamischen Abschnitte hätten normal dynamisch besetzten Inhalt. Hier ist ein Beispielcode für den Fall, dass jemand anderes das gleiche Problem hat:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 1){
return @"Dynamic Cells";
}
if (section == 0){
return @"Static Cells";
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return 1; //However many static cells you want
} else {
return [_yourArray count];
}
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (indexPath.section == 0) {
NSString *cellIdentifier = @"staticCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = @"some static content";
return cell;
} else if (indexPath.section == 1){
NSString *cellIdentifier = @"dynamicCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [_yourArray objectAtIndex:indexPath.row];
return cell;
}
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
Da niemand wirklich eine echte Antwort auf das Problem gegeben hat (sowohl statische Zellen als auch Prototypzellen in derselben Tabellenansicht), dachte ich mir, ich würde in ..__ klingeln. Das ist möglich!
Erstellen Sie Ihre statischen Zellen, wie Sie es für richtig halten. Wenn Sie für die Abschnitte, die eine dynamische Zelle benötigen, KEINEN Standardtyp UITableViewCell verwenden, müssen Sie Ihre benutzerdefinierte Zelle in einer separaten Spitze erstellen. Andernfalls können Sie die Standardsektion verwenden. .__ Implementieren Sie anschließend die folgenden Delegierten. Grundsätzlich für jeden dieser Delegierten, für das statische Zeug, das wir als super bezeichnen wollen, geben wir für die Dynamik unsere Werte zurück.
WENN Sie Ihren dynamischen Abschnitt selektiv anzeigen möchten, müssen Sie zuerst numberOfSectionsInTableView implementieren (andernfalls können Sie diesen Delegierten auslassen):
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
int staticSections = 1;
int dynamicSections = 1;
if (SOME_BOOLEAN) {
return staticSections + dynamicSections;
} else {
return staticSections;
}
}
Dann müssen Sie numberOfRowsInSection implementieren:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 1) {
return A_COUNT;
} else {
return [super tableView:tableView numberOfRowsInSection:section];
}
}
Dann müssen Sie heightForRowAtIndexPath implementieren:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 44.0f;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
Dann einrückenLevelForRowAtIndexPath:
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 1; // or manually set in IB (Storyboard)
} else {
return [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; // or 0
}
}
Schließlich cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
SomeObject *obj = self.someArray[indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DynamicCell" forIndexPath:indexPath];
cell.textLabel.text = obj.textValue;
return cell;
} else {
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
Sie können jederzeit eine Tabellensicht der statischen Tabelle anzeigen lassen, sie jedoch im Code definieren. Legen Sie die Abschnitte, die Anzahl oder die Zeilen pro Abschnitt, Kopfzeilen usw. mithilfe der Delegatmethoden fest.
Dies ist leider nicht möglich, da sich statische Tabellensichten muss in einem UITableViewController befinden und dies nur eine Tabellenansicht zulässt.
Was Sie tun müssen, ist drei dynamischere UITableviewCell's zu erstellen und sie einzeln für die ersten drei Zeilen zu laden, in denen der statische Inhalt gewünscht wird.
Wenn Sie sich nicht sicher sind, wie das geht, lassen Sie es mich wissen und ich kann etwas Code finden.
Es ist nicht möglich, dass eine Tabellenansicht statisch ist und die andere dynamisch in demselben Ansichtscontroller ist. Sie müssen also beide dynamisieren. In der ersten Tabellenansicht konfigurieren Sie die Zellen im Code beim Initialisieren des View-Controllers, und aktualisieren Sie sie niemals.
Als eine andere Option können Sie ein ähnliches Aussehen erzielen, indem Sie Ihre dynamische Tabellenansicht in einen Teil einer Ansicht einbetten, die der Verknüpfung in Schritt 4 ähnelt. Anschließend können Sie nach Belieben festlegen, was Sie mit statischen Zellen vorhaben mithilfe von Scrollviews, Beschriftungen und Schaltflächen.
Eine Möglichkeit, dynamischen Inhalt in einer statischen Tabellensicht zu haben, besteht darin, Zellen zu klonen, in denen zusätzliche Zeilen erforderlich sind.
Für den dynamischen Abschnitt meiner Tabellenansicht lege ich eine oder mehrere Zellen im Interface Builder an. Zur Laufzeit kann ich diese kopieren, indem ich sie mit NSCoder archiviere und dann die Archivierung aufhebe.
Es funktioniert, ist aber nicht unbedingt schöner, als mit einer dynamischen Prototyp-Tabellensicht zu beginnen und von dort aus statische Zeilen zu erstellen.
Es schlägt mit Standard-Tabellensichtzellen fehl. Die faul erstellten Textbeschriftungen sind nicht korrekt angeordnet. Daher habe ich UITableViewCell-Unterklassen verwendet, in denen ich mich um das Archivieren und das Aufheben der Archivierung von Unteransichten kümmere.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == kContactsSection) {
NSArray *contacts = self.contacts;
Contact *contact = [contacts objectAtIndex:indexPath.row];
NSString *name = contact.name;
NSString *role = contact.role;
if ([role length] == 0) {
NNContactDefaultTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDefault"];
if (cell == nil) {
NNContactDefaultTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
return cell;
}
else {
NNContactDetailTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDetail"];
if (cell == nil) {
NNContactDetailTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:1 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
cell.contactDetailTextLabel.text = role;
return cell;
}
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
Im obigen Beispiel habe ich zwei Zelltypen. Beide sind im Interface Builder als Teil einer statischen Tabellensicht angeordnet.
Um dynamischen Inhalt in einem Abschnitt zu erhalten, muss ich auch die folgenden Methoden überschreiben:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == kContactsSection) {
NSArray *contacts = self.contacts;
NSUInteger contactCount = [contacts count];
return contactCount;
}
return [super tableView:tableView numberOfRowsInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
if (section == kContactsSection) {
return [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
}
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
if (section == kContactsSection) {
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
return indentation;
}
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath];
return indentation;
}
Sie können auch Schaltflächen (eine für jede statische Zelle, die Sie haben) erstellen, die wie Ihre Zellen gestaltet sind, und sie in die tableHeaderView oder tableFooterView der UITableView einfügen. Diese Schaltflächen sind immerhin nur Ansichten.
Sie müssen einige Logik hinzufügen, um eine Auswahl zwischen den Schaltflächen und den Zellen zu treffen, damit das gewohnte Erscheinungsbild erhalten bleibt.
Dies setzt natürlich voraus, dass Sie statische Zellen in Ihre Tabellenansicht oben oder unten in der Tabelle einfügen möchten.