【问题标题】:Custom loading animation for UITableViewUITableView 的自定义加载动画
【发布时间】:2014-10-16 17:41:06
【问题描述】:

我正在尝试创建一个 UITableViewController,其中 tableview 上的加载动画应该使项目从侧面滑入。单元格的高度比默认单元格高,大约大 5-7 倍。我想要一个像 Google+ 加载动画这样的动画,可以在 android 上看到。 (卡片动画)。

我想是继承 TableView 类,重写一个加载方法,当它们被引入显示器时显示新项目,然后使用弹簧动画同时旋转单元格,同时它的 x 和 y 值逐渐改变.

我在this answer 中尝试过这段代码,但并没有完全发挥作用。对该答案的详细说明和解释也将非常有帮助。代码:

- (void)animate
{
[[self.tableView visibleCells] enumerateObjectsUsingBlock:^(UITableViewCell *cell, NSUInteger idx, BOOL *stop) {
    [cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
    [UIView animateWithDuration:1 animations:^{
        [cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
    }];
}];
}

任何帮助将不胜感激! 埃里克

【问题讨论】:

    标签: ios objective-c uitableview animation uiview


    【解决方案1】:

    这是一个功能齐全的示例(我相信)您所描述的内容。我打开了一个空的单视图项目,删除了情节提要中的视图控件,然后简单地创建了一个 UITableViewController 并将其类设置为我在下面创建的 UITableViewController 子类的类。

    头文件中没有添加任何内容,所以我将其排除在外

    #import "weeeTables.h"
    
    @interface weeeTables ()
    
    
    @property (nonatomic, strong) NSMutableSet *shownIndexes;
    @property (nonatomic, assign) CATransform3D initialTransform;
    
    @end
    

    shownIndexes 将包含已显示视图的索引,因此我们不会重复向上滚动的动画。 initialTransform 属性是单元格初始状态的转换(在它出现在屏幕上之前你想要它的位置)

    @implementation weeeTables
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    
    CGFloat rotationAngleDegrees = -30;
    CGFloat rotationAngleRadians = rotationAngleDegrees * (M_PI/180);
    CGPoint offsetPositioning = CGPointMake(-20, -20.0);
    
    CATransform3D transform = CATransform3DIdentity;
    transform = CATransform3DRotate(transform, rotationAngleRadians, -50.0, 0.0, 1.0);
    transform = CATransform3DTranslate(transform, offsetPositioning.x, offsetPositioning.y, -50.0);
    _initialTransform = transform;
    
    _shownIndexes = [NSMutableSet set];
    }
    

    在 ViewDidLoad 中,我们设置了初始变换的值,我对这些值进行了一些调整,并鼓励您这样做以获得您正在寻找的效果,但单元格从左下角开始动画目前。

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    return 385;
    }
    
    
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"weeCell" forIndexPath:indexPath];
    
    
    return cell;
    }
    

    上面块中的所有内容对于 UITableViewController 子类来说都是非常典型的,并且与添加动画没有特别的关系,我只是设置了一些静态数字来添加大量要滚动的单元格,这里唯一的唯一值是单元格标识符,如您所见,它有一个经过深思熟虑的名称。

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell  forRowAtIndexPath:(NSIndexPath *)indexPath
    {
    
    if (![self.shownIndexes containsObject:indexPath]) {
    
        [self.shownIndexes addObject:indexPath];
        UIView *weeeeCell = [cell contentView];
    
        weeeeCell.layer.transform = self.initialTransform;
        weeeeCell.layer.opacity = 0.8;
    
        [UIView animateWithDuration:.65 delay:0.0 usingSpringWithDamping:.85 initialSpringVelocity:.8 options:0 animations:^{
            weeeeCell.layer.transform = CATransform3DIdentity;
            weeeeCell.layer.opacity = 1;
        } completion:^(BOOL finished) {}];
    }
    }
    @end
    

    这是真正将所有内容放在一起的人,首先我们检查我们要显示的单元格是否已经在显示索引列表中,如果不是,我们添加它,然后创建一个局部变量当前单元格内容视图。

    然后将该 contentView 上的转换设置为我们的初始转换(我们在 ViewDidLoad 中设置)。这会在用户可见之前将单元格移到我们的起始位置,然后我们将该变换动画回身份变换。我也有不透明的地方,只是为了它。

    希望对你有帮助!

    【讨论】:

    • 目前在学校,今晚试试;)
    • 像魅力一样工作 :) 有什么办法可以改变这个动画吗?有没有其他选择?我看到我们设置了 CATransform3DIdentity,但我可以将其更改为其他会产生不同动画的东西吗?
    • 当然,这只是我在此示例中选择的路线,因为它具有灵活性。主要思想是一个两步过程,将单元格(或者在这种情况下,单元格内部的内容视图)放置在您想要开始动画的位置,然后将该单元格设置为动画位置。这两个步骤都将在 willDisplayCell 方法中完成。 @james_womack 的回应,这也是将单元格设置为动画位置的一种完全有效的方式。他只是将整个单元格框架移出屏幕,然后使用 UIView 动画 api 将其设置为动画。
    • 你好,我的代码有个小问题。在动画完全完成之前,我无法点击任何行。这意味着用户可能需要多次点击它——这很烦人。关于如何解决这个问题的任何想法?
    • 晚了两年,但我想这回答了你的问题@Erik,你可以使用UIViewAnimationOptionAllowUserInteraction 作为动画中的选项。希望这对某人有所帮助。
    【解决方案2】:

    我会尝试使用tableView:willDisplayCell:forRowAtIndexPath:

    您可以将 UITableViewCell 设置为初始的离屏帧,然后异步初始化该单元格的动画。

    我已经对此进行了测试,它使用 Xcode Master/Detail 模板工作

    override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
            let frame = CGRectMake(-cell.frame.size.width, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)
            cell.frame = frame
    
            UIView.animateWithDuration(1, delay: 0.1, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
                let endFrame = CGRectMake(100, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)
                cell.frame = endFrame
            }) { (foo:Bool) -> Void in
                //
            }
        }
    

    您只需要为不同的演示案例添加特殊的外壳。有时,当您再次返回视图时,或者在单元格从视图中滚动并重新打开后,将调用此方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-23
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-05
      • 2012-07-07
      相关资源
      最近更新 更多