Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate paper fold while inserting and deleting rows in a UITableView

So I am trying to simulate an origami type paper fold while adding and deleting cells much like the peek Calendar app:enter image description here

I have gotten pretty close to this functionality by subclassing the UITableView and overriding the insertRowsAtIndexPaths:withRowAnimation: and the deleteRowsAtIndexPaths:withRowAnimation:

However right now I just cant seem to get the animation looking right. Below is my current code - I would just like to help getting over this last hurdle (or maybe there is a completely different approach such as adding a tableview to a tableviewcell).

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths
              withRowAnimation:(UITableViewRowAnimation)animation
{
    [super insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    float duration = .30;
    int i = 0;
    for (NSIndexPath *indexPath in indexPaths) {
        __block UITableViewCell *cell = [super cellForRowAtIndexPath:indexPath];
        if (cell) { // If indexPath isn't visible we'll get nil here

            //even cells flip up while odd cells flip down
            if(i % 2 ==0){
                cell.layer.anchorPoint = CGPointMake(.5, 0);

                //start row off by rotating 90 degrees
                __block CATransform3D t = CATransform3DIdentity;
                t = CATransform3DTranslate(t, 0, -cell.bounds.size.height/2, 0);
                t = CATransform3DRotate(t, hn_radians(90), 1, 0, 0);
                t.m34 = -1.0/(cell.layer.bounds.size.height * 4.6666667);

                cell.layer.transform = t;


                //flip up
                [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                    t = CATransform3DIdentity;
                    t = CATransform3DTranslate(t, 0, -cell.bounds.size.height/2, 0);

                    cell.layer.transform = t;
                    NSLog(@"");
                } completion:^(BOOL finished) {
                    cell.layer.transform = CATransform3DIdentity;
                    cell.layer.anchorPoint = CGPointMake(.5, .5);
                }];



            }
            else{

                cell.contentView.layer.anchorPoint = CGPointMake(.5, 1);

                //start row off by rotating 90 degrees
                __block CATransform3D t = CATransform3DIdentity;
                t = CATransform3DTranslate(t, 0, -cell.contentView.bounds.size.height * 0.5f, 0);
                t = CATransform3DRotate(t, hn_radians(-90), 1, 0, 0);
                t.m34 = -1/500.f;

                cell.contentView.layer.transform = t;

                //flip down
                [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                    t = CATransform3DIdentity;
                    t = CATransform3DTranslate(t, 0, cell.contentView.bounds.size.height * 0.5f, 0);
                    cell.contentView.layer.transform = t;
                } completion:^(BOOL finished) {
                    //reset anchor and transform
                    cell.contentView.layer.transform = CATransform3DIdentity;
                    cell.contentView.layer.anchorPoint = CGPointMake(.5, .5);
                }];

            }
            i++;



        }

    }
}
like image 366
MweyaMutsvene Avatar asked Oct 01 '22 13:10

MweyaMutsvene


1 Answers

In the UITableViewCell.h file write this :

@property (nonatomic, assign) CGFloat  finishedHeight;
@property (nonatomic, strong) UIView *transformable1HalfView;
@property (nonatomic, strong) UIView *transformable2HalfView;

In the UITableViewCell .m file write this :

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization
        CATransform3D transform = CATransform3DIdentity;
        transform.m34 = -1/500.f;
        [self.contentView.layer setSublayerTransform:transform];

        self.transformable1HalfView = [[UIView alloc] initWithFrame:self.contentView.bounds];
        [self.transformable1HalfView.layer setAnchorPoint:CGPointMake(0.5, 0.0)];
        [self.transformable1HalfView setClipsToBounds:YES];
        [self.contentView addSubview:self.transformable1HalfView];

        self.transformable2HalfView = [[UIView alloc] initWithFrame:self.contentView.bounds];
        [self.transformable2HalfView.layer setAnchorPoint:CGPointMake(0.5, 1.0)];
        [self.transformable2HalfView setClipsToBounds:YES];
        [self.contentView addSubview:self.transformable2HalfView];
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        self.textLabel.autoresizingMask = UIViewAutoresizingNone;
        self.textLabel.backgroundColor = [UIColor clearColor];
        self.detailTextLabel.autoresizingMask = UIViewAutoresizingNone;
        self.detailTextLabel.backgroundColor = [UIColor clearColor];

    }
    return self;
}
- (void)layoutSubviews
{
    [super layoutSubviews];

    CGFloat fraction = (self.frame.size.height / self.finishedHeight);
    fraction = MAX(MIN(1, fraction), 0);

    CGFloat angle = (M_PI / 2) - asinf(fraction);
    CATransform3D transform = CATransform3DMakeRotation(angle, -1, 0, 0);
    [self.transformable1HalfView.layer setTransform:transform];
    [self.transformable2HalfView.layer setTransform:CATransform3DMakeRotation(angle, 1, 0, 0)];


    CGSize contentViewSize = self.contentView.frame.size;
    CGFloat contentViewMidY = contentViewSize.height / 2;
    CGFloat labelHeight = self.finishedHeight / 2;

    // OPTIONAL: Always accomodate 1 px to the top label to ensure two labels 
    // won't display one px gap in between sometimes for certain angles 
    self.transformable1HalfView.frame = CGRectMake(0, contentViewMidY - (labelHeight * fraction),
                                                   contentViewSize.width, labelHeight + 1);
    self.transformable2HalfView.frame = CGRectMake(0, contentViewMidY - (labelHeight * (1 - fraction)),
                                                    contentViewSize.width, labelHeight);

    if ([self.textLabel.text length]) {
        self.detailTextLabel.text = self.textLabel.text;
        self.detailTextLabel.font = self.textLabel.font;
        self.detailTextLabel.textColor = self.textLabel.textColor;
        self.detailTextLabel.textAlignment = self.textLabel.textAlignment;
        self.detailTextLabel.textColor = [UIColor whiteColor];
        self.detailTextLabel.shadowColor = self.textLabel.shadowColor;
        self.detailTextLabel.shadowOffset = self.textLabel.shadowOffset;
    }
    self.textLabel.frame = CGRectMake(10.0, 0.0, contentViewSize.width - 20.0, self.finishedHeight);
    self.detailTextLabel.frame = CGRectMake(10.0, -self.finishedHeight / 2, contentViewSize.width - 20.0, self.finishedHeight);
}

Reference : https://github.com/jamztang/JTGestureBasedTableViewDemo

Cheers.

like image 194
try catch finally Avatar answered Oct 03 '22 02:10

try catch finally