Poți anima o schimbare de înălțime pe un UITableViewCell atunci când este selectat?

voturi
361

Eu folosesc o UITableViewîn aplicația mea iPhone, și am o listă de oameni care aparțin unui grup. Mi - ar place , astfel încât atunci când utilizatorul face clic pe o anumită persoană (selectarea , astfel , celula), celula creste in inaltime pentru a afișa mai multe controale ale interfeței de utilizare pentru editarea proprietăților acelei persoane.

Este posibil?

Întrebat 20/01/2009 la 04:17
sursa de către utilizator
În alte limbi...                            


21 răspunsuri

voturi
833

Am găsit o soluție foarte simplu la aceasta ca un efect secundar la un UITableViewam fost de lucru pe .....

Păstrați înălțimea celulei într - o variabilă care raportează înălțimea inițială in mod normal pe tableView: heightForRowAtIndexPath:, atunci când doriți să anima o schimbare înălțime, pur și simplu modificați valoarea variabilei și numesc acest lucru ...

[tableView beginUpdates];
[tableView endUpdates];

Veți găsi nu face o reîncărcare completă a, dar este suficient pentru UITableViewa ști că trebuie să redesenare celulele, hapsân noua valoare inaltime pentru celula .... si ghici ce? Aceasta animă schimbarea pentru tine. Dulce.

Am o explicație și cod completă mai detaliate probe pe blog - ul meu ... Animare UITableView Cell Inaltime Schimbare

Publicat 14/01/2010 la 12:42
sursa de către utilizator

voturi
56

Îmi place răspunsul lui Simon Lee. Nu am încercat de fapt, această metodă, dar se pare că ar schimba dimensiunea tuturor celulelor din listă. Am fost în speranța pentru o schimbare de doar celula care este exploatat. Am cam făcut ca Simon, dar cu doar o mică diferență. Acest lucru se va schimba aspectul unei celule atunci când este selectată. Și nu anima. Doar un alt mod de a face acest lucru.

Creați un int să dețină o valoare pentru indicele de celule selectat curent:

int currentSelection;

Apoi:

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

Apoi:

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

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


}

Sunt sigur că puteți face modificări similare în tableView: cellForRowAtIndexPath: pentru a schimba tipul de celule sau chiar să încarce un fișier XIb pentru celula.

Ca și aceasta, currentSelection va începe de la 0. Tu ar trebui să facă ajustări în cazul în care nu doriți prima celulă a listei (la indexul 0) pentru a vedea selectat în mod implicit.

Publicat 26/04/2011 la 00:25
sursa de către utilizator

voturi
19

Adăugați o proprietate pentru a ține evidența celulei selectate

@property (nonatomic) int currentSelection;

Setați - l la o valoare santinelă (de exemplu) viewDidLoad, pentru a se asigura că UITableViewîncepe în poziția „normală“

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

    //sentinel
    self.currentSelection = -1;
}

În heightForRowAtIndexPathputeți seta înălțimea dorită pentru celula selectată

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

În didSelectRowAtIndexPathsalvați selecția curentă și de a salva o înălțime dinamică, dacă este necesar

- (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 indicele de selecție înapoi la valoarea de santinelă și anima celula înapoi la forma normală

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

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}
Publicat 05/08/2013 la 17:02
sursa de către utilizator

voturi
12

reloadData nu este bun pentru că nu există nici o animație ...

Aceasta este ceea ce eu sunt în prezent, încerc:

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

Aproape funcționează corect. Aproape. Sunt creșterea înălțimii celulei, și, uneori, există un pic „sughiț“ în afișarea tabelului ca celula este înlocuit, ca și în cazul în care o anumită poziție de defilare în afișarea tabelului este păstrată, noua celulă (care este prima celulă în tabel) se termină cu offset-ul prea mare, iar scrollview ricoșează repoziționarea.

Publicat 07/05/2009 la 00:24
sursa de către utilizator

voturi
10

Am rezolvat cu reloadRowsAtIndexPaths.

Salva în didSelectRowAtIndexPathindexPath de celule selectate și apel reloadRowsAtIndexPathsla final (puteți trimite NSMutableArray pentru lista de elementului pe care doriți reîncărcare).

În heightForRowAtIndexPathputeți verifica dacă indexPath este în listă sau nu de celule expandIndexPath și trimite înălțime.

Puteți verifica acest exemplu de bază: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam Este o soluție simplă.

i se adaugă un fel de cod, dacă te ajute

- (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];
}
Publicat 14/11/2014 la 13:20
sursa de către utilizator

voturi
10

Nu știu ce toate aceste lucruri despre asteptare beginUpdates / endUpdates în succesiune este, puteți folosi -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Aici este un proiect de exemplu .

Publicat 02/08/2014 la 23:52
sursa de către utilizator

voturi
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;
}
Publicat 15/08/2016 la 16:32
sursa de către utilizator

voturi
2

doar o notă pentru cineva ca mine să căutați adăugați „Mai multe detalii“ la celula personalizate.

[tableView beginUpdates];
[tableView endUpdates];

A făcut o treabă excelentă, dar nu uitați să vedeți celula „cultură“. De la Interface Builder selectați Cell -> Conținut View -> de proprietate Inspector selectați " subview clipului "

Publicat 25/03/2015 la 20:08
sursa de către utilizator

voturi
2

Încercați acest lucru este pentru extinderea rând indexwise:

@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;
}
Publicat 24/09/2014 la 06:41
sursa de către utilizator

voturi
1

În loc de beginUpdates()/ endUpdates(), apelul recomandată este acum:

tableView.performBatchUpdates(nil, completion: nil)

Apple spune, în ceea ce privește beginUpdates / endUpdates: „Utilizați performBatchUpdates (_:. Finalizarea metodei în loc de aceasta ori de câte ori este posibil :)“

A se vedea: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

Publicat 19/11/2018 la 16:47
sursa de către utilizator

voturi
1

Heresa versiune mai scurtă de Simons răspuns pentru Swift 3. De asemenea, permite basculând de selecție a celulei

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
  }
Publicat 30/05/2017 la 23:36
sursa de către utilizator

voturi
1

Swift versiune a răspunsului Simon Lee.

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

Apoi, în 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()
            }
        }
    }
}
Publicat 07/06/2016 la 15:30
sursa de către utilizator

voturi
0

Swift 4 și de mai sus

adăugați codul de mai jos în tine metoda rând delegat didselect tableview lui

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
Publicat 23/11/2018 la 11:53
sursa de către utilizator

voturi
0

Intrări -

tableView.beginUpdates () tableView.endUpdates () aceste funcții nu vor suna

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

Dar, dacă faci, tableView.reloadRows (la: [selectedIndexPath ca IndexPath!], Cu: .none)

Se va apela tableView FUNC (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} această funcție.

Publicat 28/03/2018 la 11:08
sursa de către utilizator

voturi
0

Versiunea Swift a răspunsului Simon Lee :

tableView.beginUpdates()
tableView.endUpdates()

Rețineți că ar trebui să modificați proprietățile de înălțime ÎNAINTE endUpdates() .

Publicat 08/02/2018 la 14:11
sursa de către utilizator

voturi
0

Da este posibil.

UITableView are o metodă delegat 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) {
    }];
}

Dar , în cazul dumneavoastră , dacă utilizatorul derulează și selectează o celulă diferită , atunci u nevoie pentru a avea ultima celulă selectată pentru a micșora și extinde celula selectată în mod curent reloadRowsAtIndexPaths:apeluri , heightForRowAtIndexPath:astfel se ocupe în mod corespunzător.

Publicat 01/08/2016 la 11:29
sursa de către utilizator

voturi
0

Verificați această metodă după iOS 7 și mai târziu.

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

Îmbunătățirile au fost făcute la acest lucru în iOS 8. O putem seta ca proprietate a afișarea tabelului în sine.

Publicat 04/03/2016 la 12:10
sursa de către utilizator

voturi
0

Am folosit @ minunat răspunsul lui Joy, si a functionat perfect cu ios 8.4 și XCode 7.1.1.

În cazul în care sunteți în căutarea de a face celula de comutare-capabil, am schimbat -tableViewDidSelect la următoarele:

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

}

Sper ca toate astea te-a ajutat.

Publicat 19/11/2015 la 21:00
sursa de către utilizator

voturi
0

Aici este codul meu personalizat UITableViewsubclasă, care se extinde de UITextViewla celula de masă, fără reîncărcare (și a pierdut focalizarea tastaturii):

- (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;
}
Publicat 10/11/2015 la 02:14
sursa de către utilizator

voturi
-1

Tocmai am rezolvat această problemă cu un pic 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;
}

Când am nevoie pentru a extinde înălțimea celulei am stabilit isInEdit = YESși apel metoda [self onTimer]și animă creșterea celulară până când se ajunge la valoarea s_CellHeightEditing :-)

Publicat 20/08/2009 la 21:18
sursa de către utilizator

voturi
-1

Ia indexpath din rândul selectat. Reîncarcă tabel. În metoda heightForRowAtIndexPath de UITableViewDelegate, setați înălțimea rândului selectat la o înălțime diferită și pentru ceilalți reveni înălțimea normală rând

Publicat 21/01/2009 la 16:13
sursa de către utilizator

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