UFO ET IT

아코디언 테이블 셀-uitableviewcell을 동적으로 확장 / 축소하는 방법은 무엇입니까?

ufoet 2020. 12. 4. 21:30
반응형

아코디언 테이블 셀-uitableviewcell을 동적으로 확장 / 축소하는 방법은 무엇입니까?


사용자가 셀을 선택하면 digg 앱이 작동하는 방식과 유사한 세부 정보보기를 인라인으로 표시하도록 확장되는 uitableviewcell의 아코디언 유형을 만들려고합니다. 처음에는 현재 tablecell을 cellForRowAtIndex의 customcell로 바꾸려고 시도했지만 셀이 교체되고 전체적으로 효과가 잘 작동하지 않는 것을 볼 수 있으므로 애니메이션이 약간 고르지 않게 보입니다.

digg 앱과 이것을 한 다른 사람들을 보면 현재 셀을 대체하지 않고 대신 셀에 하위 뷰를 추가하는 것 같습니다. 그러나 원래 셀은 전혀 애니메이션되지 않고 테이블에 새 뷰 아코디언 만 표시됩니다.

누구든지 비슷한 효과를내는 방법에 대한 아이디어가 있습니까?

업데이트 : 아래의 neha의 방법을 사용하여 약간의 진전을 보였으며 셀이 올바른 방식으로 애니메이션하는 동안 테이블의 다른 셀과 혼란을 겪고 있습니다. 내가 한 것은 실제로 뷰를 그리는 UIView의 인스턴스를 포함하는 사용자 정의 클래스가있는 하위 클래스 UITableViewCell입니다.

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

내가 사용하는 모든 테이블 대리자 메서드는 다음과 같습니다.

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

이제 셀이 확장되지만 실제로 새로 고쳐지지 않아 레이블과 텍스트 필드가 표시되지 않는 것 같습니다. 그러나 셀을 화면에서 스크롤하면 표시됩니다.

어떤 아이디어?


Apple의 방법은 매우 간단합니다.

먼저 선택한 indexPath 행을 저장해야합니다.

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

업데이트 된 시작 / 종료 부분에 대해서는 나중에 설명하겠습니다.

그런 다음 현재 선택된 인덱스가 있으면 해당 행에 더 많은 공간을 제공해야한다고 tableView에 알릴 수 있습니다.

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

선택한 셀의 높이 100을 반환합니다.

이제 시작 / 종료 업데이트로 돌아갈 수 있습니다. 해당 블록은 모든 tableView 지오메트리의 재로드를 트리거합니다. 또한 해당 블록이 애니메이션화되어 결국 행 확장의 영향을줍니다.

도움이 되었기를 바랍니다, Pawel


Pawel의 beginUpdates / endUpdates 트릭은 훌륭하며 자주 사용합니다. 그러나이 경우 상태를 변경하는 행을 다시로드하여 원하는 셀 유형으로 올바르게 다시로드하고 올바른 새 셀 높이를 반환하는지 확인하기 만하면됩니다.

다음은 달성하려는 작업을 완벽하게 구현 한 것입니다.

.h :

#import <UIKit/UIKit.h>

@interface ExpandingTableViewController : UITableViewController 
{

}

@property (retain) NSIndexPath* selectedIndexPath;

@end

.미디엄:

@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

If you don't want to reload the cell (you want to keep your existing cell and just change the size, and likely add/remove some subviews), then simply do the beginUpdates/endUpdates trick in didSelectRowAtIndexPath:, and call some method on your cell to incite the layout change. beginUpdates/endUpdates will prompt the tableView to re-query the heights for each cell - so be sure to return the correct value.


Create a class that subclasses UITableviewcell in your project. Create this class' nib and set its parent to be the class in your project with tableview and override its -

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

Write methods contractCell() and expandCell() in this class, and provide the height of the cells you want in expandCell method. Call this methods appropriately based on some flags set to identify wheather the cell is in expanded state or contracted state. Use your tableview's

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

method to handle selection of cells.


Replace your cellForRowAtIndexPath function with this one.

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

create array wof dictionary which have a key Select_sts which is 0 in start when click its change 1 accourding u change table

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

}

참고URL : https://stackoverflow.com/questions/3066167/accordion-table-cell-how-to-dynamically-expand-contract-uitableviewcell

반응형