2016-02-22 43 views
9

我試圖通過點擊一個按鈕來放置一個可擴展的UITableViewCell如何強制uitableview調整單元格大小(解除高度限制後)?

我使用約束來強制動態UITextView告訴UITableViewCell它的新高度。 (使用自動佈局和UITableViewAutomaticDimension

這可以按預期的方式沒有按鈕:UITableViewCell的高度取決於UITextView的高度。

UITextView上約束單元格的大小,當點擊按鈕(單元格被摺疊)時,我想刪除高度約束爲UITextView(即限制單元格高度)並更新單元格因此。這裏的擴展方法:

-(void)extendCellWasTapped:(UITableViewCell*)senderCell{ 

    MAFollowingPostTableViewCell *cell = (MAFollowingPostTableViewCell*)senderCell; 

    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; 

    if (![self.arrayExtendedTitlesAtIndexPaths containsObject:indexPath]) { 
     [self.arrayExtendedTitlesAtIndexPaths addObject:indexPath]; 
    } 

    if ([self.tableView.indexPathsForVisibleRows containsObject:indexPath]) { 
     dispatch_async(dispatch_get_main_queue(), ^(void){ 

      [NSLayoutConstraint deactivateConstraints:@[cell.constraintTextViewHeight]]; 

      // CGPoint offset = self.tableView.contentOffset; 

      [self.tableView beginUpdates]; 
      [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 
      [self.tableView endUpdates]; 

// I would like to minimize the animations as well here.. but thats another //problem 
//   [self.tableView.layer removeAllAnimations]; 
//   [self.tableView setContentOffset:offset animated:NO]; 
//   [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 

     }); 
    } 
} 

如果我點擊按鈕,然後滾動到一個類似的單元格,它已經展開。所以我在這裏錯過了一些東西。禁用約束條件後,我已嘗試執行[cell updateConstraints],但它不起作用。

UPDATE

起初,按鈕不會顯示出來的某些原因。我注意到(使用相同的代碼),如果向下滾動然後向上滾動,該按鈕會顯示出來,如果我試圖擴展它,它會起作用。

UPDATE

這是我的UIViewController:

http://www.gfycat.com/FairBossyAfricanporcupine

注意,擴展按鈕不存在,但一旦我向下滾動/向上談到表明了,它延長了電池一旦我點擊擴展按鈕。

UPDATE

我注意到,被計算出的時TEXTSIZE(查看是否該細胞是可伸長的或沒有),在第一,TextView的比其最終狀態更寬。而且我在執行上的cellForRowAtIndexPath此檢查:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

MAPostTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath]; 

cell.delegate = self; 
cell.selectionStyle = UITableViewCellSelectionStyleNone; 

MAPostFollowing *post = (MAPostFollowing*)[self.arrayPosts objectAtIndex:indexPath.section]; 

cell.textViewTitle.textContainer.lineBreakMode = NSLineBreakByWordWrapping; 

NSString *title = [post.post title]; 

[cell.textViewTitle setText:title]; 

UIButton * buttonExtend = [cell buttonExtend]; 

if ([self.arrayExtendedTitlesAtIndexPaths containsObject:indexPath]) { 
    cell.constraintTextViewHeight.active = NO; 

    if (![buttonExtend isHidden]) { 
     buttonExtend.hidden = YES; 
     buttonExtend.userInteractionEnabled = NO; 
    } 
}else{ 

    cell.constraintTextViewHeight.active = YES; 

    NSLog(@"index %li", (long)indexPath.row); 

    BOOL b = ![self isTitleExtendable:title forTextView:cell.textViewTitle]; // Checks if the current text view is able to fit the title. If not, it will show the buttonExtend 

    buttonExtend.hidden = b; 
    buttonExtend.userInteractionEnabled = !b; 

} 
} 
... 

所以在第一次運行(滾動前)[自isTitleExtendable:標題forTextView:cell.textViewTitle]。不會返回所需的值,因爲textView在計算textSize時沒有正確的寬度。

所以,我認爲有以下幾種選擇: - 強制textViewTitle刷新它已經改變(從而計算出正確的可擴展的UI狀態) 佈局後 - 重新檢查擴展UI狀態一旦textViewTitle改變寬度

UPDATE

對於prepareForReuse方法,textViewTitle仍然有一個更寬的框架。在layoutSubviews方法中,它實際上是一個小框架。這裏的挑戰是被調用次數多了,它讓我假案(按鈕被顯示時,它不應該)

這是我與實驗:

-(void)layoutSubviews{ 
[super layoutSubviews]; 

BOOL b = [self isTitleExtendable:self.textViewTitle.text forTextView:self.textViewTitle]; 

self.buttonExtend.hidden = !b; 
self.buttonExtend.userInteractionEnabled = b; 

if (!b) { 
    NSLog(@"Button hidden YES UserInteraction NO"); 
}else{ 
    NSLog(@"Button hidden NO UserInteraction YES"); 
} 

NSLog(@"textViewTitle layout %f",self.textViewTitle.frame.size.width); 
} 
+0

到底是什麼,如果你嘗試,會發生什麼刪除約束而不是取消激活'[cell removeConstraints:cell.constraintTextViewHeight]'? – Randy

+0

同樣的事情。不知道一旦細胞被重複使用它是否會起作用(這就是爲什麼我停用而不是移除) – jonypz

+0

對於問題是什麼,我有點困惑。通過查看你的GIF,聽起來像問題是單元格第一次渲染時按鈕不在那裏。在你似乎暗示的問題中,相反,按鈕在那裏並且不起作用。忍受着我,也許這只是我誤解了這個問題。 – Eppilo

回答

0

難道忘記刪除indexpath from self.arrayExtendedTitlesAtIndexPaths

if (![self.arrayExtendedTitlesAtIndexPaths containsObject:indexPath]) { 
    [self.arrayExtendedTitlesAtIndexPaths addObject:indexPath]; 
} 
else 
{ 
    [self.arrayExtendedTitlesAtIndexPaths removeObject:indexPath]; 
} 
+0

不需要。這是用戶點擊擴展按鈕後執行的操作。一旦他這樣做了,那個細胞就會一直延續下去。 – jonypz

0

如果該按鈕不存在,當您滾動它時再次顯示肯定您有可重用性的問題。

您可能決定要在cellForRowAtIndexPath:中顯示或隱藏按鈕。如果你有一個條件,試着總是顯示這個按鈕,如果這樣會按預期工作,那麼只要這個約束存在或不存在,就隱藏一個單元內的按鈕。 UITableViewCell子類中正確的方法是prepareForReuse

+0

這可能是要走的路。儘管 – jonypz

+0

檢查了我的更新 – jonypz

-1

一旦您的更改完成,請致電[cell layoutSubviews];

+0

每個關於layoutSubviews:方法的文檔:「你不應該直接調用這個方法。」我仍然不是100%肯定的執行。 – GingerBreadMane

1

要做這樣的事情,你不應該依靠約束,但在tableView(_:heightForRowAtIndexPath:)你只需要根據上下文給出正確的高度。

按下按鈕會觸發更改,因此tableView(_:heightForRowAtIndexPath:)會爲您擴展的單元返回不同的值。

而只是在做這個觸發後,只是做:

[self.tableView beginUpdates]; 
[self.tableView endUpdates]; 

他們之間沒有任何東西,它會觸發UITableView「自然動畫」和你想

+0

正如說明所述,我正在使用UITableViewAutomaticDimension – jonypz

+0

我仍然會採用開始 - 結束更新技巧強制動畫更新;)但我沒有嘗試使用自動調整大小的單元格 – AncAinu