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

Posted

技术标签:

【中文标题】如何在 tableView 加载时显示活动指示器?【英文标题】:How to show activity indicator while tableView loads? 【发布时间】:2015-04-28 07:22:18 【问题描述】:

当我在标签之间切换时,它会加载几秒钟,我想知道我的数据正在加载。为此,我决定添加一个活动指示器。

我写了一个小函数:

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 执行之前显示它并在之后隐藏。这对我没有帮助。当我尝试使用同步时:

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

但这也无济于事。当我按下选项卡时,它的不透明度变为 0.5,我在加载时等待。但我没有看到我的活动指示器。

有什么问题?

【问题讨论】:

【参考方案1】:

试试这个:

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

【讨论】:

可见。只是根本没有出现 为什么你给显示活动指示器并同时隐藏 我评论了这行//self.hideActivityIndicator()。还是一样。不工作 @OrkhanAlizade 如果你想从另一个视图控制器调用活动指标意味着只需创建一个具有子类 nsobject 的类。然后将该实例调用到你的 VC。对我来说它有效如果你想要更多细节让我知道我会给出更多代码 @Lyuda 你能帮我在聊天中解决它吗?请!我工作了 2-3 天,一无所获!【参考方案2】:

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 中无法使用它自己的扩展文件。【参考方案3】:

斯威夫特 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 的背景颜色相同。只要没有单元格覆盖视图,此解决方案就可以工作(因此在加载时这没问题),除非您(像我一样)有一个占位符单元格显示一些文本。在这种情况下,将加载指示器添加到该单元格可能会更容易。【参考方案4】:

我使用两种扩展方法来添加一个UIActivityIndicatorView 作为tableview 的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()

【讨论】:

【参考方案5】:

这段代码可以帮助你:)

   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()

【讨论】:

【参考方案6】:

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()

在我的例子中,我通过 func 请求请求 json 对象,所以我将它放在该函数的末尾,以便在数据加载后删除活动指示器:

self.indicator.stopAnimating()
self.indicator.hidesWhenStopped = true

【讨论】:

【参考方案7】:

另一种方法,在我的代码中,我为 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(superview)中

【讨论】:

【参考方案8】:
 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

【讨论】:

【参考方案9】:

更新 Swift 4.2:

1.调用viewDidLoad上的activityIndi​​cator函数 例如:

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

这里是添加 ActivityIndi​​cator 作为子视图的代码

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。执行 UI 相关操作或 API 调用并停止活动指示器

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

【讨论】:

【参考方案10】:

使用“惰性变量”。比功能好

fileprivate lazy var activityIndicatorView: UIActivityIndicatorView = 
    let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    activityIndicatorView.hidesWhenStopped = true

    // Set Center
    var center = self.view.center
    if let navigationBarFrame = self.navigationController?.navigationBar.frame 
        center.y -= (navigationBarFrame.origin.y + navigationBarFrame.size.height)
    
    activityIndicatorView.center = center

    self.view.addSubview(activityIndicatorView)
    return activityIndicatorView
()

在任何地方启动微调器

喜欢这个

func requestData() 
  // Request something
  activityIndicatorView.startAnimating()

【讨论】:

【参考方案11】:

@brocolli 对 swift 4.0 的回答。在获取或设置关联对象之前,您必须使用 objc_。根据文档,在 Swift 中获取和设置关联对象的 API 是:

func objc_getAssociatedObject(object: AnyObject!,
                                 key: UnsafePointer<Void>
                             )  -> AnyObject!

func objc_setAssociatedObject(object: AnyObject!,
                                 key: UnsafePointer<Void>,
                               value: AnyObject!,
                              policy: objc_AssociationPolicy)

实施:

import UIKit

fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey"

extension UIView 
    var activityIndicatorView: UIActivityIndicatorView 
        get 
            if let activityIndicatorView = objc_getAssociatedObject(self, &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)

                objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, activityIndicatorView, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                return activityIndicatorView
            
        

        set 
            addSubview(newValue)
            objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        

    

【讨论】:

请提供一些关于如何解决问题的详细信息。否则,此答案对未来的用户几乎毫无用处。【参考方案12】:

为了将 UIActivityIndi​​cator 放在前台,甚至在最终的 UITableViewController 分隔符上,我采用了这个解决方案。

我以编程方式添加了 UIActivityIndi​​cator,并将其添加为我的 UINavigationController 的子视图

var activityIndicator: UIActivityIndicatorView!

override func viewDidLoad() 
   super.viewDidLoad()
   // Code
   // .... omissis

   // Set activity indicator
   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()
       
   
   // Others UIViewController or UITableViewController follows...
   // all of them exhibits an activityIndicator variable
   // implemented programmatically or with the storyboard

PS。我的环境是 Xcode 10.0,ios 12.0

【讨论】:

以上是关于如何在 tableView 加载时显示活动指示器?的主要内容,如果未能解决你的问题,请参考以下文章

恢复应用程序状态时显示不确定的活动指示器?

如何在加载kendo-grid时显示kendo加载图标?

在流星收集加载时显示加载器

在 SwiftUI 中加载网站时加载活动指示器

仅在 graphql 查询中的初始加载时显示加载指示器

当页面数据未从 Firebase 完全加载时显示加载指示器/微调器 - Flutter