Kun je animeren een hoogte verandering op een UITableViewCell wanneer geselecteerd?

stemmen
361

Ik gebruik een UITableViewin mijn iPhone app, en ik heb een lijst van mensen die behoren tot een groep. Ik zou willen zodat wanneer de gebruiker op een bepaalde persoon klikt (dus de cel te selecteren), de cel groeit in de hoogte op verschillende UI bedieningen voor het bewerken van de eigenschappen van die persoon.

Is dit mogelijk?

De vraag is gesteld op 20/01/2009 om 04:17
bron van user
In andere talen...                            


21 antwoorden

stemmen
833

Ik vond een heel eenvoudige oplossing voor dit als een neveneffect van een UITableViewwaar ik aan werkte .....

Bewaar de cel hoogte in een variabele die de oorspronkelijke hoogte normaal meldt via het tableView: heightForRowAtIndexPath:, dan wanneer je wilt een hoogte verandering animeren, verander eenvoudig de waarde van de variabele en noemen dit ...

[tableView beginUpdates];
[tableView endUpdates];

U vindt het geen volledig reload doen, maar is genoeg voor het UITableViewte weten dat het om de cellen opnieuw te tekenen, grijpen de nieuwe hoogte waarde voor de cel .... en wat denk je? Het bezielt de verandering voor u. Zoet.

Ik heb een meer gedetailleerde uitleg en volledige codevoorbeelden op mijn blog ... Animate UITableView celhoogte Change

antwoordde op 14/01/2010 om 12:42
bron van user

stemmen
56

Ik hou van het antwoord door Simon Lee. Ik heb eigenlijk niet te proberen deze methode, maar het lijkt alsof het de grootte van alle cellen in de lijst zou veranderen. Ik hoopte op een verandering van alleen de cel die wordt afgetapt. Ik deed het een beetje zoals Simon, maar met slechts een klein verschil. Dit zal het uiterlijk van een cel te veranderen wanneer het wordt geselecteerd. En het maakt animeren. Gewoon een andere manier om het te doen.

Maak een int om een ​​waarde voor de huidige geselecteerde cel index te houden:

int currentSelection;

Dan:

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

Dan:

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

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


}

Ik weet zeker dat je kunt soortgelijke veranderingen in tableView maken: cellForRowAtIndexPath: de aard van de cel een xib bestand voor de cel te veranderen of zelfs te laden.

Op deze manier zal de currentSelection beginnen bij 0. Je nodig zou hebben om aanpassingen te maken als je niet de eerste cel van de lijst (op index 0) om te kijken standaard geselecteerd wilde.

antwoordde op 26/04/2011 om 00:25
bron van user

stemmen
19

Voeg een woning aan het bijhouden van de geselecteerde cel te houden

@property (nonatomic) int currentSelection;

Zet deze op een sentinel waarde in (bijvoorbeeld) viewDidLoad, om ervoor te zorgen dat de UITableViewstart in de 'normale' positie

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

    //sentinel
    self.currentSelection = -1;
}

In heightForRowAtIndexPathu de hoogte kunt instellen u wilt gebruiken voor de geselecteerde cel

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

In didSelectRowAtIndexPathbesparen u de huidige selectie en opslaan van een dynamische hoogte, indien nodig

- (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];
    }
}

In didDeselectRowAtIndexPathset de selectie index terug naar de sentinel waarde en animeren de cel terug naar de normale vorm

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

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}
antwoordde op 05/08/2013 om 17:02
bron van user

stemmen
12

reloadData is niet goed, want er is geen animatie ...

Dit is wat ik momenteel proberen:

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];

Het werkt bijna goed. Bijna. Ik ben het verhogen van de hoogte van de cel, en soms is er een beetje "hik" in de tabel aanzicht als de cel wordt vervangen, alsof sommige scrollen positie in de tabelweergave wordt bewaard, de nieuwe cel (dat is de eerste cel in de tabel) eindigt met een offset te hoog en de ScrollView niet te verplaatsen.

antwoordde op 07/05/2009 om 00:24
bron van user

stemmen
10

Ik opgelost met reloadRowsAtIndexPaths.

Ik sparen in didSelectRowAtIndexPathde indexPath van geselecteerde cel en bel reloadRowsAtIndexPathsaan het einde (u kunt NSMutableArray te sturen voor de lijst van het element die u wilt reload).

In heightForRowAtIndexPathkunt u controleren of indexPath is in de lijst of niet die van expandIndexPath cel en stuur hoogte.

Je kunt dit eenvoudig voorbeeld te controleren: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam Het is een eenvoudige oplossing.

voeg ik een soort code als je hulp

- (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];
}
antwoordde op 14/11/2014 om 13:20
bron van user

stemmen
10

Ik weet niet wat dit allemaal over bellen beginUpdates / endUpdates in successie is, kun je gewoon gebruiken -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Hier is een voorbeeld van een project .

antwoordde op 02/08/2014 om 23:52
bron van user

stemmen
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;
}
antwoordde op 15/08/2016 om 16:32
bron van user

stemmen
2

slechts een opmerking voor iemand zoals ik op zoek naar toe te voegen "Meer Details" op maat cel.

[tableView beginUpdates];
[tableView endUpdates];

Heeft een uitstekende werk, maar vergeet niet om "crop" cel view. Van Interface Builder selecteert u de Cell -> Inhoud Beeld -> vanaf eigenschapcontrole selecteer " Clip subweergave "

antwoordde op 25/03/2015 om 20:08
bron van user

stemmen
2

Probeer deze is voor het uitbreiden van indexwise rij:

@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;
}
antwoordde op 24/09/2014 om 06:41
bron van user

stemmen
1

In plaats van het beginUpdates()/ endUpdates()de aanbevolen oproep is nu:

tableView.performBatchUpdates(nil, completion: nil)

Apple zegt, met betrekking tot beginUpdates / endUpdates: "Gebruik de performBatchUpdates (_:. Voltooiing :) methode in plaats van deze ene waar mogelijk"

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

antwoordde op 19/11/2018 om 16:47
bron van user

stemmen
1

Heres een kortere versie van Simons antwoord voor Swift 3. zorgt ook voor omschakeling van de cel van de selectie

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
  }
antwoordde op 30/05/2017 om 23:36
bron van user

stemmen
1

Swift versie van het antwoord van Simon Lee's.

// 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
}

Toen in 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()
            }
        }
    }
}
antwoordde op 07/06/2016 om 15:30
bron van user

stemmen
0

Swift 4 en hoger

Voeg onderstaande code in je didselect rij afgevaardigde methode Tableview's

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
antwoordde op 23/11/2018 om 11:53
bron van user

stemmen
0

ingangen -

tableView.beginUpdates () tableView.endUpdates () zullen deze functies niet bellen

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

Maar, als je dat doet, tableView.reloadRows (op: [selectedIndexPath als indexPath!], Met: .none)

Het zal de roep func TableView (_ tableView: UITableView, cellForRowAt indexPath: indexPath) -> UITableViewCell {} deze functie.

antwoordde op 28/03/2018 om 11:08
bron van user

stemmen
0

Swift versie van antwoord Simon Lee's :

tableView.beginUpdates()
tableView.endUpdates()

Houd er rekening mee dat u de hoogte eigenschappen moeten wijzigen VOORDAT endUpdates() .

antwoordde op 08/02/2018 om 14:11
bron van user

stemmen
0

Ja het is mogelijk.

UITableView een werkwijze gemachtigde 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) {
    }];
}

Maar in uw geval als de gebruiker scrollt en kiest een andere cel dan moet u naar de laatste geselecteerde cel te krimpen en de momenteel geselecteerde cel uit te breiden hebben reloadRowsAtIndexPaths:gesprekken heightForRowAtIndexPath:dus dienovereenkomstig te handelen.

antwoordde op 01/08/2016 om 11:29
bron van user

stemmen
0

Controleer deze methode na iOS 7 en hoger.

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

Er zijn verbeteringen aangebracht om deze in iOS 8. Wij kan ingesteld als eigendom van de tabelweergave zelf.

antwoordde op 04/03/2016 om 12:10
bron van user

stemmen
0

Ik gebruikte @ geweldig antwoord Joy's, en het werkte perfect met iOS 8.4 en XCode 7.1.1.

In het geval dat u op zoek bent naar uw mobiele toggle-staat te maken, veranderde ik de -tableViewDidSelect op het volgende:

-(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];

}

Ik hoop dat een van deze je geholpen.

antwoordde op 19/11/2015 om 21:00
bron van user

stemmen
0

Hier is mijn code aangepaste UITableViewsubklasse, die uit te breiden UITextViewaan de tafel cel, zonder herladen (en verloren toetsenbord focus):

- (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;
}
antwoordde op 10/11/2015 om 02:14
bron van user

stemmen
-1

Ik heb dit probleem met een beetje hack opgelost:

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;
}

Toen ik nodig om de cel hoogte I uit te breiden isInEdit = YESen roept u de methode [self onTimer]en het bezielt de celgroei tot het de s_CellHeightEditing waarde te bereiken :-)

antwoordde op 20/08/2009 om 21:18
bron van user

stemmen
-1

Haal het indexPath van de geselecteerde rij. Laad de tafel. Bij de werkwijze volgens heightForRowAtIndexPath UITableViewDelegate, stel de hoogte van de voor een andere hoogte en in de andere rij terug het normale rijhoogte

antwoordde op 21/01/2009 om 16:13
bron van user

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