2010-06-17 26 views
56

Tôi đang cố gắng tạo một loại accordion của uitableviewcell, khi người dùng chọn ô, nó sẽ mở rộng để hiển thị chế độ xem thông tin chi tiết nội tuyến tương tự như cách hoạt động của ứng dụng digg. Ban đầu tôi đã thử thay thế tablecell hiện tại bằng một customcell trong cellForRowAtIndex, tuy nhiên hoạt hình trông hơi bị thay đổi khi bạn có thể thấy ô được thay thế và hiệu quả tổng thể không hoạt động tốt.Tế bào bảng Accordion - Làm thế nào để tự động mở rộng/hợp đồng uitableviewcell?

Nếu bạn nhìn vào ứng dụng digg và những người khác đã làm điều này có vẻ như họ không thay thế tế bào hiện tại mà thay vào đó có lẽ thêm một subview vào tế bào? Tuy nhiên, ô ban đầu dường như không hoạt ảnh và chỉ có chế độ xem mới phù hợp với bảng.

Có ai có ý tưởng nào về cách thực hiện hiệu ứng tương tự không?

Cập nhật: Tôi đã thực hiện một số tiến bộ sử dụng phương pháp neha của dưới đây và trong khi tế bào được tạo hiệu ứng động một cách chính xác nó đang tàn phá với các tế bào khác trong bảng. Những gì tôi đã làm là subclassed UITableViewCell với một lớp tùy chỉnh trong đó có một thể hiện của một UIView mà thực sự rút ra cái nhìn mà tôi sau đó thêm vào các tế bào bảng contentview.

- (void)setSelected:(BOOL)selected animated:(BOOL)animated { 

if (selected) { 
    [self expandCell]; 
} 
} 

-(void)expandCell { 
    self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110); 
} 

Dưới đây là tất cả các phương pháp đại biểu bảng tôi đang sử dụng:

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

if (isSearching && indexPath.row == selectedIndex) { 

    static NSString *CellIdentifier = @"SearchCell"; 
    CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; 

    UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)]; 
    theText.text = @"Title Text"; 
    [cell.contentView addSubview:theText]; 


    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)]; 
    textField.borderStyle = UITextBorderStyleLine; 
    [cell.contentView addSubview:textField];   

    UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)]; 
    testLabel.text = [NSString stringWithFormat:@"Some text here"]; 
    [cell.contentView addSubview:testLabel]; 

    [theText release]; 
    [textField release]; 
    [testLabel release]; 

    return cell;   
} else { 

    static NSString *CellIdentifier = @"Cell"; 
    CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; 
    return cell; 
} 


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

[tableView deselectRowAtIndexPath:indexPath animated:NO]; 

selectedIndex = indexPath.row; 
isSearching = YES; 


[tableView beginUpdates]; 
[tableView endUpdates]; 

} 


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {   
if (isSearching && indexPath.row == selectedIndex) { 
    return 110; 
} 
return rowHeight;   
} 

Có vẻ như bây giờ mà các tế bào được mở rộng nhưng không thực sự được làm mới nên nhãn và textfield arent được hiển thị. Tuy nhiên, chúng hiển thị khi tôi di chuyển ô và tắt trên màn hình.

Bất kỳ ý tưởng nào?

+0

ai? Không tìm kiếm mã chi tiết mà chỉ là một số hướng dẫn về cách đạt được điều này? –

+0

Tại sao bạn không trả lời câu trả lời chính xác của Pawel ... Bạn không thể làm tốt hơn thế. –

Trả lời

2

Tạo lớp học phân lớp UITableviewcell trong dự án của bạn. Tạo lớp ngòi này và thiết lập mẹ của nó là lớp trong dự án của bạn với tableview và ghi đè lên nó -

(void)setSelected:(BOOL)selected animated:(BOOL)animated 

Viết phương pháp contractCell() và expandCell() trong lớp này, và cung cấp chiều cao của ô bạn muốn trong phương thức expandCell. Gọi phương thức này một cách thích hợp dựa trên một số cờ được đặt để xác định thời tiết là ô ở trạng thái mở rộng hoặc trạng thái được hợp đồng. Sử dụng chế độ xem

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

của bảng điều khiển để xử lý lựa chọn ô.

+0

neha, thx cho phản ứng của bạn. Bạn có thể xây dựng một chút về cách chính xác để đi về điều này? Tôi vẫn còn hơi bối rối về cách sử dụng phương thức setSelected:? Liệu tableCell có tự động điều chỉnh chiều cao sau khi gọi expandCell/contractCell và quan trọng hơn là nó sẽ xuất hiện như thể ô được chọn đang mở rộng và không đơn giản là nạp lại mà là vấn đề ban đầu mà tôi gặp phải? Tôi gọi reoloadRowsAtIndex trong didSelectRowAtIndex và trong khi đó làm việc bạn có thể nhìn thấy trực quan các tế bào được nạp lại, hoặc từ trên/dưới/etc. tùy thuộc vào phong cách hoạt hình được chọn. –

+0

Khi bạn tạo một lớp con phân lớp uitablviewcell, phương thức "(void) setSelected: (BOOL) được chọn hoạt ảnh: (BOOL) hoạt hình" sẽ tự động xuất hiện trong lớp được tạo rõ ràng bất cứ khi nào bạn chọn một ô trong tableview. Nó có nghĩa là để định cấu hình chế độ xem cho trạng thái ô đã chọn. Hãy chắc chắn rằng bạn cũng tạo ra một nib của lớp con uitableviewcell này và thiết lập phụ huynh của nib này làm lớp tableview của bạn. Có, điều này sẽ cung cấp cho bạn hiệu quả bạn đang mong đợi, nó sẽ hiển thị các tế bào mở rộng/ký kết hợp đồng và không tải lại. – neha

+0

hi neha, thx lần nữa để trả lời. Tôi dường như được thực hiện một số tiến bộ tuy nhiên xin xem ở trên cho những thay đổi tôi đã cố gắng và các vấn đề tôi vẫn còn có. Ngoài ra mã nào chính xác nên đi vào phương thức setSelected:? Vẫn cố gắng vấp ngã qua điều này thật không may. thx –

92

Cách Apple thực hiện khá đơn giản.

Trước tiên, bạn sẽ cần phải lưu hàng indexPath chọn:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    self.selectedRowIndex = [indexPath retain]; 
    [tableView beginUpdates]; 
    [tableView endUpdates]; 
} 

tôi sẽ giải thích bắt đầu/kết thúc cập nhật phần sau.

Sau đó, khi bạn có chỉ mục hiện được chọn, bạn có thể nói với tableView rằng nó sẽ cung cấp cho hàng đó nhiều không gian hơn.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    //check if the index actually exists 
    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) { 
     return 100; 
    } 
    return 44; 
} 

Điều này sẽ trả về chiều cao 100 cho ô đã chọn.

Bây giờ chúng ta có thể quay lại các bản cập nhật bắt đầu/kết thúc. Khối đó kích hoạt tải lại của tất cả các hình học tableView.Hơn nữa, khối đó là hoạt ảnh, mà cuối cùng cung cấp cho các impresions của hàng mở rộng.

Hy vọng điều này là hữu ích, Pawel

+0

Xin chào Pawel, đã thử điều này và hiệu ứng hoạt hình chính xác là những gì tôi đang tìm nhưng vấn đề tôi chạy vào là mã này không gọi cellForRowAtIndex vì vậy tôi không thể tìm ra cách/nơi để sửa đổi nội dung của ô mở rộng. Nó chỉ đơn giản điều chỉnh chiều cao của ô. Tôi cũng đã cố gắng để có được các tế bào trong didSelectRowAtIndex với: UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath]; và thực hiện thay đổi đối với ô và sau đó gọi beginUpdates. Trong khi điều này làm việc nó có vẻ tàn phá trên phần còn lại của bảng. Bạn có thể giải thích nơi bạn thực hiện thay đổi cho ô đã chọn để tránh điều này không? –

+5

Vì bạn đang gọi các bản cập nhật bắt đầu/kết thúc trong phương thức didSelectCellForRowAtIndexPath:, ô đã được chọn. Vì vậy, bạn có thể sử dụng phương thức setSelected: animated: trong implemenetation của ô để cấu hình nó cho trạng thái được chọn. – Pawel

+0

Xin chào, tôi đã cập nhật mã của mình ở trên để phản ánh một số thay đổi này tuy nhiên có vẻ như nếu tôi đặt mã để tạo nội dung mới như nhãn, textfield, v.v ... vào phương thức cellForRowAtIndex thì nó không hoạt động vì phương thức đó không được gọi khi bạn gọi [tableView beginUpdate] và [tableView endUpdates]. Vì vậy, tôi không chắc chắn nơi để đặt mã này và làm thế nào để sử dụng một cách chính xác phương thức setSelected:? Bất kỳ lời khuyên nào khiến tôi phát điên. –

0

Thay thế chức năng cellForRowAtIndexPath của bạn với một này.

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

    if (isSearching && indexPath.row == selectedIndex) { 

     static NSString *CellIdentifier = @"SearchCell"; 
     CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; 

     UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 
10.0, cell.contentView.bounds.size.width 
-20, 22.0)]; 
     theText.text = @"Title Text"; 
     [cell.contentView addSubview:theText]; 


     UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 
46.0, cell.contentView.bounds.size.width - 20, 40.0)]; 
     textField.borderStyle = UITextBorderStyleLine; 
     [cell.contentView addSubview:textField];   

     UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 
88.0, cell.contentView.bounds.size.width - 20, 22.0)]; 
     testLabel.text = [NSString stringWithFormat:@"Some text here"]; 
     [cell.contentView addSubview:testLabel]; 

     [theText release]; 
     [textField release]; 
     [testLabel release]; 

     return cell;   
    } else { 

     static NSString *CellIdentifier = @"Cell"; 
     CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; 
     return cell; 
    } 
    } 
5

Bắt đầu của PawUpCập nhật/kết thúcCập nhật lừa là tốt và tôi thường sử dụng nó. Nhưng trong trường hợp này, bạn chỉ cần tải lại các hàng đang thay đổi trạng thái, đảm bảo rằng bạn tải lại chúng một cách chính xác với loại ô mong muốn và bạn trả lại chiều cao ô mới chính xác.

Đây là một thực hiện làm việc tất cả những gì tôi nghĩ rằng bạn đang cố gắng để hoàn thành:

.h:

#import <UIKit/UIKit.h> 

@interface ExpandingTableViewController : UITableViewController 
{ 

} 

@property (retain) NSIndexPath* selectedIndexPath; 

@end 

.m:

@implementation ExpandingTableViewController 
@synthesize selectedIndexPath; 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    // Return the number of sections. 
    return 1; 
} 


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    // Return the number of rows in the section. 
    return 10; 
} 

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

    static NSString *CellIdentifier1 = @"Cell1"; 
    static NSString *CellIdentifier2 = @"Cell2"; 

    UITableViewCell *cell; 

    NSIndexPath* indexPathSelected = self.selectedIndexPath; 

    if (nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame) 
    { 
     cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1]; 
     if (cell == nil) { 
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease]; 
     } 

     cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row]; 
    } 
    else 
    { 
     cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2]; 
     if (cell == nil) { 
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease]; 
     } 

     cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row]; 
     cell.detailTextLabel.text = [NSString stringWithFormat: @"(expanded!)", indexPath.row]; 
    } 

    return cell; 
} 

#pragma mark - 
#pragma mark Table view delegate 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame) 
    { 
     return tableView.rowHeight * 2; 
    } 

    return tableView.rowHeight; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil]; 
    self.selectedIndexPath = indexPath; 

    [tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle]; 
} 


#pragma mark - 
#pragma mark Memory management 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (void)viewDidUnload { 
} 

- (void)dealloc { 
    [super dealloc]; 
} 

@end 

Nếu bạn không muốn tải lại ô (bạn muốn giữ ô hiện tại của mình và chỉ thay đổi kích thước và có thể thêm/xóa một số bản xem trước), sau đó chỉ cần thực hiện mẹo startUpdates/endUpdates trong didSelectRowAtIndexPath :, và gọi tôi phương pháp trên tế bào của bạn để kích động sự thay đổi bố trí. beginUpdates/endUpdates sẽ nhắc tableView truy vấn lại chiều cao cho mỗi ô - vì vậy hãy chắc chắn trả lại giá trị chính xác.

-1

tạo từ điển WoF mảng trong đó có một Select_sts then chốt đó là 0 trong khi bắt đầu nhấp thay đổi của nó 1 accourding u thay đổi bảng

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ 

    customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)]; 
    UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 
    headerLabel.backgroundColor = [UIColor clearColor]; 
    headerLabel.opaque = NO; 
    headerLabel.textColor = [UIColor blackColor]; 
    headerLabel.highlightedTextColor = [UIColor whiteColor]; 
    headerLabel.font = [UIFont boldSystemFontOfSize:16]; 
    headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0); 
    headerLabel.text=[NSString stringWithFormat: @"PNR %@",[[record objectAtIndex:section] objectForKey:@"number"]]; 
    customView.backgroundColor=[UIColor whiteColor]; 

btn_openClose.tag=section+10000; 
    btn_openClose.backgroundColor=[UIColor clearColor]; 
    // [btn_openClose setImage:[UIImage imageNamed:@"down_arrow.png"] forState:UIControlStateNormal]; 
    [btn_openClose addTarget:self action:@selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside]; 
    [customView addSubview:btn_openClose]; 

} 


- (void) collapseExpandButtonTap:(id) sender{ 
    int indexNo=[sender tag]-10000; 
// NSLog(@"total_record %@",[total_record objectAtIndex:indexNo]); 
    NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy]; 
    if([[mutDictionary objectForKey:@"Select_sts"] integerValue]==0) 
     [mutDictionary setObject:[NSNumber numberWithInt:1] forKey:@"√"]; 
    else 
     [mutDictionary setObject:[NSNumber numberWithInt:0] forKey:@"Select_sts"]; 

    [total_record replaceObjectAtIndex:indexNo withObject:mutDictionary]; 

// [table_view beginUpdates]; 
// [table_view reloadData]; 
// [table_view endUpdates]; 

    NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init]; 
    [indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>] 
    // You can add multiple indexes(sections) here. 
    [table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade]; 

} 
Các vấn đề liên quan