Swift - 显示带有动画的标题

Posted

技术标签:

【中文标题】Swift - 显示带有动画的标题【英文标题】:Swift - Display header with animation 【发布时间】:2019-07-11 15:15:34 【问题描述】:

我对 Swift 编码有点陌生,我想通过寻找一些布局来训练自己并尝试使用 AutoLayout 来实现它们。

这是我尝试实现的屏幕截图

https://i.imgur.com/9yzvnzp.png

这里想要的行为是在滚动图片时应该消失并且标题应该这样设置

https://i.imgur.com/bLhyTGs.png

有人可以帮我解决这个问题吗? 我应该使用 ScrollView 吗?界面视图? UICollectionView ?

【问题讨论】:

【参考方案1】:

我实际上正在开发一个做类似事情的应用程序。

所以,您要做的第一件事是为背景创建一个UIView,即显示 Squirtle 的蓝色部分。这个视图可以占据整个视图控制器。通过IBOutlet 将其连接到您的UIViewController 并调用它backgroundView

接下来,我们要在backgroundView 上放置一个UIScrollView。这个滚动视图应该被限制在超级视图的顶部、底部、前导和后沿,以便它覆盖整个视图控制器的框架。通过IBOutlet 将此UIScrollView 连接到您的UIViewController 并将其命名为scrollView。另外,确保scrollViewbackgroundColor 设置为clear。这样,我们就可以在scrollView 下方看到backgroundView

在您的UIViewController 中,您需要将scrollView 的委托设置为self 内部viewDidLoad。您的 UIViewController 的代码现在应该如下所示:

class SquirtleViewController: UIViewController 
    @IBOutlet var backgroundView: UIView!
    @IBOutlet var scrollView: UIScrollView!

    override func viewDidLoad() 
        super.viewDidLoad()
        scrollView.delegate = self
    


extension SquirtleViewController: UIScrollViewDelegate 


稍后我们将为scrollView 设置委托方法。这些将帮助我们知道滚动视图何时开始滚动到 SquirtleViewController 的顶部。

现在,我们的scrollView 具有清晰的背景,实际上并没有向我们的用户显示任何内容。这就是我们现在想要的。我们希望scrollView 的顶部清晰,以便我们可以看到它后面的backgroundView,而scrollView 的底部有另一个视图,即显示STATS、@987654351 的“内容视图” @、MOVESHP

所以,让我们添加另一个UIView 作为scrollView 的子视图。通过IBOutlet 将其连接到SquirtleViewController 并将其命名为contentView

现在,我们需要在contentView 的上边缘和scrollView 的上边缘之间创建一个约束。这个约束的常数需要等于backgroundView 的内容的高度。这样,我们的contentView 就不会掩盖我们想从backgroundView 看到的内容。我们还应该将此高度保存为backgroundViewContentHeight,以便我们以后可以引用它。

我们还需要contentViewleadingtrailingbottom 约束等于其父视图的约束,即scrollView。这些不需要通过IBOutlets 连接。

另外,给contentView 一个heightwidth 约束,并将它们分别作为contentViewHeightcontentViewWidth 通过IBOutlet 连接到SquirtleViewController。这将有助于我们稍后设置scrollViewcontentSize

您的代码现在应该如下所示:

class SquirtleViewController: UIViewController 
    @IBOutlet var backgroundView: UIView!
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var contentView: UIView!

    //New lines of code
    //Our constraints
    @IBOutlet var contentViewTop: NSLayoutConstraint!
    @IBOutlet var contentViewHeight: NSLayoutConstraint!
    @IBOutlet var contentViewWidth: NSLayoutConstraint!

    var backgroundViewContentHeight = 400

    override func viewDidLoad() 
        super.viewDidLoad()
        scrollView.delegate = self
    


extension SquirtleViewController: UIScrollViewDelegate 


现在,当SquirtleViewController 布置其子视图时,我们将要设置contentViewHeightcontentViewWidthconstant 属性。这将为我们的scrollView 设置一个contentSize。我们希望contentViewWidth 的大小与SquirtleViewControllerview 的宽度相同。我们的contentViewHeightconstant 会有点不同,因为它取决于我们contentView 的子视图的高度。对于这个例子,我们会说 contentViewHeightconstant 应该是 1200。代码现在应该是这样的:

class SquirtleViewController: UIViewController 
    @IBOutlet var backgroundView: UIView!
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var contentView: UIView!

    //Our constraints
    @IBOutlet var contentViewTop: NSLayoutConstraint!
    @IBOutlet var contentViewHeight: NSLayoutConstraint!
    @IBOutlet var contentViewWidth: NSLayoutConstraint!

    var backgroundViewContentHeight = 400

    override func viewDidLoad() 
        super.viewDidLoad()
        scrollView.delegate = self
    

    //New lines of code
    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        contentViewWidth.constant = view.frame.width
        contentViewHeight.constant = 1200
    


extension SquirtleViewController: UIScrollViewDelegate 


从这里,您可以根据需要向backgroundViewcontentView 添加子视图,以显示口袋妖怪 (backgroundView) 以及口袋妖怪的统计数据 (contentView)。但是,您仍然需要知道如何根据我们滚动scrollView 的次数来更改backgroundView 的内容。这就是UIScrollViewDelegate 帮助我们的地方。

UIScrollViewDelegate 中有一个方法,每次我们的scrollViewcontentOffset.y 更改时都会调用该方法。这基本上意味着每次我们更改 scrollView 的滚动量时,都会调用此方法。

在这个方法中,我们可以交叉引用我们滚动的量和背景视图的高度。当我们的scrollViewcontentOffset.y 接近我们backgroundView 的内容的高度时,我们可以淡出Squirtle 的图像并淡入简单地说“Squirtle”的UILabel(就像在你的例子中一样)。

因此,在您的情况下,我建议将 Squirtle 的 UIImage 添加为 contentView 的子视图,并通过 IBOutlet 将其连接为 pokemonImageViewpokemonImageView 的框架应部分位于 contentView 之外(如您的示例中所示)。如果这样做,请确保 contentViewclipsToBounds 属性设置为 false

我还将添加一个UILabel 作为backgroundView 的子视图,并通过IBOutlet 作为pokemonNameLabel 将其连接到SquirtleViewController。当我们的SquirtleViewController 的视图加载时,我们应该将pokemonNameLabel.alpha 设置为零,以便它最初是隐藏的。

您的代码现在应该如下所示:

class SquirtleViewController: UIViewController 
    @IBOutlet var backgroundView: UIView!

    //New line of code
    @IBOutlet var pokemonNameLabel: UILabel!
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var contentView: UIView!

    //New line of code
    @IBOutlet var pokemonImageView: UIImageView!

    //Our constraints
    @IBOutlet var contentViewTop: NSLayoutConstraint!
    @IBOutlet var contentViewHeight: NSLayoutConstraint!
    @IBOutlet var contentViewWidth: NSLayoutConstraint!

    var backgroundViewContentHeight = 400

    override func viewDidLoad() 
        super.viewDidLoad()
        scrollView.delegate = self

        //New line of code
        pokemonNameLabel.alpha = 0
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        contentViewWidth.constant = view.frame.width
        contentViewHeight.constant = 1200
    


extension SquirtleViewController: UIScrollViewDelegate 


现在我们只需在类扩展中添加scrollViewDidScroll 方法。这是告诉我们scrollViewcontentOffset.y 属性的方法,以便我们知道我们滚动了多少。随着这个数字的增加,我们的pokemonImageView 的 alpha 应该减少到零,我们的pokemonNameLabel 的 alpha 应该增加到 1。

在这个方法中,我将scrollView.contentOffset.y 除以backgroundView 的高度减去pokemonNameLabel 的高度。然后我们可以使用这个小数来设置我们各自的 alphas pokemonImageViewpokemonNameLabel

您的代码现在应该如下所示:

class SquirtleViewController: UIViewController 
    @IBOutlet var backgroundView: UIView!

    //New line of code
    @IBOutlet var pokemonNameLabel: UILabel!
    @IBOutlet var scrollView: UIScrollView!
    @IBOutlet var contentView: UIView!

    //New line of code
    @IBOutlet var pokemonImageView: UIImageView!

    //Our constraints
    @IBOutlet var contentViewTop: NSLayoutConstraint!
    @IBOutlet var contentViewHeight: NSLayoutConstraint!
    @IBOutlet var contentViewWidth: NSLayoutConstraint!

    var backgroundViewContentHeight = 400

    override func viewDidLoad() 
        super.viewDidLoad()
        scrollView.delegate = self

        //New line of code
        pokemonNameLabel.alpha = 0
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        contentViewWidth.constant = view.frame.width
        contentViewHeight.constant = 1200
    


extension SquirtleViewController: UIScrollViewDelegate 
    func scrollViewDidScroll(_ scrollView: UIScrollView) 
        //Subtracting contentView.frame.height from scrollView.frame.height
        let alphaDecimal = scrollView.contentOffset.y / (backgroundViewContentHeight - pokemonNameLabel.frame.height)
        pokemonNameLabel.alpha = alphaDecimal
        pokemonImageView.alpha = 1 - alphaDecimal
    

现在,当我们向上滚动并且可以看到 backgroundView 缩小时,我们的 pokemonImageView 将淡出,而我们的 pokemonNameLabel 将淡入。在两者之间会有一个点0.5的阿尔法。您可以随意使用此 scrollViewDidScroll 方法,以使其最适合您。

【讨论】:

@ImadBenAbdeslam 让我知道它是怎么回事。我知道它有很多内容,我试图让它尽可能清楚

以上是关于Swift - 显示带有动画的标题的主要内容,如果未能解决你的问题,请参考以下文章

(Swift)如何通过重新加载 UITableView 根据 UITextfield 输入(动画)显示/隐藏单元格?

如何在 Swift 3 中加载/删除带有动画的自定义视图

带有约束的 UIViewAnimation 在 Swift 中不起作用

如何检查单元格是不是已显示 Swift

加载动画仅在按钮功能后显示(Swift)

按下按钮时 UITableView 标题视图的动画显示(swift)