【问题标题】:Place a UIActivityIndicator inside a UIButton在 UIButton 中放置一个 UIActivityIndi​​cator
【发布时间】:2013-03-07 10:54:06
【问题描述】:

我知道我错过了一些愚蠢的东西,但无论如何,这是我的代码:

UIActivityIndicatorView indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.hidesWhenStopped = YES;
indicator.frame = btnLogin.frame;
indicator.center = btnLogin.center;
[self.view addSubview:indicator];
[indicator bringSubviewToFront:indicator];

这是最终结果:

http://img542.imageshack.us/img542/8172/uiactivity.png

提前谢谢你!

【问题讨论】:

    标签: ios uiactivityindicatorview


    【解决方案1】:

    我认为您缺少的概念是视图的框架(及其中心)都与其父视图相关。根据您的屏幕截图,我猜您的文本字段和按钮都在充当容器的视图中。因此,您的按钮的框架和中心与该容器视图相关,而不是与视图控制器的整体视图相关。您将相同的框架和中心分配给活动指示器,但随后将指示器添加为主视图的子视图,而不是容器视图。因此,您现在有两个视图(按钮和指示器)具有相同的框架,但该框架与两个不同的超级视图相关。

    最简单的更改就是将您的指标添加到您正在使用的容器视图中。但我建议将指示器添加为按钮的子视图,然后只需进行一些数学运算即可调整其位置。

    UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    CGFloat halfButtonHeight = btnLogin.bounds.size.height / 2;
    CGFloat buttonWidth = btnLogin.bounds.size.width;
    indicator.center = CGPointMake(buttonWidth - halfButtonHeight , halfButtonHeight);
    [btnLogin addSubview:indicator];
    [indicator startAnimating];
    

    附带说明:您在视图框架之后设置视图中心是多余的。此外,作为子视图添加的最后一个视图会自动成为前子视图。

    【讨论】:

      【解决方案2】:

      根据@Musa almatri 的回答,我创建了扩展:

      extension UIButton {
      func loadingIndicator(show show: Bool) {
          let tag = 9876
          if show {
              let indicator = UIActivityIndicatorView()
              let buttonHeight = self.bounds.size.height
              let buttonWidth = self.bounds.size.width
              indicator.center = CGPointMake(buttonWidth/2, buttonHeight/2)
              indicator.tag = tag
              self.addSubview(indicator)
              indicator.startAnimating()
          } else {
              if let indicator = self.viewWithTag(tag) as? UIActivityIndicatorView {
                  indicator.stopAnimating()
                  indicator.removeFromSuperview()
              }
          }
      }}
      

      那么你可以这样使用它:

      yourButton.loadingIndicator(show: true) //hide -> show: false
      

      【讨论】:

      • 请注意,这会将指示器置于按钮的中心。 CGPointMake(buttonWidth - halfButtonHeight , halfButtonHeight) 接受的答案放在右侧(以简单、聪明的方式,IMO)。
      • show 函数参数标签是多余的,因为它与参数名称相同。你可以写:func loadingIndicator(show: Bool).
      【解决方案3】:

      这是一个 Swift 3 版本,没有使用标签。

      import UIKit
      
      extension UIButton {
          func loadingIndicator(show: Bool) {
              if show {
                  let indicator = UIActivityIndicatorView()
                  let buttonHeight = self.bounds.size.height
                  let buttonWidth = self.bounds.size.width
                  indicator.center = CGPoint(x: buttonWidth/2, y: buttonHeight/2)
                  self.addSubview(indicator)
                  indicator.startAnimating()
              } else {
                  for view in self.subviews {
                      if let indicator = view as? UIActivityIndicatorView {
                          indicator.stopAnimating()
                          indicator.removeFromSuperview()
                      }
                  }
              }
          }
      }
      

      【讨论】:

      • 为什么这比带标签的更好?能详细点吗?
      • 使用标签会增加额外的复杂性并可能导致错误,但我并不是说标签不好。此解决方案更简单,并查找 UIActivityIndi​​catorView 本身。
      • 感谢您的解释。:)
      • 为什么不indicator.center = self.center
      【解决方案4】:

      小升级:(在superview上添加按钮)

      extension UIButton {
          func loadingIndicator(_ show: Bool) {
              let indicatorTag = 808404
              if show {
                  isEnabled = false
                  alpha = 0
                  let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
                  indicator.center = center
                  indicator.tag = indicatorTag
                  superview?.addSubview(indicator)
                  indicator.startAnimating()
              } else {
                  isEnabled = true
                  alpha = 1.0
                  if let indicator = superview?.viewWithTag(indicatorTag) as? UIActivityIndicatorView {
                      indicator.stopAnimating()
                      indicator.removeFromSuperview()
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        Swift 解决方案

        var indicator = UIActivityIndicatorView()
        var halfButtonHeight = SOME_BUTTON.bounds.size.height / 2;
        var buttonWidth = SOME_BUTTON.bounds.size.width;
        indicator.center = CGPointMake(buttonWidth - halfButtonHeight , halfButtonHeight);
        SOME_BUTTON.addSubview(indicator)
        indicator.startAnimating()
        

        并使其位于按钮的中心

        indicator.center = CGPointMake(buttonWidth/2, halfButtonHeight);
        

        或者使用优秀的库

        https://github.com/souzainf3/RNLoadingButton-Swift

        【讨论】:

        • buttonWidth - halfButtonHeight:从宽度中减去高度,似乎是错误的。然后,第一个 indicator.center 分配是无用的,因为还有第二个。最后,x是什么?
        【解决方案6】:

        我正在使用约束来使 UIButton 内的指示器居中。 改编@DanielQ 的扩展,就变成了:

        extension UIButton {
            func loadingIndicator(show: Bool) {
                let tag = 9876
                if show {
                    let indicator = UIActivityIndicatorView()
                    indicator.tag = tag
                    self.addSubview(indicator)
                    indicator.translatesAutoresizingMaskIntoConstraints = false
                    let horizontalConstraint = NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
                    let verticalConstraint = NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0)
                    self.addConstraints([horizontalConstraint, verticalConstraint])
                    indicator.startAnimating()
                } else {
                    if let indicator = self.viewWithTag(tag) as? UIActivityIndicatorView {
                        indicator.stopAnimating()
                        indicator.removeFromSuperview()
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          我从按钮中删除了标题,然后在动画完成后将其添加回来,而不是覆盖标题的指示器:

          extension UIButton {
          
          func loadingIndicator(show: Bool) {
              let tag = 9876
          
              var color: UIColor?
          
              if show {
                  color = titleColor(for: .normal)
                  let indicator = UIActivityIndicatorView()
                  let buttonHeight = self.bounds.size.height
                  let buttonWidth = self.bounds.size.width
                  indicator.center = CGPoint(x: buttonWidth/2, y: buttonHeight/2)
                  indicator.tag = tag
                  indicator.color = UIColor.white
                  setTitleColor(.clear, for: .normal)
          
                  self.addSubview(indicator)
                  indicator.startAnimating()
              } else {
                  if let indicator = self.viewWithTag(tag) as? UIActivityIndicatorView {
                      indicator.stopAnimating()
                      indicator.removeFromSuperview()
                      setTitleColor(color, for: .normal)
                  }
              }
          }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多