使用HVTableView动态展开tableView中的cell

效果:

源码:

HVTableView.h 与 HVTableView.m

//
//  HVTableView.h
//  HRVTableView
//
//  Created by Hamidreza Vakilian on 25/11/2013
//  Copyright (c) 2013 Hamidreza Vakilian. All rights reserved.
//  Website: http://www.infracyber.com/
//  Email:   [email protected]
//

//
//***************    HVTableView - UITableView with expand/collapse feature   *****************************
//                    by hamidreza vakilian
//
//
//    This is a subclass of UITableView with expand/collapse feature that may come so handy in many apps.
//    The developer can save a lot of time using an expand/collapse tableView instead of creating a detail viewController for
//        every cell. I mean the details of each cell can be displayed immediately on the same table without switching to
//        another view. On the other hand in my opinion it far more impressive and eye-catching from a regular user‘s view.
//
//        To create an instance of HVTableView you go by code.
//      (currently I you can‘t do it from xib - I will work on that later)
//        That‘s simple as:
//
//            HVTableView* myTable = [[HVTableView alloc] initWithFrame:CGRectMake(84, 250, 600, 600) expandOnlyOneCell:NO enableAutoScroll:YES];
//            myTable.HVTableViewDelegate = self;
//            myTable.HVTableViewDataSource = self;
//            [myTable reloadData];
//            [self.view addSubview:myTable];

//    Two important parameters when initializing the HVTableView
//        if expandOnlyOneCell==TRUE: Just one cell will be expanded at a time.
//        if expandOnlyOneCell==FALSE: multiple cells can be expanded at a time
//
//        if enableAutoScroll==TRUE: when the user touches a cell, the HVTableView will automatically scroll to it
//        if enableAutoScroll==FALSE: when the user touches a cell, the HVTableView won‘t scroll. but the if the cell was close to the bottom of the table; the lower part of it may go invisible because it grows
//
//
//    Your viewController must conform to HVTableViewDelegate, HVTableViewDataSource protocols. Just like the regular
//            UITableView
//
//    Like before you implement these familiar delegate functions:
//        -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//        -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
//
//    I added a boolean parameter the heightForRowAtIndexPath function so you will return different values for an expanded or a collapsed cell.
//    (isExpanded==TRUE: return the size of the cell in expanded state)
//    (isExpanded==FALSE: return the size of the cell in collapsed (initial) state)
//
//        -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isexpanded
//
//
// I also added a boolean parameter to the cellForRowAtIndexPath function too. update the cell‘s content respecting it‘s state (isExpanded)
//        -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded
//
//
//    Now the interesting functions are here. Implement this function and it will be fired when a cell is going to expand. You can perform your drawings, animations, etc. in this function:
//        -(void)tableView:(UITableView *)tableView collapseCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath;
//
//  Implement this function. it will be fired when a cell is going to collapse. You can perform your drawings, animations, etc. or clearing up the cell in this function:
//        -(void)tableView:(UITableView *)tableView expandCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath;
//
// IMPORTANT NOTE: there are some delegate functions from UITableViewDelegate that I have commented their forwarding. If you need to implement those on your viewController or smth, go to HVTableView.m and uncomment those delegate functions. If you don‘t uncomment them; your delegate functions won‘t fire up.
//
//
//    This code may contain bugs. I don‘t garauntee its functionality, but use it on your own risk. I also tried to craft it with best performance, yet it can be optimized more.
//
//
//    Please don‘t hesitate to mail me your feedbacks and suggestions or a bug report. I would be very thankful of your responses.
//
//    ON THE BOTTOM LINE: I allow you to use my code in your applications with freedom in making any modifications, but if you are going to do so, or you just like it and want further updates and bug fixes please consider donating me via this url:
//    https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xerxes235%40yahoo%2ecom&lc=AE&item_name=Hamidreza%20Vakilian&item_number=HVTableView%20donation&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
//
//
//    Thanks,....
// ***************************************************************************************************************

#import <UIKit/UIKit.h>

@protocol HVTableViewDataSource <NSObject>
@required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded;
-(void)tableView:(UITableView *)tableView collapseCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath;
-(void)tableView:(UITableView *)tableView expandCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath;
@optional

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
@end

@protocol HVTableViewDelegate <NSObject>
@optional
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0, 3_0);
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(5_0);
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0);
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0);
@end

@interface HVTableView : UITableView <UITableViewDataSource, UITableViewDelegate>
{

    NSIndexPath *selectedIndexPath;
    int actionToTake;
    NSMutableArray* expandedIndexPaths;
}

@property (weak,nonatomic) id <HVTableViewDelegate> HVTableViewDelegate;
@property (weak,nonatomic) id <HVTableViewDataSource> HVTableViewDataSource;
@property (nonatomic) BOOL expandOnlyOneCell;
@property (nonatomic) BOOL enableAutoScroll;

- (id)initWithFrame:(CGRect)frame
  expandOnlyOneCell:(BOOL)expandOnlyOneCell
   enableAutoScroll:(BOOL)enableAutoScroll;

@end
//
//  HVTableView.m
//  HRVTableView
//
//  Created by Hamidreza Vakilian on 25/11/2013
//  Copyright (c) 2013 Hamidreza Vakilian. All rights reserved.
//  Website: http://www.infracyber.com/
//  Email:   [email protected]
//

#import "HVTableView.h"

@implementation HVTableView
@synthesize HVTableViewDelegate, HVTableViewDataSource;

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self) {
        self.delegate = self;
        self.dataSource = self;
        expandedIndexPaths = [NSMutableArray new];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame expandOnlyOneCell:(BOOL)expandOnlyOneCell enableAutoScroll: (BOOL)enableAutoScroll
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        _expandOnlyOneCell = expandOnlyOneCell;
        if (!_expandOnlyOneCell)
            expandedIndexPaths = [[NSMutableArray alloc] init];

        _enableAutoScroll = enableAutoScroll;

        self.delegate = self;
        self.dataSource = self;

    }
    return self;
}

//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// UITableViewDataSource Protocol Forwarding
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [HVTableViewDataSource tableView:tableView numberOfRowsInSection:section];
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [HVTableViewDataSource numberOfSectionsInTableView:tableView];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:titleForHeaderInSection:)])
        return [HVTableViewDataSource tableView:tableView titleForHeaderInSection:section];
    return nil;
}

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:titleForFooterInSection:)])
    return [HVTableViewDataSource tableView:tableView titleForFooterInSection:section];
    return nil;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:canEditRowAtIndexPath:)])
    return [HVTableViewDataSource tableView:tableView canEditRowAtIndexPath:indexPath];
    return NO;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:canMoveRowAtIndexPath:)])
        return [HVTableViewDataSource tableView:tableView canMoveRowAtIndexPath:indexPath];
    return NO;
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    if ([HVTableViewDataSource respondsToSelector:@selector(sectionIndexTitlesForTableView:)])
        return [HVTableViewDataSource sectionIndexTitlesForTableView:tableView];
    return nil;
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:sectionForSectionIndexTitle:atIndex:)])
        return [HVTableViewDataSource tableView:tableView sectionForSectionIndexTitle:title atIndex:index];
    return 0;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:commitEditingStyle:forRowAtIndexPath:)])
        return [HVTableViewDataSource tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath];
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    if ([HVTableViewDataSource respondsToSelector:@selector(tableView:moveRowAtIndexPath:toIndexPath:)])
        return [HVTableViewDataSource tableView:tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
}

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

    if (self.expandOnlyOneCell)
    {
        if (actionToTake == 0) // e.g. the first time or an expanded cell from before gets in to view
        {
            if (selectedIndexPath)
                if (selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section)
                {
                    cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:YES];//i want it expanded
                    return cell;
                }

            cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO];

            return cell; //it‘s already collapsed!
        }

        cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO];

        if(actionToTake == -1)
        {
            [HVTableViewDataSource tableView:tableView collapseCell:cell withIndexPath:indexPath];
            actionToTake = 0;
        }
        else
        {
            [HVTableViewDataSource tableView:tableView expandCell:cell withIndexPath:indexPath];
            actionToTake = 0;
        }
    }
    else
    {
        if (actionToTake == 0) // e.g. the first time or an expanded cell from before gets in to view
        {
            BOOL alreadyExpanded = NO;
            NSIndexPath* correspondingIndexPath;
            for (NSIndexPath* anIndexPath in expandedIndexPaths) {
                if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section)
                {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;}
            }

            if (alreadyExpanded)
                cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:YES];
            else
                cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO];

            return cell; //it‘s already collapsed!

        }

        cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO];

        if(actionToTake == -1)
        {
            [HVTableViewDataSource tableView:tableView collapseCell:cell withIndexPath:indexPath];
            actionToTake = 0;
        }
        else
        {
            [HVTableViewDataSource tableView:tableView expandCell:cell withIndexPath:indexPath];
            actionToTake = 0;
        }
    }

    return cell;
}

//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!!
//////// UITableViewDelegate Protocol Forwarding
//////// NOTE::::: If you want to use any of these protocols in your code; you must uncomment it. I have comment them for performance reasons
/*
 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath];
 }

 -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayHeaderView:forSection:)])
 [HVTableViewDelegate tableView:tableView willDisplayHeaderView:view forSection:section];
 }

 -(void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayFooterView:forSection:)])
 [HVTableViewDelegate tableView:tableView willDisplayFooterView:view forSection:section];
 }

 -(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingCell:forRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView didEndDisplayingCell:cell forRowAtIndexPath:indexPath];
 }

 - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingHeaderView:forSection:)])
 [HVTableViewDelegate tableView:tableView didEndDisplayingHeaderView:view forSection:section];
 }

 - (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingFooterView:forSection:)])
 [HVTableViewDelegate tableView:tableView didEndDisplayingFooterView:view forSection:section];
 }
 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)])
 return [HVTableViewDelegate tableView:tableView heightForHeaderInSection:section];
    return 0;
 }

 - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:heightForFooterInSection:)])
 return [HVTableViewDelegate tableView:tableView heightForFooterInSection:section];
    return 0;
 }

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0)
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView estimatedHeightForRowAtIndexPath:indexPath];
    return 100;
 }

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0)
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForHeaderInSection:)])
 return [HVTableViewDelegate tableView:tableView estimatedHeightForHeaderInSection:section];
    return 0;
 }

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForFooterInSection:)])
 return [HVTableViewDelegate tableView:tableView estimatedHeightForFooterInSection:section];
    return 0;
 }

 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)])
 return [HVTableViewDelegate tableView:tableView viewForHeaderInSection:section];
    return nil;
 }
 - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:viewForFooterInSection:)])
 return [HVTableViewDelegate tableView:tableView viewForFooterInSection:section];
    return nil;
 }

 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:accessoryButtonTappedForRowWithIndexPath:)])
 [HVTableViewDelegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
 }

 - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldHighlightRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView shouldHighlightRowAtIndexPath:indexPath];
    return YES;
 }
 - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didHighlightRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView didHighlightRowAtIndexPath:indexPath];
 }
 - (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didUnhighlightRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView didUnhighlightRowAtIndexPath:indexPath];
 }
 - (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView willDeselectRowAtIndexPath:indexPath];
    return nil;
 }

 - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
 }
 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView editingStyleForRowAtIndexPath:indexPath];
    return UITableViewCellEditingStyleNone;
 }
 - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath];
    return nil;
 }
 - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldIndentWhileEditingRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView shouldIndentWhileEditingRowAtIndexPath:indexPath];
    return NO;
 }
 - (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView willBeginEditingRowAtIndexPath:indexPath];
 }
 - (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)])
 [HVTableViewDelegate tableView:tableView didEndEditingRowAtIndexPath:indexPath];
 }
 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:)])
 return [HVTableViewDelegate tableView:tableView targetIndexPathForMoveFromRowAtIndexPath:sourceIndexPath toProposedIndexPath:proposedDestinationIndexPath];
    return nil;
 }
 - (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:indentationLevelForRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView indentationLevelForRowAtIndexPath:indexPath];
    return 0;
 }
 - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldShowMenuForRowAtIndexPath:)])
 return [HVTableViewDelegate tableView:tableView shouldShowMenuForRowAtIndexPath:indexPath];
    return YES;
 }
 - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:canPerformAction:forRowAtIndexPath:withSender:)])
 return [HVTableViewDelegate tableView:tableView canPerformAction:action forRowAtIndexPath:indexPath withSender:sender];
    return NO;
 }
 - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
 {
    if ([HVTableViewDelegate respondsToSelector:@selector(tableView:performAction:forRowAtIndexPath:withSender:)])
 return [HVTableViewDelegate tableView:tableView performAction:action forRowAtIndexPath:indexPath withSender:sender];
 }
 */

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.expandOnlyOneCell)
    {
        if (selectedIndexPath)
            if(selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section)
                return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:YES];

        return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:NO];
    }
    else
    {
        BOOL alreadyExpanded = NO;
        NSIndexPath* correspondingIndexPath;
        for (NSIndexPath* anIndexPath in expandedIndexPaths) {
            if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section)
            {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;}
        }
        if (alreadyExpanded)
            return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:YES];
        else
            return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:NO];
    }
}

-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 更新代理,让外面的tableView也可以使用
    if (self.HVTableViewDelegate && [self.HVTableViewDelegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
        [self.HVTableViewDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
    }

    if (self.expandOnlyOneCell)
    {
        if (selectedIndexPath)
            if (selectedIndexPath.row != -1 && selectedIndexPath.row != -2) //collapse the last expanded item (if any)
            {
                BOOL dontExpandNewCell = NO;
                if (selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section)
                    dontExpandNewCell = YES;

                NSIndexPath* tmp = [NSIndexPath indexPathForRow:selectedIndexPath.row inSection:selectedIndexPath.section];//tmp now holds the last expanded item
                selectedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];

                actionToTake = -1;

                [tableView beginUpdates];
                [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tmp] withRowAnimation:UITableViewRowAnimationAutomatic];
                [tableView endUpdates];

                if (dontExpandNewCell) return; //the same expanded cell was touched and now I collapsed it. No new cell is touched
            }

        actionToTake = 1;
        ///expand the new touched item

        selectedIndexPath = indexPath;
        [tableView beginUpdates];
        [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        [tableView endUpdates];
        if (self.enableAutoScroll)
            [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

    }
    else
    {
        BOOL alreadyExpanded = NO;
        NSIndexPath* correspondingIndexPath;
        for (NSIndexPath* anIndexPath in expandedIndexPaths) {
            if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section)
            {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;}
        }

        if (alreadyExpanded)////collapse it!
        {
            actionToTake = -1;
            [expandedIndexPaths removeObject:correspondingIndexPath];
            [tableView beginUpdates];
            [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView endUpdates];
        }
        else ///expand it!
        {
            actionToTake = 1;
            [expandedIndexPaths addObject:indexPath];
            [tableView beginUpdates];
            //            [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView endUpdates];
            if (self.enableAutoScroll)
                [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
        }
    }
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect
 {
 // Drawing code
 }
 */

@end

针对源码修改过的地方:

时间: 2024-12-18 14:26:45

使用HVTableView动态展开tableView中的cell的相关文章

动态切换tableView中的cell的种类

为什么要动态切换tableView中cell的种类呢?如果项目经理不出这种需求,你也就见不到这篇文章了:) 效果: 源码: 首先,你要准备3种cell,直接继承系统的就行了. // // RootViewController.m // ChangeCell // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import "YellowCell.h&quo

iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见

iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见 (2015-12-05 12:48:20)[编辑][删除] 转载▼     首先我们先明确一下问题: 1.因为UI是在主线程中更新的,不能在down数据的同时显示界面,这样会使得下载的时间占用主线程,导致的后果就是你的屏幕就那样的卡死在哪了 2.如果要解觉问题1,就势必要将其下载数据的环节放在其他分线程上来实现,但是这里还会遇见一个问题,分线程的执行是不会有序的,这样,在动态显示的过 程中,cell中的数据就会混乱的变

UITableView (4): 在TableView中移动cell和Section 从TableView中删除cell和section

一  .问题:你想用流畅直观的动画来移动和拖拽TableView中的cell和section 方案: 用moveSection:toSection:方法把一个Section移动到新位置. 用moveRowAtIndexPath:toIndexPath:方法把一个cell从当前位置移动到新位置 例子: 创建一个TableView并在其中加载3个Section,每个Section有3个cell #pragma - mark 初始化数据 - (NSMutableArray *)newSectionWi

转--动态改变UITableView中的Cell高度

往往在开发iPhone的应用过程中用得最多的应该算是UITableVIew了,凭着IOS给UITableView赋予了这种灵活的框架结构,让它不管在显示列表方面还是在排版方面都有着一定的优势.虽然UITableView功能强大,但是对于一些复杂的应用需求在开发的过程中会出现一些问题,如动态改变UITableView显示的Cell高度就是其中之一 其实想要改变UITableView的Cell高度并不难,UITableView带有一个rowHeight属性,使用他就可以改变高度了.但是这样的改变是把

OC TableView中自定义Cell实现文字滚动效果

需求:有一个动态需要更新的TableView,每一个Cell显示的内容从网络获取,并且Cell中有一个需要显示文字的Label,当文字太长的时候,不能完全显示,所以采用跑马灯的样式 实现:1. IB的方式(??) 2.纯代码(?) IB的层次关系 实现的功能: 1.动态获取文字的实际长度 2.设置滚动的收尾位置 代码: 1.TitleRolling.h @interface TitleRolling : UIViewController -(void) startScroll : (UIScro

解决tableView中cell动态加载控件的重用问题

tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问题,即使你能做到该cell只根据数值加载了一回控件,你也没法保证不出现重用问题:) 效果(请注意查看,移动下面的格子时,上面出现了重用的问题) 源码: YXCell.h // // YXCell.h // YXTableView // // Copyright (c) 2014年 Y.X. All rights reserved. // #import

【iOS知识学习】_iOS动态改变TableView Cell高度

在做tableView的时候,我们有时候需要根据cell的高度动态来调整,最近在网上看到一段代码不错,跟大家Share一下. 在 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 类中获取cell的高度: CGSize boundSize = CGSizeMake(216, CGFLOAT_MAX); cell.textLabel.text

如何获取tableview中当前选中的cell

当我们点击某个cell时,会执行下面这个方法,方法中调用另一方法执行具体操作: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (0 == indexPath.section) { [self btnActionForUserSetting:self]; } } 在下面方法中怎样获取刚刚选中的那个cell,并修改它的内容呢? - (void)btnAc

tableview 点击cell改变cell中的label.text的字体颜色,cell复用出现问题的解决方案2

关于Cell的复用问题,上次已经说了一种,但似乎那种方法不是最好的,所以说,今天下午根据别人提示,想到了此方法.还是老样子,可能不是最好的,但是实现了功能,至少比上次的要好一些. 题目要求:定义固定数据源,然后让tableview的行上各自显示第几行,然后点击选中的时候,字体颜色会变为红色,取消选中的时候字体变为黑色.然后最后的时候要输出选中的结果 解题思路:首先实现tableView的几个协议,然后定义一个模型,在模型中定义一个标识,然后通过点中的时候标识,然后判断标识解决Cell的复用. M