Как реализовать вид аккордеона для приложения iPhone SDK?

Используйте File.mkdirs() .

13
задан raf 22 December 2009 в 06:02
поделиться

3 ответа

Я бы просто использовал UITableView, чтобы высота каждой ячейки зависела от того, "открыта" она или нет, а затем переходите оттуда. Легко изменить размер строк и можно просто сделать так, чтобы общая высота объединенных ячеек была доступной в UITableView, чтобы она выглядела как гармошка больше, чем просто таблица.

Это быстрый хак, который должен работать, но в вашем .h файле подкласса UITableViewController:

bool sectionopen[4]; ///or some other way of storing the sections expanded/closed state

И в .m файле поместите что-то вроде:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 4;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  {
    if (sectionopen[indexPath.row]) {
        return 240;///it's open
    } else {
        return 45;///it's closed
    }

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *mycell = [[[UITableViewCell alloc] init] autorelease];
    mycell.textLabel.text= @"Section Name";
    return mycell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ///turn them all off
    sectionopen[0]=NO;
    sectionopen[1]=NO;
    sectionopen[2]=NO;
    sectionopen[3]=NO;

    ///open this one
    sectionopen[indexPath.row]=YES;

    ///animate the opening and expand the row
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}

Это в основном возьмет 4 строки и превратит их в свернутые секции, где выбор одной строки расширит ее до 240 пикселей и свернет все остальные строки до 40. Вы можете изменить все эти цифры, разобраться в секциях и делать с ними все, что захотите.

Я попробовал это, и это работает. Затем вы можете завершить его, добавив в код создания ячейки другое содержимое, чтобы добавить в секцию все, что захотите (включая, возможно, прокручиваемый UITextView, если хотите)

.
18
ответ дан 1 December 2019 в 18:13
поделиться

​​Я только что наткнулся на это и нашел решение mjdth очень простым и полезным. Однако вы можете использовать

[self.tableView reloadRowsAtIndexPaths: paths withRowAnimation:UITableViewRowAnimationBottom];

вместо предложенного метода reloadSections , поскольку строки перезагрузки обеспечивают более плавный переход.

2
ответ дан 1 December 2019 в 18:13
поделиться

Вот класс CollapsingTableViewDelegate, с которым я сейчас работаю, чтобы сделать это. Это работает только со статическим содержимым таблицы.

Вы предоставляете этому классу реализацию CollapsingTableCellDelegate, который должен знать, как вычислить свернутые и развернутые размеры каждой строки, и как создать UIView для каждой строки. Представление остается неизменным в свернутом или развернутом виде, так что верхняя часть представления каждой строки служит кликабельным заголовком этой строки.

Затем вы делаете этот класс источником данных и делегатом для вашего UITableView.

Файл заголовка CollapsingTableViewDelegate.h:

#import <UIKit/UIKit.h>

@protocol CollapsingTableCellDelegate<NSObject>

@required
- (CGFloat)collapsingCellHeightForRow:(int)row expanded:(BOOL)expanded;
- (UIView *)collapsingCellViewForRow:(int)row;

@optional
- (BOOL)collapsingCellAllowCollapse:(int)row;

@end

struct cell;

@interface CollapsingTableViewDelegate : NSObject <UITableViewDelegate, UITableViewDataSource> {
    id<CollapsingTableCellDelegate> cellDelegate;
    int numCells;
    int currentSelection;
    struct cell *cells;
}

@property (nonatomic, retain, readonly) id<CollapsingTableCellDelegate> cellDelegate;
@property (nonatomic, assign, readonly) int numCells;
@property (nonatomic, assign) int currentSelection;
@property (nonatomic, assign, readonly) struct cell *cells;

- (CollapsingTableViewDelegate *)initWithCellDelegate:(id<CollapsingTableCellDelegate>)delegate numCells:(int)numCells;
- (void)tableView:(UITableView *)tableView touchRow:(int)newSelection;

@end

и файл исходников CollapsingTableViewDelegate.m:

#import "CollapsingTableViewDelegate.h"

@implementation CollapsingTableViewDelegate

struct cell {
    u_char expanded;
    u_char collapsable;
};

@synthesize cellDelegate;
@synthesize currentSelection;
@synthesize cells;
@synthesize numCells;

#pragma mark -
#pragma mark Setup and Teardown

- (CollapsingTableViewDelegate *)initWithCellDelegate:(id<CollapsingTableCellDelegate>)delegate numCells:(int)num {
    if ([super init] == nil)
        return nil;
    if ((cells = calloc(num, sizeof(*cells))) == NULL) {
        [self autorelease];
        return nil;
    }
    cellDelegate = [delegate retain];
    numCells = num;
    for (int row = 0; row < self.numCells; row++) {
        struct cell *const cell = &self.cells[row];

        cell->collapsable = ![self.cellDelegate respondsToSelector:@selector(collapsingCellAllowCollapse:)]
          || [self.cellDelegate collapsingCellAllowCollapse:row];
        cell->expanded = !cell->collapsable;
    }
    currentSelection = -1;
    return self;
}

- (void)dealloc {
    [cellDelegate release];
    free(cells);
    [super dealloc];
}

- (void)tableView:(UITableView *)tableView reloadRow:(int)row fade:(BOOL)fade {
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:row inSection:0]]
                     withRowAnimation:fade ? UITableViewRowAnimationFade : UITableViewRowAnimationNone];
}

- (void)tableView:(UITableView *)tableView touchRow:(int)newSelection {

    // Sanity check
    if (newSelection < -1 || newSelection >= self.numCells) {
        NSLog(@"CollapsingTableViewDelegate: invalid row %d not in the range [-1..%d)", newSelection, self.numCells);
        return;
    }

    // Gather info
    int oldSelection = self.currentSelection;
    BOOL sameCellSelected = newSelection == oldSelection;
    struct cell *const oldCell = oldSelection != -1 ? &self.cells[oldSelection] : NULL;
    struct cell *const newCell = newSelection != -1 ? &self.cells[newSelection] : NULL;

    // Mark old cell as collapsed and new cell as expanded
    if (newCell != NULL)
        newCell->expanded = TRUE;
    if (oldCell != NULL)
        oldCell->expanded = FALSE;
    self.currentSelection = sameCellSelected ? -1 : newSelection;

    // Update table view
    if (oldSelection >= newSelection) {
        if (oldSelection != -1)
            [self tableView:tableView reloadRow:oldSelection fade:sameCellSelected];
        if (newSelection != -1 && !sameCellSelected)
            [self tableView:tableView reloadRow:newSelection fade:TRUE];
    } else {
        if (newSelection != -1 && !sameCellSelected)
            [self tableView:tableView reloadRow:newSelection fade:TRUE];
        if (oldSelection != -1)
            [self tableView:tableView reloadRow:oldSelection fade:sameCellSelected];
    }

    // If expanding a cell, scroll it into view
    if (newSelection != -1 && !sameCellSelected) {
        [tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:newSelection inSection:0]
                         atScrollPosition:UITableViewScrollPositionTop
                                 animated:TRUE];
    }
}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.numCells;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    struct cell *const cell = &self.cells[row];
    return [self.cellDelegate collapsingCellHeightForRow:row expanded:cell->expanded];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    UIView *cellView = [self.cellDelegate collapsingCellViewForRow:row];
    [cellView removeFromSuperview];
    UITableViewCell *tvcell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
    [tvcell.contentView addSubview:cellView];
    tvcell.clipsToBounds = TRUE;
    tvcell.selectionStyle = UITableViewCellSelectionStyleNone;
    return tvcell;
}

#pragma mark -
#pragma mark Table view delegate

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    struct cell *const cell = &self.cells[row];
    return cell->collapsable ? indexPath : nil;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newSelection {
    [tableView deselectRowAtIndexPath:newSelection animated:TRUE];
    [self tableView:tableView touchRow:[newSelection row]];
}

@end

Не совершенство, но, кажется, в основном работает для меня.

1
ответ дан 1 December 2019 в 18:13
поделиться