擴大比方說,我們有一個自定義的UITableViewCell的UITableViewCell上點擊
所以每當我單擊單元格的自定義按鈕..它應擴大到一定程度(你可以說40高度更多...),當我點擊再次到相同的自定義按鈕,它應該摺疊到先前的高度。
開發者請指導我..我怎樣才能實現這個任務
擴大比方說,我們有一個自定義的UITableViewCell的UITableViewCell上點擊
所以每當我單擊單元格的自定義按鈕..它應擴大到一定程度(你可以說40高度更多...),當我點擊再次到相同的自定義按鈕,它應該摺疊到先前的高度。
開發者請指導我..我怎樣才能實現這個任務
執行heightForRowAtIndexPath來計算正確的高度。然後在您的按鈕的代碼,迫使表重新評估每個單元的高度與beginUpdates加endUpdates:
[self.tableView beginUpdates];
[self.tableView endUpdates];
更改到的tableview細胞的高度會自動heightForRowAtIndexPath計算和變化也將被動畫。
實際上,您可能會選擇單元格而不是您的單元格上的按鈕,而不是在didSelectRowAtIndexPath
中執行此操作。
我做了一個可重用的組件,將做你在談論什麼。這很容易使用,並有一個演示項目。
GCRetractableSectionController在GitHub上。
這正是我所需要的。 UITableviewCell中的UITableview。完善。謝謝。 :) – ScarletWitch 2015-10-29 07:57:24
對我來說,這是完美的解決方案 - 我想知道如何讓擴大的區域包含更多可點擊的單元行,而不僅僅是一個單元格。 – ToolmakerSteve 2017-03-12 01:25:09
我使用了Gcamp的源代碼並創建了自己的版本。
1)在loadView方法中,初始化一個可變數組,您將在其中保存段的展開或非展開狀態。將擴展狀態保存在單獨的數組中是非常重要的,當表視圖滾動時不會破壞它們(例如,如果將它存儲在headerView中,它將被重繪,並且忘記它展開或不展開的天氣)。在我的情況下,它是_sectionStatuses數組。
- (void)loadView
{
// At the beginning all sections are expanded
_sectionStates = [NSMutableArray arrayWithCapacity:self.tableView.numberOfSections];
for (int i = 0; i < self.tableView.numberOfSections; i++) {
_sectionStates[i] = [NSNumber numberWithBool:YES];
}
}
2)爲具有用於展開的按鈕的部分創建自定義headerView。使用委託模式將您的headerView中按鈕的動作委託給TableViewController。您可以在Gcamp的源代碼中找到合適的圖像。
3)創建一個操作來刪除或添加行。這裏_foldersArray是我的結構,它包含所有的數據。我的部分的headerView - MCExpandableAccountHeaderView知道它是自己的部分編號 - 當我爲每個部分創建標題視圖時,我將其轉移到那裏。將它轉移到此方法非常重要,因爲您必須知道哪個節現在被展開或拉伸。
- (void)expandClicked:(MCAccountHeaderView *)sender
{
MCExpandableAccountHeaderView *expandableAccountHeaderView = (MCExpandableAccountHeaderView*)sender;
// Finding a section, where a button was tapped
NSInteger section = expandableAccountHeaderView.section;
// Number of rows, that must be in a section when it is expanded
NSUInteger contentCount = [_foldersArray[section - 1][@"folders"] count];
// Change a saved status of a section
BOOL expanded = [_sectionStates[section] boolValue];
expanded = ! expanded;
expandableAccountHeaderView.expanded = expanded;
_sectionStates[section] = [NSNumber numberWithBool:expanded];
// Animation in a table
[self.tableView beginUpdates];
NSMutableArray* modifiedIndexPaths = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < contentCount; i++) {
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:section];
[modifiedIndexPaths addObject:indexPath];
}
if (expandableAccountHeaderView.expanded) [self.tableView insertRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade];
else [self.tableView deleteRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
// Scroll to the top of current expanded section
if (expandableAccountHeaderView.expanded) [self.tableView scrollToRowAtIndexPath:INDEX_PATH(0, section) atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
4)根據擴展與否,在一個段中返回正確的數字或行也很重要。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
BOOL expanded = [_sectionStates[section] boolValue];
return expanded ? [_foldersArray[section - 1][@"folders"] count] : 0;
}
因爲這是完全正確的,所以我不打算在這裏說任何與公認的答案相抵觸的東西。但是,我將詳細討論如何實現這一點。如果您不想閱讀所有這些內容,並且更願意在工作項目中使用源代碼,則我已上傳example project to GitHub。
其基本思想是在方法-tableView: heightForRowAtIndexPath:
內部有一個條件,用於確定當前單元格是否應該展開。這將通過在-tableView: didSelectRowAtIndexPath:
之內調用表格上的開始/結束更新來觸發。在本例中,我將演示如何製作允許一次擴展一個單元格的表格視圖。
您需要做的第一件事是聲明對NSIndexPath對象的引用。不過你想要的,你可以這樣做,但我建議使用這樣的屬性聲明:
@property (strong, nonatomic) NSIndexPath *expandedIndexPath;
注:你並不需要創建裏面viewDidLoad中該指數的路徑,或者其他類似方法。索引最初爲零的事實只意味着表格最初不會有擴大的行。如果你寧願表具有擴展您所選擇的一排開始,您可以添加這樣的事情您的viewDidLoad方法:
NSInteger row = 1;
NSInteger section = 2;
self.expandedIndexPath = [NSIndexPath indexPathForRow:row inSection:section];
的下一步是頭頂到您的UITableViewDelegate方法-tableView: didSelectRowAtIndexPath:
添加基於用戶選擇來改變擴展的小區索引的邏輯。這裏的想法是檢查剛纔選擇的索引路徑是否存儲在expandedIndexPath
變量中的索引路徑中。如果兩者匹配,那麼我們知道用戶正試圖取消選擇擴展單元,在這種情況下,我們將該變量設置爲零。否則,我們將expandedIndexPath
變量設置爲剛剛選擇的索引。這一切都在beginUpdates/endUpdates調用之間完成,以允許表視圖自動處理過渡動畫。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates]; // tell the table you're about to start making changes
// If the index path of the currently expanded cell is the same as the index that
// has just been tapped set the expanded index to nil so that there aren't any
// expanded cells, otherwise, set the expanded index to the index that has just
// been selected.
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
self.expandedIndexPath = nil;
} else {
self.expandedIndexPath = indexPath;
}
[tableView endUpdates]; // tell the table you're done making your changes
}
然後,最後一步是在另一個UITableViewDelegate方法-tableView: heightForRowAtIndexPath:
。此方法將在您爲表確定需要更新的每個索引路徑觸發beginUpdates
後調用。這是您將比較expandedIndexPath
與當前正在重新評估的索引路徑的位置。
如果兩個索引路徑相同,那麼這是您希望展開的單元格,否則它的高度應該是正常的。我使用了100和44的值,但你可以使用任何適合你需要的東西。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Compares the index path for the current cell to the index path stored in the expanded
// index path variable. If the two match, return a height of 100 points, otherwise return
// a height of 44 points.
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
return 100.0; // Expanded height
}
return 44.0; // Normal height
}
我爲此創建了一個開源庫。您只需在您的代碼中實施摺疊並展開代表,然後在代碼中輸入即可!!你也可以執行任何繪圖和動畫。退房this。
項目可以改進,如果你subview而不是使用viewWithTag的tableview單元格 – SleepsOnNewspapers 2015-06-03 01:21:23
initialize iSelectedIndex = -1; and declare
UITableView *urTableView;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 10; //Section count
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3; //row count
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell.textLabel setText:[NSString stringWithFormat:@"sec:%d,row:%d",indexPath.section,indexPath.row]];
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
// adding a label with the tap gesture to the header in each section
headerLabel = [[UILabel alloc]init];
headerLabel.tag = section;
headerLabel.userInteractionEnabled = YES;
headerLabel.backgroundColor = [UIColor greenColor];
headerLabel.text = [NSString stringWithFormat:@"Header No.%d",section];
headerLabel.frame = CGRectMake(0, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(gestureTapped:)];
[headerLabel addGestureRecognizer:tapGesture];
return headerLabel;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 50.0; //adjust the height as you need
}
- (void)gestureTapped:(UITapGestureRecognizer *)sender{
UIView *theSuperview = self.view; // whatever view contains
CGPoint touchPointInSuperview = [sender locationInView:theSuperview];
UIView *touchedView = [theSuperview hitTest:touchPointInSuperview withEvent:nil];
if([touchedView isKindOfClass:[UILabel class]])
{
if (iSelectedIndex != touchedView.tag) { //if new header is selected , need to expand
iSelectedIndex = touchedView.tag;
}else{ // if the header is already expanded , need to collapse
iSelectedIndex = -1;
}
[urTableView beginUpdates];
[urTableView endUpdates];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Show or hide cell
float height = 0.0;
if (indexPath.section == iSelectedIndex) {
height = 44.0; // Show the cell - adjust the height as you need
}
return height;
}
而不是使用[tableView beginUpdates]
和[tableView endUpdates]
的,我使用的是didSelectRowAtIndexPath
方法裏面[tableView reloadRowsAtIndexPath:... withRowAnimation:...]
方法。
我更喜歡這個,因爲當我展開我的UITableViewCell
時,當我使用開始&末端更新方法時,我有一些應該顯示的元素的問題。另一點是,你可以像一些動畫之間進行選擇:上,下,左,右......
爲了增加爲0x7FFFFFFF的答案,我發現我需要一個額外的條件if語句didSelectRowAtIndexPath方法內 - 因此:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates];
if (self.expandedIndexPath && [indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
self.expandedIndexPath = nil;
} else {
self.expandedIndexPath = indexPath;
}
[tableView endUpdates];
}
這是米克的答案,但對於斯威夫特4.(IndexPath取代NSIndexPath,它配備了一個空IndexPath爲無會崩潰斯威夫特此外,比較方法是現在不同了。您不能再使用NSOrderedSame)
聲明expandedIndexPath屬性。
var expandedIndexPath = IndexPath()
可選的viewDidLoad部分。
expandedIndexPath = IndexPath(row: 1, section: 2)
然後didSelectRow部分。
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.beginUpdates()
if indexPath.compare(expandedIndexPath) == .orderedSame {
expandedIndexPath = IndexPath()
} else {
expandedIndexPath = indexPath
}
tableView.endUpdates()
}
然後是heightForRow部分。
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.compare(expandedIndexPath) == .orderedSame {
return 100
}
return 44
}
注意:如果你想擴展區域包含新的可點擊的細胞(行)(而不僅僅是擴大爲單擊的單元格的空間),參見[gcamp的答案](http://stackoverflow.com/a/ 199364分之7253288)。它開始於一組關閉的*部分*;點擊部分標題打開該部分,顯示其單元格。 – ToolmakerSteve 2017-03-12 01:30:00