Ios 将UIActivityIndicator放置在UIButton内

Ios 将UIActivityIndicator放置在UIButton内,ios,uiactivityindicatorview,Ios,Uiactivityindicatorview,我知道我遗漏了一些愚蠢的东西,但无论如何,这是我的代码: UIActivityIndicatorView indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; indicator.hidesWhenStopped = YES; indicator.frame = btnLogin.frame; indicator.center =

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

UIActivityIndicatorView indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.hidesWhenStopped = YES;
indicator.frame = btnLogin.frame;
indicator.center = btnLogin.center;
[self.view addSubview:indicator];
[indicator bringSubviewToFront:indicator];
以下是最终结果:


提前谢谢你

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

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

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];

作为旁注:在视图框架之后设置视图中心是多余的。另外,作为子视图添加的最后一个视图将自动成为前子视图。

Swift Solution

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);
或使用大型库


基于@Musa-almatri-answer,我创建了扩展:

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

我在用违禁品把指示灯放在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()
            }
        }
    }
}

这是一个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()
                }
            }
        }
    }
}

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

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)
        }
    }
}
}
小升级:(在superview上添加按钮)


注意,这会将指示器置于按钮的中心。使用CGPointMake(buttonWidth-halfButtonHeight,halfButtonHeight)接受答案。将答案放在右边(IMO,以一种简单、巧妙的方式)。函数参数标签是多余的,因为它与参数名称相同。你可以写:
func-loadingIndicator(show:Bool)
。为什么这比带标签的更好?你能详细说明一下吗?使用标签会增加额外的复杂性并可能导致错误,但我并不是说标签不好。此解决方案更简单,只需查找UIActivityIndicatorView本身。感谢您的解释:)为什么不
indicator.center=self.center
buttonWidth-half buttonheight
:从宽度中减去高度似乎是错误的。然后,第一个
指示符.center
赋值无效,因为还有第二个赋值。最后,什么是
x
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()
            }
        }
    }
}