【问题标题】:Is there a way to animate changing a UILabel's textAlignment?有没有办法动画更改 UILabel 的 textAlignment?
【发布时间】:2013-10-15 14:24:48
【问题描述】:

我使用的是 iOS 7,我试图将一个居中的标签移动到我的视图左侧。目前,我正在尝试通过更改 UILabel 的对齐方式来做到这一点,并且我正在尝试在此过程中对其进行动画处理。我目前正在拨打以下电话:

[UIView animateWithDuration:0.5
                 animations:^{
                      self.monthLabel.textAlignment = NSTextAlignmentLeft;
                 } completion:nil];

但这只是将标签跳转到新的对齐方式。有没有办法对此进行动画处理,或者有更好的方法来调整标签以实现这一点?

【问题讨论】:

    标签: ios uiviewanimation


    【解决方案1】:

    将 UILabel 框架大小设置为完全包含文本并将 UILabel 在您的视图中居中。

    self.monthLabel.text = @"February";
    [self.monthLabel sizeToFit];
    self.monthLabel.center = parentView.center; // You may need to adjust the y position
    

    然后设置不影响布局的对齐方式,因为不会有多余的空间。

    self.monthLabel.textAlignment = NSTextAlignmentLeft;
    

    接下来,为 UILabel 帧大小设置动画,使其滑过您想要的位置。

    [UIView animateWithDuration:0.5
                 animations:^{
                      CGRect frame = self.monthLabel.frame;
                      frame.origin.x = 10;
                      self.monthLabel.frame = frame;
                 } completion:nil];
    

    【讨论】:

    • 我无法将框架设置为标签的确切大小,因为文本会发生变化,特别是不同月份的名称
    • 在设置文本的同时更新标签框架。我更新了答案以显示如何做到这一点。
    • @bbarnhart 如果标签中有 2 行文本怎么办?比这不起作用...
    【解决方案2】:

    你的标签是多行的吗?像这样的动画:http://img62.imageshack.us/img62/9693/t7hx.png?

    如果是这样,那么有几个选择。

    多行标签

    选项 1:

    尝试使用 UIView 过渡,而不是传统的 UIView 动画。文本不会向左滑动,而是会很好地淡出到新位置。

    [UIView transitionWithView:self.monthLabel
                          duration:0.5
                           options:UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{
            self.monthLabel.textAlignment = NSTextAlignmentLeft;
        } completion:NO];
    

    选项 2:

    您可以手动确定新行将出现的位置,然后为每行文本创建一个单独的 UILabel,然后为框架设置动画。这显然需要更多的工作,但会提供所需的幻灯片动画。

    单行标签

    不要为 textAlignment 设置动画,而是使用 [self.monthLabel sizeToFit] 使标签与其包含的字符串大小相同,然后手动计算框架和居中。然后只需为框架设置动画,与多行标签上的选项 2 相同。

    【讨论】:

      【解决方案3】:

      您可以为 FRAME 设置动画,而不是 textAlignment。

      如果您想摆脱框架上的任何“填充”,请在标签上执行 [UILabel sizeToFit],然后您可以在动画块中为框架设置动画以根据需要移动它

      CGRect frameLabel = self.monthLabel.frame;
      
      [UIView animateWithDuration:0.5
                       animations:^{
                            frameLabel.origin.x -= 100;          // e.g. move it left by 100
                            self.monthLabel.frame = frameLabel;
                       } completion:nil];
      

      【讨论】:

      • 我喜欢这种方法!我确实需要让我的标签居中(现在它在日历集合视图上方显示一个月的名称)所以我会玩这个并最初设置标签的中心而不是尝试使用 textAlignment
      • 如果你想在块动画中设置变量“frameLabel”,你需要设置具有访问前缀“__block CGRect frameLabel”的变量...,因为你将在块中更改值变量frameLabel。跨度>
      【解决方案4】:

      您只需要为您的标签框架设置动画。 由于这里有完成块,您应该再次更改框架。让循环继续下去。

      [UIView animateWithDuration:0.5
                       animations:^{
                            // Change the frame
                       } completion:^{[UIView animateWithDuration:0.5
                       animations:^{
                            // Change the frame
                       } completion:^{
                           // repeat the proccess
      }]
      
      }];
      

      【讨论】:

      • 我愿意,但我在标签的任一侧都有填充,因为我的文本会根据用户选择的月份而改变。
      【解决方案5】:

      这对我很有帮助

      import Foundation
      import UIKit
      
      
      class AnimatableMultilineLabel: UIView {
      
          enum Alignment {
              case left
              case right
          }
      
          public var textAlignment: Alignment = .left {
              didSet {
                  layout()
              }
          }
      
          public var font: UIFont? = nil {
              didSet {
                  setNeedsLayout()
              }
          }
      
          public var textColor: UIColor? = nil {
              didSet {
                  setNeedsLayout()
              }
          }
      
          public var lines: [String] = [] {
              didSet {
                  for label in labels {
                      label.removeFromSuperview()
                  }
                  labels = []
                  setNeedsLayout()
              }
          }
      
          private var labels: [UILabel] = []
      
          override init(frame: CGRect) {
              super.init(frame: frame)
              setup()
          }
      
          required init?(coder aDecoder: NSCoder) {
              super.init(coder: aDecoder)
              setup()
          }
      
          private func setup() {
              isUserInteractionEnabled = false
          }
      
          override func layoutSubviews() {
              super.layoutSubviews()
      
              layout()
          }
      
          private func layout() {
      
              autocreateLabels()
      
              var yPosition: CGFloat = 0.0
              for label in labels {
                  let size = label.sizeThatFits(bounds.size)
                  let minX = textAlignment == .left ? 0.0 : bounds.width - size.width
                  let frame = CGRect(x: minX, y: yPosition, width: size.width, height: size.height)
                  label.frame = frame
                  yPosition = frame.maxY
              }
          }
      
          private func autocreateLabels() {
              if labels.count != lines.count {
                  for text in lines {
                      let label = UILabel()
                      label.font = font
                      label.textColor = textColor
                      label.text = text
                      addSubview(label)
                      labels.append(label)
                  }
              }
          }
      
          override func sizeThatFits(_ size: CGSize) -> CGSize {
              autocreateLabels()
      
              var height: CGFloat = 0.0
              for label in labels {
                  height = label.sizeThatFits(size).height
              }
              return CGSize(width: size.width, height: height)
          }
      }
      

      那你应该可以

      UIView.animate(withDuration: 0.5, animations: {
          multilineLabel.textAlignment = .right
      })
      

      【讨论】:

      • 有趣。您如何决定拆分哪些行?
      • 所有行都没有中断,所以我事先知道我可以这样声明。更聪明的解决方案是使用属性字符串并自动为换行符设置动画。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 1970-01-01
      • 2020-01-19
      • 2020-02-22
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多