it-swarm.dev

Seçildiğinde bir UITableViewCell'deki yükseklik değişimini hareketlendirebilir misiniz?

İPhone uygulamamda UITableView__ kullanıyorum ve bir gruba ait kişilerin bir listesine sahibim. Kullanıcı belirli bir kişiye tıkladığında (böylece hücreyi seçerken), hücrenin o kişinin özelliklerini düzenlemek için çeşitli UI kontrolleri gösterecek şekilde büyür. 

Mümkün mü? 

379
Ted

Buna gerçekten çok basit bir çözüm buldum. UITableView 'in yan etkisi olarak.

Hücre yüksekliğini normalde tableView: heightForRowAtIndexPath: aracılığıyla orijinal yüksekliği bildiren bir değişkende saklayın, ardından bir yükseklik değişimini canlandırmak istediğinizde, değişkenin değerini değiştirin ve bunu arayın ...

[tableView beginUpdates];
[tableView endUpdates];

Tam bir yeniden yükleme yapmadığını göreceksiniz ama UITableView'nin hücreleri yeniden çizmesi, hücrenin yeni yükseklik değerini alması gerektiğini bilmesi ve ... ne olacağını bilmesi için yeterli. Bu sizin için değişikliği HAYAL ETMEKTEDİR. Tatlı.

Blogumda daha ayrıntılı bir açıklama ve tam kod örnekleri var ... Animate UITableView Cell Height Change

862
Simon Lee

Simon Lee'nin cevabını beğendim. Aslında bu yöntemi denemedim, ancak listedeki tüm hücrelerin boyutunu değiştirecek gibi görünüyor. Dokunulan hücrenin değişmesini umuyordum. Bunu Simon gibi yaptım ama biraz farkla. Bu, seçildiğinde hücrenin görünümünü değiştirir. Ve canlandırıyor. Bunu yapmanın başka bir yolu.

Geçerli seçilen hücre dizini için bir değer tutacak bir int oluşturun:

int currentSelection;

Sonra: 

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

Sonra:

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

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


}

TableView'de benzer değişiklikler yapabileceğinizden eminim: cellForRowAtIndexPath: hücre türünü değiştirmek veya hatta hücre için bir xib dosyası yüklemek için.

Bu şekilde currentSelection 0 ile başlayacaktır. Listenin ilk hücresinin (dizin 0'da) varsayılan olarak seçili görünmesini istemiyorsanız ayarlamalar yapmanız gerekecektir.

59
Mark A.

Seçili hücrenin kaydını tutmak için bir özellik ekleyin

@property (nonatomic) int currentSelection;

viewDidLoad öğesinin 'normal' konumda başladığından emin olmak için UITableView öğesindeki bir sentinel değerine ayarlayın

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

    //sentinel
    self.currentSelection = -1;
}

heightForRowAtIndexPath içinde, seçilen hücre için istediğiniz yüksekliği ayarlayabilirsiniz.

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

didSelectRowAtIndexPath uygulamasında mevcut seçimi ve gerekirse dinamik yüksekliği kaydedersiniz

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

didDeselectRowAtIndexPath içinde seçim dizinini tekrar sentinel değerine ayarlayın ve hücreyi normal forma geri getirin

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

        // sentinel
        self.currentSelection = -1;

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

reloadData iyi değil çünkü animasyon yok ...

Şu anda deniyorum budur:

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

Neredeyse doğru çalışıyor. Neredeyse. Hücrenin yüksekliğini artırıyorum ve bazen masa görünümünde hücre değiştirilirken masa görünümünde küçük bir "hıçkırık" var, sanki tablo görünümündeki bir kaydırma konumu korunuyormuş gibi, yeni hücre (ilk hücre olan Tabloda) ofsetinin çok yüksek olması ile sona erer ve kaydırma görünümü onu yeniden konumlandırmak için seker.

14
lawrence

Bu kadar şeyin art arda startUpdates/endUpdates'i çağırmakla ilgili ne olduğunu bilmiyorum, sadece -[UITableView reloadRowsAtIndexPaths:withAnimation:] kullanabilirsiniz. İşte örnek bir proje .

11
axiixc

reloadRowsAtIndexPaths ile çözdüm. 

didSelectRowAtIndexPath içinde seçilen hücrenin indexPath değerini kaydedin ve sonunda reloadRowsAtIndexPaths öğesini çağırın (yeniden yüklemek istediğiniz öğelerin listesi için NSMutableArray gönderebilirsiniz).

heightForRowAtIndexPath öğesinde, indexPath öğesinin listede olup olmadığını genişletinIndexPath hücresinin olup olmadığını kontrol edebilir ve yüksekliği gönderebilirsiniz.

Bu temel örneği kontrol edebilirsiniz: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam .

eğer yardım edersen bir tür kod eklerim

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

Bunu indexwise satırını genişletmek için deneyin:

@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;
}
3
Nagarjun
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;
}
3
Roman Solodyashkin

benim gibi birisi için sadece bir not özel hücreye "Daha Fazla Ayrıntı" ekleyin. 

[tableView beginUpdates];
[tableView endUpdates];

Mükemmel bir iş çıkardım, ancak hücre görünümünü "kırpmayı" unutma. Arabirim Oluşturucusundan Hücre -> İçerik Görünümü -> Özellik Denetçisi'nden " Klip alt görünümü " seçeneğini seçin. 

2

Heres, Simons'un kısa versiyonunu Swift 3'e cevapladı. Ayrıca hücrenin seçimini değiştirmeye de izin veriyor

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
  }
1
aBikis

Simon Lee'nin cevabını Swift Versiyonu.

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

Sonra didSelectRowAtIndexPath () içinde 

  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()
            }
        }
    }
}
1
ioopl

beginUpdates()/endUpdates() yerine, önerilen çağrı şimdi:

tableView.performBatchUpdates(nil, completion: nil)

Apple, beginUpdates/endUpdates ile ilgili olarak şunları söylüyor: "Mümkün olduğunda bunun yerine showBatchUpdates (_: complete :) yöntemini kullanın."

Bakınız: https://developer.Apple.com/documentation/uikit/uitableview/1614908-beginupdates

1
raf

Evet mümkün.

UITableView bir temsilci yöntemi vardır 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) {
    }];
}

Ancak sizin durumunuzda, kullanıcı farklı bir hücreyi kaydırır ve seçerse, seçili hücreyi küçültmek ve genişletmek için son seçilen hücreye sahip olmanız gerekir reloadRowsAtIndexPaths:, heightForRowAtIndexPath: işlevini çağırır;.

1
Koushik

Girişler -

tableView.beginUpdates () tableView.endUpdates () bu işlevler çağrılmaz 

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

Ancak, yaparsanız, tableView.reloadRows (at: [selectedIndexPath! Olarak IndexPath], ile: .none)

O çağırır. func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} bu işlev.

0
sRoy

@ Joy'un müthiş cevabını kullandım ve ios 8.4 ve XCode 7.1.1 ile mükemmel çalıştı. 

Hücrenizi geçiş yapabilecek duruma getirmek istiyorsanız, -tableViewDidSelect öğesini aşağıdaki gibi değiştirdim:

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

}

Umarım bunlardan herhangi biri size yardımcı oldu. 

0
Septronic

İOS 7 ve sonrası için bu yöntemi kontrol edin. 

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

Bu iOS 8'de iyileştirmeler yapılmıştır. Bunu tablo görünümünün kendisinin bir özelliği olarak ayarlayabiliriz.

0
iGo

Swift 4 ve Üstü

size aşağıdaki tabloyu ekleyin: tableview'ın didselect row delegate metodu

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
0
midhun p

Simon Lee'nin cevabı 'nin hızlı versiyonu: _

tableView.beginUpdates()
tableView.endUpdates()

YÜKSEKLIK ÖZELLIKLERINIendUpdates() işlevinden önce değiştirmeniz gerektiğini unutmayın.

0
Tamás Sengel

İşte tablo hücresinde UITableView öğesini genişleten, yeniden yüklemeden (ve klavye odağını kaybetmeden) genişleten özel UITextView alt sınıfımın kodu:

- (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;
}
0
Vitaliy Gozhenko