Můžete animovat změnu výšky na UITableViewCell při výběru?

hlasů
361

Jsem pomocí UITableViewmého aplikace pro iPhone, a mám seznam osob, které patří do skupiny. Já bych to tak, že když uživatel klikne na určitou osobu (tedy výběrem buňky), buňky rostou do výšky zobrazit několik ovládacích prvků uživatelského rozhraní pro editaci vlastností této osoby.

Je to možné?

Položena 20/01/2009 v 04:17
zdroj uživatelem
V jiných jazycích...                            


21 odpovědí

hlasů
833

Našel jsem to opravdu jednoduché řešení tohoto problému jako vedlejší účinek jako UITableViewjsem pracoval na .....

Ukládat výšku buňky v proměnné, která vykazuje původní výšku zpravidla prostřednictvím tableView: heightForRowAtIndexPath:, pak pokud chcete animovat změnu výšky, jednoduše změnit hodnotu proměnné a nazvat ...

[tableView beginUpdates];
[tableView endUpdates];

Zjistíte, že nedělá úplné znovu načíst, ale stačí, aby UITableViewvědět, že má překreslit buňky a sebral mu novou hodnotu výšky pro buňku .... a hádejte co? To oživuje změny pro vás. Sladký.

Mám detailnější vysvětlení a plná ukázky kódu na mém blogu ... Animate UITableView Cell výšku změnit

Odpovězeno 14/01/2010 v 12:42
zdroj uživatelem

hlasů
56

Líbí se mi odpověď Simon Lee. Nechtěl jsem vlastně vyzkoušet tuto metodu, ale vypadá to, že by se změnit velikost všech buněk v seznamu. Doufal jsem, že pro změnu jen buňky, která se odebírá. I tak nějak to udělal jako Simon, ale jen s malým rozdílem. Tím se změní vzhled buňky, když je vybrána. A to oživit. Jen jiný způsob, jak to udělat.

Vytvořte int držet hodnotu pro současný index vybrané buňky:

int currentSelection;

Pak:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    selectedNumber = row;
    [tableView beginUpdates];
    [tableView endUpdates];
}

Pak:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([indexPath row] == currentSelection) {
        return  80;
    }
    else return 40;


}

Jsem si jistý, můžete provést podobné změny ve Tableview: cellForRowAtIndexPath: změnit typ buňky nebo dokonce načíst soubor XIb pro buňku.

Takhle bude currentSelection začínají na 0. Budete muset provést úpravy, pokud nechtěl na první buňku v seznamu (na indexu 0) vypadat vybraný ve výchozím nastavení.

Odpovězeno 26/04/2011 v 00:25
zdroj uživatelem

hlasů
19

Přidejte vlastnost sledovat vybrané buňky

@property (nonatomic) int currentSelection;

Nastavte ji na hodnotu sentinelové v (například) viewDidLoad, aby se ujistil, že UITableViewzačíná v ‚normální‘ polohy

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //sentinel
    self.currentSelection = -1;
}

V heightForRowAtIndexPathmůžete nastavit výšku chcete pro vybrané buňky

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int rowHeight;
    if ([indexPath row] == self.currentSelection) {
        rowHeight = self.newCellHeight;
    } else rowHeight = 57.0f;
    return rowHeight;
}

V didSelectRowAtIndexPathuložit aktuální výběr a uložení dynamickou výšku, v případě potřeby

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        // do things with your cell here

        // set selection
        self.currentSelection = indexPath.row;
        // save height for full text label
        self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

Při didDeselectRowAtIndexPathnastavení indexu výběr zpět na hodnotu sentinelové a oživit buňku zpět do normální formy

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {       
        // do things with your cell here

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}
Odpovězeno 05/08/2013 v 17:02
zdroj uživatelem

hlasů
12

reloadData je k ničemu, protože tam není žádný animační ...

To je to, co jsem v současné době snaží:

NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

Je to skoro funguje hned. Téměř. Já zvýšení výšky buňky, a někdy to trochu „škytavka“ v zobrazení tabulky se na buňky je nahrazen, jako by někteří rolování pozice v zobrazení tabulky je zachováno, nový článek (což je první buňka v tabulce) skončí s jeho offset příliš vysoká, a scrollview odrazí jej přemístit.

Odpovězeno 07/05/2009 v 00:24
zdroj uživatelem

hlasů
10

Rozhodl jsem se reloadRowsAtIndexPaths.

I s výjimkou didSelectRowAtIndexPathna indexPath buňky zvolené a volat reloadRowsAtIndexPathsna konci (můžete posílat NSMutableArray na seznamu element je chcete znovu načíst).

V heightForRowAtIndexPathsi můžete zkontrolovat, zda indexPath je v seznamu, nebo ne expandIndexPath buňka je a poslat výšku.

Můžete zkontrolovat tuto základní příklad: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam Je to jednoduché řešení.

přidám druh kódu v případě, pomůže vám

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

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath
{
    if ([indexPath isEqual:_expandIndexPath])
        return 80;

    return 40;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Celda";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    [cell.textLabel setText:@"wopwop"];

    return cell;
}

#pragma mark -
#pragma mark Tableview Delegate Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *modifiedRows = [NSMutableArray array];
    // Deselect cell
    [tableView deselectRowAtIndexPath:indexPath animated:TRUE];
    _expandIndexPath = indexPath;
    [modifiedRows addObject:indexPath];

    // This will animate updating the row sizes
    [tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
Odpovězeno 14/11/2014 v 13:20
zdroj uživatelem

hlasů
10

Nevím, co všechny ty věci o volání beginUpdates / endUpdates v řadě znamená, že stačí použít -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Zde je příklad projektu .

Odpovězeno 02/08/2014 v 23:52
zdroj uživatelem

hlasů
2
BOOL flag;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    flag = !flag;
    [tableView beginUpdates];
    [tableView reloadRowsAtIndexPaths:@[indexPath] 
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES == flag ? 20 : 40;
}
Odpovězeno 15/08/2016 v 16:32
zdroj uživatelem

hlasů
2

Jen poznámka pro někoho, jako jsem já hledá přidat „Více detailů“ na vlastní buňky.

[tableView beginUpdates];
[tableView endUpdates];

Odvedl výbornou práci, ale nezapomeňte na „oříznutí“ pohled buněk. Od Interface Builder vyberte Cell -> Obsah Zobrazení -> z Inspektoru vlastností vyberte „ Clip subview

Odpovězeno 25/03/2015 v 20:08
zdroj uživatelem

hlasů
2

Zkuste to je pro rozšiřování indexwise řádek:

@property (nonatomic) NSIndexPath *expandIndexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.expandedIndexPath])
    return 100;

return 44;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandIndexPath]) {
    [modifiedRows addObject:self.expandIndexPath];
    self.expandIndexPath = nil;
} else {
    if (self.expandedIndexPath)
        [modifiedRows addObject:self.expandIndexPath];

    self.expandIndexPath = indexPath;
    [modifiedRows addObject:indexPath];
}

// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];

// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ViewControllerCellReuseIdentifier];
    cell.textLabel.text = [NSString stringWithFormat:@"I'm cell %ld:%ld", (long)indexPath.section, (long)indexPath.row];

return cell;
}
Odpovězeno 24/09/2014 v 06:41
zdroj uživatelem

hlasů
1

Namísto beginUpdates()/ endUpdates()doporučená hovor je nyní:

tableView.performBatchUpdates(nil, completion: nil)

Apple říká, co se týče beginUpdates / endUpdates: „Použití performBatchUpdates (_:. Dokončení :) metodu namísto tenhle kdykoli je to možné“

Viz: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

Odpovězeno 19/11/2018 v 16:47
zdroj uživatelem

hlasů
1

Heres kratší verze Simons odpověď na Swift 3. Také umožňuje přepínání výběru buňky

var cellIsSelected: IndexPath?


  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    cellIsSelected = cellIsSelected == indexPath ? nil : indexPath
    tableView.beginUpdates()
    tableView.endUpdates()
  }


  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if cellIsSelected == indexPath {
      return 250
    }
    return 65
  }
Odpovězeno 30/05/2017 v 23:36
zdroj uživatelem

hlasů
1

Swift verze Simon Lee odpověď.

// MARK: - Variables 
  var isCcBccSelected = false // To toggle Bcc.



    // MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    // Hide the Bcc Text Field , until CC gets focused in didSelectRowAtIndexPath()
    if self.cellTypes[indexPath.row] == CellType.Bcc {
        if (isCcBccSelected) {
            return 44
        } else {
            return 0
        }
    }

    return 44.0
}

Pak v didSelectRowAtIndexPath ()

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

    // To Get the Focus of CC, so that we can expand Bcc
    if self.cellTypes[indexPath.row] == CellType.Cc {

        if let cell = tableView.cellForRowAtIndexPath(indexPath) as? RecipientTableViewCell {

            if cell.tag == 1 {
                cell.recipientTypeLabel.text = "Cc:"
                cell.recipientTextField.userInteractionEnabled = true
                cell.recipientTextField.becomeFirstResponder()

                isCcBccSelected = true

                tableView.beginUpdates()
                tableView.endUpdates()
            }
        }
    }
}
Odpovězeno 07/06/2016 v 15:30
zdroj uživatelem

hlasů
0

Swift 4 a Above

přidat pod kódem do vás Tableview je didselect metodou řádek delegáta

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
Odpovězeno 23/11/2018 v 11:53
zdroj uživatelem

hlasů
0

vstupy -

tableView.beginUpdates () tableView.endUpdates () tyto funkce nebudou volat

func Tableview (_ Tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}

Ale pokud ano, tableView.reloadRows (na adrese: [selectedIndexPath jako IndexPath!], S: .none)

Bude volat func Tableview (_ Tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} tuto funkci.

Odpovězeno 28/03/2018 v 11:08
zdroj uživatelem

hlasů
0

Swift verze Simon Lee odpověď :

tableView.beginUpdates()
tableView.endUpdates()

Mějte na paměti, že byste měli změnit výškové vlastnosti PŘED endUpdates() .

Odpovězeno 08/02/2018 v 14:11
zdroj uživatelem

hlasů
0

Ano, je to možné.

UITableView má metodu delegáta didSelectRowAtIndexPath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [UIView animateWithDuration:.6
                          delay:0
         usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
          initialSpringVelocity:0
                        options:UIViewAnimationOptionBeginFromCurrentState animations:^{

                            cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
                            NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
                            [violatedTableView beginUpdates];
                            [violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
                            [violatedTableView endUpdates];
                        }
                     completion:^(BOOL finished) {
    }];
}

Ale ve vašem případě, pokud uživatel svitky a vybere jinou buňku pak u potřeba mít poslední vybranou buňku smršťovat se a rozšířit aktuálně vybranou buňku reloadRowsAtIndexPaths:hovory heightForRowAtIndexPath:tak zacházet odpovídajícím způsobem.

Odpovězeno 01/08/2016 v 11:29
zdroj uživatelem

hlasů
0

Zkontrolujte, zda tento způsob po iOS 7 a vyšší.

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}

Vylepšení byly provedeny, jak to v iOS 8. Můžeme nastavit jako vlastnost zobrazení tabulky sám.

Odpovězeno 04/03/2016 v 12:10
zdroj uživatelem

hlasů
0

Použil jsem @ úžasné odpovědi Joy, a to dokonale pracoval s iOS 8.4 a XCode 7.1.1.

V případě, že chtějí, aby váš mobilní lomené schopný jsem změnil -tableViewDidSelect na následující:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell, 
//cell is expanded. If tapped again on the same cell, 
//cell is collapsed. 
    if (self.currentSelection==indexPath.row) {
        self.currentSelection = -1;
    }else{
        self.currentSelection = indexPath.row;
    }
        // animate
        [tableView beginUpdates];
        [tableView endUpdates];

}

Doufám, že nic z toho vám pomohla.

Odpovězeno 19/11/2015 v 21:00
zdroj uživatelem

hlasů
0

Zde je můj kód vlastní UITableViewpodtřídy, která rozšíří UITextViewna buňky tabulky, bez překládky (a ztratil zaměření klávesnice):

- (void)textViewDidChange:(UITextView *)textView {
    CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
    // Check, if text height changed
    if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
        [self beginUpdates];

        // Calculate difference in height
        CGFloat difference = textHeight - self.previousTextHeight;

        // Update currently editing cell's height
        CGRect editingCellFrame = self.editingCell.frame;
        editingCellFrame.size.height += difference;
        self.editingCell.frame = editingCellFrame;

        // Update UITableView contentSize
        self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);

        // Scroll to bottom if cell is at the end of the table
        if (self.editingNoteInEndOfTable) {
            self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
        } else {
            // Update all next to editing cells
            NSInteger editingCellIndex = [self.visibleCells indexOfObject:self.editingCell];
            for (NSInteger i = editingCellIndex; i < self.visibleCells.count; i++) {
                UITableViewCell *cell = self.visibleCells[i];
                CGRect cellFrame = cell.frame;
                cellFrame.origin.y += difference;
                cell.frame = cellFrame;
            }
        }
        [self endUpdates];
    }
    self.previousTextHeight = textHeight;
}
Odpovězeno 10/11/2015 v 02:14
zdroj uživatelem

hlasů
-1

Právě jsem vyřešil tento problém s trochou hack:

static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;

- (void)onTimer {
    cellHeight++;
    [tableView reloadData];
    if (cellHeight < s_CellHeightEditing)
        heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}

- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        if (isInEdit) {
            return cellHeight;
        }
        cellHeight = s_CellHeight;
        return s_CellHeight;
}

Když jsem se muset rozšířit výška buňky I nastavit isInEdit = YESa volání metody [self onTimer]a oživuje buněčný růst, dokud se dosáhne hodnoty s_CellHeightEditing :-)

Odpovězeno 20/08/2009 v 21:18
zdroj uživatelem

hlasů
-1

Získat indexpath na řádku vybraného. Obnovit tabulku. Ve způsobu heightForRowAtIndexPath z UITableViewDelegate, nastavit výšku řádku zvoleného na jinou výšku a pro ostatní vrátí normální výšku řádku

Odpovězeno 21/01/2009 v 16:13
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more