如何在tableView加载时显示活动指示器?

37

当我在选项卡之间切换时,页面需要加载几秒钟时间,我想知道我的数据正在加载。因此,我决定添加活动指示器。

我编写了一个小函数:

func showActivityIndicator() {
    dispatch_async(dispatch_get_main_queue()) {
        self.spinner = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
        self.spinner.frame = CGRect(x: 0.0, y: 0.0, width: 80.0, height: 80.0)
        self.spinner.center = CGPoint(x:self.loadingView.bounds.size.width / 2, y:self.loadingView.bounds.size.height / 2)

        self.loadingView.addSubview(self.spinner)
        self.view.addSubview(self.loadingView)
        self.spinner.startAnimating()
    }
}

这将显示我的指示器。并尝试在我从infoController轻敲按钮时使用它:

@IBAction func goToMainFromInfo(sender: AnyObject) {
        self.showActivityIndicator()
        self.performSegueWithIdentifier("fromMainToInfoWActivity", sender: nil)
        self.hideActivityIndicator()
    }
}

在执行Segue之前我将其显示出来,之后隐藏它,并没有帮助到我。当我尝试使用sync时:

@IBAction func goToMainFromInfo(sender: AnyObject) {
    dispatch_async(dispatch_get_main_queue()) {
        self.showActivityIndicator()
        self.performSegueWithIdentifier("fromMainToInfoWActivity", sender: nil)
        self.hideActivityIndicator()
    }
}

但这也没有帮助。当我按tab键时,它的不透明度变为0.5,我在等待加载,但是我看不到我的活动指示器。

问题出在哪里?

12个回答

59

只需尝试这个:

var indicator = UIActivityIndicatorView()

func activityIndicator() {
    indicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 40, 40))
    indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
    indicator.center = self.view.center
    self.view.addSubview(indicator)    
}

你想从哪里开始制作动画

indicator.startAnimating()
indicator.backgroundColor = UIColor.whiteColor()

停止使用:

indicator.stopAnimating()
indicator.hidesWhenStopped = true

注意: 避免同时调用start和stop。只需提供一些条件。

SWIFT: 4.2 尝试这样做:

var indicator = UIActivityIndicatorView()

func activityIndicator() {
    indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
    indicator.style = UIActivityIndicatorView.Style.gray
    indicator.center = self.view.center
    self.view.addSubview(indicator)   
}

你想从哪里开始制作动画

activityIndicator()
indicator.startAnimating()
indicator.backgroundColor = .white

停止:

indicator.stopAnimating()
indicator.hidesWhenStopped = true

1
它是可见的。只是根本没有出现。 - Orkhan Alizade
为什么您要同时显示和隐藏活动指示器? - Lydia
@Lyuda,你能在聊天中帮我解决这个问题吗?拜托了!我已经花了2-3天的时间在上面,但是什么也没做出来! - Orkhan Alizade
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/76422/discussion-between-lyida-and-orkhan-alizade。 - Lydia
尝试使用该指标。将子视图带到前台(self.view)。 - Shanmugasundharam
显示剩余3条评论

19

Swift 3.0

// UIView扩展

fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey"
public extension UIView {
   var activityIndicatorView: UIActivityIndicatorView {
        get {
            if let activityIndicatorView = getAssociatedObject(&ActivityIndicatorViewAssociativeKey) as? UIActivityIndicatorView {
                return activityIndicatorView
            } else {
                let activityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
                activityIndicatorView.activityIndicatorViewStyle = .gray
                activityIndicatorView.color = .gray
                activityIndicatorView.center = center
                activityIndicatorView.hidesWhenStopped = true
                addSubview(activityIndicatorView)

                setAssociatedObject(activityIndicatorView, associativeKey: &ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                return activityIndicatorView
            }
        }

        set {
            addSubview(newValue)
            setAssociatedObject(newValue, associativeKey:&ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

// NSObject扩展

public extension NSObject {
    func setAssociatedObject(_ value: AnyObject?, associativeKey: UnsafeRawPointer, policy: objc_AssociationPolicy) {
        if let valueAsAnyObject = value {
            objc_setAssociatedObject(self, associativeKey, valueAsAnyObject, policy)
        }
    }

    func getAssociatedObject(_ associativeKey: UnsafeRawPointer) -> Any? {
        guard let valueAsType = objc_getAssociatedObject(self, associativeKey) else {
            return nil
        }
        return valueAsType
    }
}

开始动画

tableView.activityIndicatorView.startAnimating()

停止动画

tableView.activityIndicatorView.stopAnimating()

你可以在 Magic 中找到更多代码。


在Swift 4中无法将其作为独立的扩展文件运行。 - James Jordan Taylor

14

Swift 2+

    class ViewController: UITableViewController {
        weak var activityIndicatorView: UIActivityIndicatorView!

        override func viewDidLoad() {
            super.viewDidLoad()
            let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
            tableView.backgroundView = activityIndicatorView
            self.activityIndicatorView = activityIndicatorView
            activityIndicatorView.startAnimating()

        }
        ...
    }

对我来说,问题在于我将它添加到了视图中,而该视图被我的tableview单元格隐藏,并且与tableview的背景颜色相同。只要没有任何单元格覆盖该视图(因此在加载时这不是问题),这个解决方案就可以工作,除非你有(像我一样)一个显示一些文本的占位符单元格。在这种情况下,将加载指示器添加到该单元格可能更容易。 - user2359168

7

我使用了两个扩展方法将 UIActivityIndicatorView 添加为表视图的 backgroundView

extension UITableView {
    func showActivityIndicator() {
        DispatchQueue.main.async {
            let activityView = UIActivityIndicatorView(style: .medium)
            self.backgroundView = activityView
            activityView.startAnimating()
        }
    }

    func hideActivityIndicator() {
        DispatchQueue.main.async {
            self.backgroundView = nil
        }
    }
}

您可以像这样显示/隐藏它。
tableView.showActivityIndicator()
tableView.hideActivityIndicator()

2

这段代码可以帮助你 :)

   let indicator:UIActivityIndicatorView = UIActivityIndicatorView  (activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray) 
   indicator.color = UIColor .magentaColor()
   indicator.frame = CGRectMake(0.0, 0.0, 10.0, 10.0)
   indicator.center = self.view.center
   self.view.addSubview(indicator)
   indicator.bringSubviewToFront(self.view)
   indicator.startAnimating()

2

SWIFT

将以下代码放在你的类下面:

let indicator:UIActivityIndicatorView = UIActivityIndicatorView  (activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)

将以下代码放置在您的loadView()函数中:

indicator.color = UIColor .magentaColor()
indicator.frame = CGRectMake(0.0, 0.0, 10.0, 10.0)
indicator.center = self.view.center
self.view.addSubview(indicator)
indicator.bringSubviewToFront(self.view)
indicator.startAnimating()

在我的情况下,我通过一个名为“请求”的函数来请求Json对象,因此我把以下代码放在该函数的末尾,以便在数据加载完成后移除活动指示器:
self.indicator.stopAnimating()
self.indicator.hidesWhenStopped = true

2

更新 Swift 4.2:

1. 在 viewDidLoad 中调用 activityIndicator 函数。
例如:

var indicator = UIActivityIndicatorView()
override func viewDidLoad() {
    //Initializing the Activity Indicator
    activityIndicator()
    //Starting the Activity Indicator
    indicator.startAnimating()
    //Call Your WebService or API
    callAPI()
}

以下是添加ActivityIndicator为子视图的代码

func activityIndicator() {
            indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
            indicator.style = UIActivityIndicatorView.Style.whiteLarge
            indicator.color = .red
            indicator.center = self.view.center
            self.view.addSubview(indicator)
    }

2. 执行与用户界面相关的操作或API调用,并停止活动指示器。

    func callAPI() {     
        YourModelClass.fetchResult(someParams, 
        completionHandler: { (response) in 
        //Do necessary UIUpdates
        //And stop Activity Indicator
        self.indicator.stopAnimating()
        })
    }

2

另一种方法,在我的代码中我添加了一个UITableView的扩展(Swift 2.3):

extension UITableView {
    func activityIndicator(center: CGPoint = CGPointZero, loadingInProgress: Bool) {
        let tag = 12093
        if loadingInProgress {
            var indicator = UIActivityIndicatorView()
            indicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 40, 40))
            indicator.tag = tag
            indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
            indicator.color = //Your color here
            indicator.center = center
            indicator.startAnimating()
            indicator.hidesWhenStopped = true
            self.superview?.addSubview(indicator)
        }else {
             if let indicator = self.superview?.viewWithTag(tag) as? UIActivityIndicatorView { {
                indicator.stopAnimating()
                indicator.removeFromSuperview()
            }
        }
    }
}

注意:我的tableview嵌入在一个UIView(父视图)中。

1
 func setupSpinner(){
    spinner = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height:40))
    spinner.color = UIColor(Colors.Accent)
    self.spinner.center = CGPoint(x:UIScreen.main.bounds.size.width / 2, y:UIScreen.main.bounds.size.height / 2)
    self.view.addSubview(spinner)
    spinner.hidesWhenStopped = true
}

0
为了将UIActivityIndicator置于前景,甚至覆盖可能存在的UITableViewController分隔线,我采用了这个解决方案。
  • 我已经在编程中添加了UIActivityIndicator,并将其作为我的UINavigationController的子视图添加

    var activityIndicator: UIActivityIndicatorView!
    
    override func viewDidLoad() {
       super.viewDidLoad()
       // 代码
       // ....省略
    
       // 设置活动指示器
       activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
       activityIndicator.color = UIColor.darkGray
       activityIndicator.center = tableView.center
       activityIndicator.hidesWhenStopped = true
       activityIndicator.stopAnimating()
       self.navigationController?.view.addSubview(activityIndicator)
    }
    
  • 我只是在需要时(在我的情况下)开始和停止它:

    func animateActivityIndicator(_ sender: Any ) {
       guard let vc = sender as? UIViewController else { return }
       if let v = vc as? MyTableViewController {
           if v.activityIndicator.isAnimating {
               v.activityIndicator.stopAnimating()
           } else {
               v.activityIndicator.startAnimating()
           }
       }
       // 其他UIViewController或UITableViewController遵循...
       // 所有这些都展示了一个activityIndicator变量
       // 使用故事板或以编程方式实现
    }
    

顺便提一下,我的开发环境是Xcode 10.0,iOS 12.0。


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