过渡导航栏标题

10
在名为“Luvocracy”的应用程序中,当用户向上滑动屏幕时,导航栏的标题会更改。旧的标题被推上去,而新的标题则过渡进来。我现在没有视频,但是这里有一些屏幕截图:https://www.dropbox.com/s/sns0bsxkdv7pw3l/Photo%20Apr%2008%2C%2011%2001%2005%20AM.pnghttps://www.dropbox.com/s/ys9a49u3dyxrlcm/Photo%20Apr%2008%2C%2011%2001%2009%20AM.pnghttps://www.dropbox.com/s/dlcfvfvqqov3ag7/Photo%20Apr%2008%2C%2011%2001%2013%20AM.png。如何像所示那样动画或过渡出新的导航栏标题?编辑:该应用程序已不再在应用商店上提供,因此我无法上传此操作的视频。

我猜他们在导航栏中有一个自定义视图,在其中执行动画。 - rckoenes
我该如何着手做这件事? - Jacob
你尝试过什么?听起来你是在要求代码,请尝试自己解决问题。 - rckoenes
抱歉,我还没有真正尝试过任何东西。我知道如何将自定义视图添加到导航栏,但是当我滚动到视图顶部时,如何“推”上新标题呢? - Jacob
4个回答

29
您可以通过使用CATransition来动画更改标题... 但是,由于标题本身是导航栏上的私有属性,因此您需要首先创建自定义标签并将其附加到导航项。
设置标题标签(这将覆盖默认导航栏的标题):
UILabel *titleLabelView = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 44.0f) /* auto-sized anyway */];
titleLabelView.backgroundColor = [UIColor clearColor];
titleLabelView.textAlignment = NSTextAlignmentCenter;
titleLabelView.textColor = [UIColor blackColor];
titleLabelView.font = [UIFont systemFontOfSize:16.0f];
titleLabelView.adjustsFontSizeToFitWidth = YES;
titleLabelView.text = @"@cracy123";
self.navigationItem.titleView = titleLabelView;

假设您想在滚动视图委托操作上更改标题时进行动画处理,那么只需添加CAAnimation层即可:

CATransition *animation = [CATransition animation];
animation.duration = 1.0;
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromTop;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.navigationItem.titleView.layer addAnimation:animation forKey:@"changeTitle"];

((UILabel*)self.navigationItem.titleView).text = @"JACOB K";

你显然可以更改CATransition动画属性来获得你想要的效果,但这些属性会给你带来“推上去”的效果。

输入图像说明


谢谢您的快速回复!我想要应用它的方式是,我有一个带有“标题”的表视图,其上方是我的游戏标志。当我向上滚动表视图时,我希望这个图像向上移动并变小,并最终移动到导航栏的标题视图中。这可能吗? - Jacob
理论上你可以这样做,但是要将视图动画到正确的位置会非常麻烦(不是不可能,但是你需要为每个滚动事件移动1像素的框架,如果这有意义的话)。你最好复制一个UINavigationBar样式(即不是实际的导航栏)到UITableView头部,然后你就能更容易地控制tableview头部高度/标签。 - Gavin Bunney
我可以将图像作为表头,当图像滚动到导航栏下方时,它会向上滑动到标题视图中,就像您在上面展示的动画一样吗? - Jacob
那可能行得通 - 在野外有一些类似的TableView子类,可以做到人们所谓的视差效果(即使它在技术上并不是“视差”)- 这将让你完成50%的工作 - https://github.com/pyro2927/ParallaxBlur - Gavin Bunney
可以的。你需要一个scrollView代理方法来跟踪tableView的滚动,当你达到阈值时,开始调整tableView header frame的大小(缩小),然后当你达到另一个阈值时,开始让导航栏头部的图像出现(就像我发布的示例使用UILabel一样,你也可以使用UIImageView或任何UIView子类)。 - Gavin Bunney
显示剩余2条评论

7

由于缺少 Swift 的答案,这里提供 Gavin 答案的 Swift 实现:

设置自定义标题标签:

let titleLabelView = UILabel.init(frame: CGRect(x: 0, y: 0, width: 0, height: 44))
titleLabelView.backgroundColor = UIColor.clearColor()
titleLabelView.textAlignment = .Center
// this next line picks up the UINavBar tint color instead of fixing it to a particular one as in Gavin's solution
titleLabelView.textColor = UINavigationBar.appearance().tintColor
titleLabelView.font = UIFont.boldSystemFontOfSize(16.0)
titleLabelView.text = "Old Title"
self.navigationItem.titleView = titleLabelView

以下是标题动画代码:

let titleAnimation = CATransition()
titleAnimation.duration = 0.5
titleAnimation.type = kCATransitionPush
titleAnimation.subtype = kCATransitionFromTop
titleAnimation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)

navigationItem.titleView!.layer.addAnimation(titleAnimation, forKey: "changeTitle")
(navigationItem.titleView as! UILabel).text = "New Title"

// I added this to autosize the title after setting new text
(navigationItem.titleView as! UILabel).sizeToFit()

5
这是一个很好的答案,但需要做一些调整才能正确实现。 基本思路是在scrollView中间放置一段文本,当用户向上滚动超过该文本时,该文本将成为新标题。此外,当您向下滚动时,它将更改回默认标题。

enter image description here

enter image description here

所以,使用Gix发布的代码,现在已经转换为Swift 3,下面是如何完成它。

将这些变量添加到您的viewController的顶部

var didChangeTitle = false
let defaultTitle = "Default Title"
let animateUp: CATransition = {
    let animation = CATransition()
    animation.duration = 0.5
    animation.type = kCATransitionPush
    animation.subtype = kCATransitionFromTop
    animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
    return animation
}()
let animateDown: CATransition = {
    let animation = CATransition()
    animation.duration = 0.5
    animation.type = kCATransitionPush
    animation.subtype = kCATransitionFromBottom
    animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
    return animation
}()

在您的viewDidLoad中,添加以下代码来设置默认标题。
let titleLabelView = UILabel.init(frame: CGRect(x: 0, y: 0, width: 200, height: 44))
titleLabelView.backgroundColor = .clear
titleLabelView.textAlignment = .center
titleLabelView.textColor = UINavigationBar.appearance().tintColor
titleLabelView.font = UIFont.boldSystemFont(ofSize: 16)
titleLabelView.text = defaultTitle
self.navigationItem.titleView = titleLabelView

现在您需要在scrollView代理函数中添加一些代码:
extension MyViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y >= (labelName.frame.origin.y + labelName.frame.height) && !didChangeTitle {
            if let label = navigationItem.titleView as? UILabel {
                label.layer.add(animateUp, forKey: "changeTitle")
                label.text = labelName.text
            }
            didChangeTitle = true
        } else if scrollView.contentOffset.y < labelName.frame.origin.y && didChangeTitle {
            if let label = navigationItem.titleView as? UILabel {
                label.layer.add(animateDown, forKey: "changeTitle")
                label.text = defaultTitle
            }
            didChangeTitle = false
        }
    }
}

“labelName”变量是滚动视图中包含您未来标题的标签。

1

This is an example:

UILabel *titleLabelView = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f) /* auto-sized anyway */];
titleLabelView.backgroundColor = [UIColor clearColor];
titleLabelView.textAlignment = NSTextAlignmentCenter;

(和其他应用程序)
self.navigationItem.titleView = LabelView;

我不太明白你的问题!

(保留HTML)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接