带有加载指示器的UISearchController

问题描述 投票:0回答:6

我实现了

UISearchController
并且我从 js 回调中获取数据,但是当我录入
searchbar
时,需要一些时间来放置数据,所以我想知道如何实现将
indicator
加载到表中查看结果
UISearchController

ios objective-c loading uisearchcontroller
6个回答
12
投票

用 Swift 3 编写了这个扩展,看起来效果很好。

extension UISearchBar {

    private var textField: UITextField? {
        return subviews.first?.subviews.flatMap { $0 as? UITextField }.first
    }

    private var activityIndicator: UIActivityIndicatorView? {
        return textField?.leftView?.subviews.flatMap{ $0 as? UIActivityIndicatorView }.first
    }

    var isLoading: Bool {
        get {
            return activityIndicator != nil
        } set {
            if newValue {
                if activityIndicator == nil {
                    let newActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
                    newActivityIndicator.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
                    newActivityIndicator.startAnimating()
                    newActivityIndicator.backgroundColor = UIColor.white
                    textField?.leftView?.addSubview(newActivityIndicator)
                    let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
                    newActivityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
                }
            } else {
                activityIndicator?.removeFromSuperview()
            }
        }
    }
}

搜索结果控制器上的加载指示器


4
投票

iOS 13 的更新解决方案:

extension UISearchBar {
    var textField: UITextField? {
        if #available(iOS 13.0, *) {
            return searchTextField
        } else {
           if let textField = value(forKey: "searchField") as? UITextField {
                return textField
            }
            return nil
        }
    }

    private var activityIndicator: UIActivityIndicatorView? {
        return textField?.leftView?.subviews.compactMap{ $0 as? UIActivityIndicatorView }.first
    }

    var isLoading: Bool {
        get {
            return activityIndicator != nil
        } set {
            if newValue {
                if activityIndicator == nil {
                    let newActivityIndicator = UIActivityIndicatorView(style: .gray)
                    newActivityIndicator.startAnimating()
                    if #available(iOS 13.0, *) {
                        newActivityIndicator.backgroundColor = UIColor.systemGroupedBackground
                    } else {
                        newActivityIndicator.backgroundColor = UIColor.groupTableViewBackground
                    }
                    newActivityIndicator.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                    textField?.leftView?.addSubview(newActivityIndicator)
                    let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
                    newActivityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
                }
            } else {
                activityIndicator?.removeFromSuperview()
            }
        }
    }
}

2
投票

适用于 iOS 13 及更高版本的更干净的解决方案:

extension UISearchController {
    
    private static let defaultLeftView: UIView = {
        UISearchTextField().leftView ?? UIView()
    }()
    
    private static let leftViewSize: CGSize = {
        UISearchTextField().leftView?.frame.size ?? .zero
    }()
    
    private static let loadingLeftView: UIView = {
        let view = UIView(frame: .init(origin: .zero, size: leftViewSize))
        
        let activityIndicatorView = UIActivityIndicatorView(style: .medium)
        activityIndicatorView.transform = .init(scaleX: 0.9, y: 0.9)
        activityIndicatorView.startAnimating()
        
        view.addSubview(activityIndicatorView)
        
        activityIndicatorView.center = CGPoint(x: leftViewSize.width / 2, y: leftViewSize.height / 2)
        
        return view
    }()
    
    func startLoading() {
        searchBar.searchTextField.leftView = Self.loadingLeftView
    }
    
    func stopLoading() {
        searchBar.searchTextField.leftView = Self.defaultLeftView
    }
}

0
投票

当您开始搜索时,您可以创建一个活动指示器,并使用

subview
方法将其添加为
UISearchBar
addSubView

  UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

//set your frame for activity indicator

[searchBar addSubview: spinner];

[spinner startAnimating];

完成搜索后,使用

removeFromSuperView
方法将其从搜索栏中删除。


0
投票

请尝试一下这个。可能对你有帮助

SearchBarWithloading.h

#import <UIKit/UIKit.h>

@interface SearchBarWithloading : UISearchBar

     - (void)startActivity;  // increments startCount and shows activity indicator
     - (void)finishActivity; // decrements startCount and hides activity indicator if 0

@end

SearchBarWithloading.m

import "SearchBarWithloading.h"

@interface SearchBarWithloading()

 @property(nonatomic) UIActivityIndicatorView *activityIndicatorView;
 @property(nonatomic) int startCount;

@end


@implementation SearchBarWithloading

 - (void)layoutSubviews {
     UITextField *searchField = nil;

for(UIView* view in self.subviews){
    if([view isKindOfClass:[UITextField class]]){
        searchField= (UITextField *)view;
        break;
    }
}

if(searchField) {
    if (!self.activityIndicatorView) {
        UIActivityIndicatorView *taiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        taiv.center = CGPointMake(searchField.leftView.bounds.origin.x + searchField.leftView.bounds.size.width/2,
                                  searchField.leftView.bounds.origin.y + searchField.leftView.bounds.size.height/2);
        taiv.hidesWhenStopped = YES;
        taiv.backgroundColor = [UIColor whiteColor];
        self.activityIndicatorView = taiv;
        [taiv release];
        _startCount = 0;

        [searchField.leftView addSubview:self.activityIndicatorView];
    }
}

[super layoutSubviews];
}

 - (void)startActivity  {
   self.startCount = self.startCount + 1;
 }

  - (void)finishActivity {
     self.startCount = self.startCount - 1;
  }

  - (void)setStartCount:(int)startCount {
       _startCount = startCount;
      if (_startCount > 0)
         [self.activityIndicatorView startAnimating];
      else {
          [self.activityIndicatorView stopAnimating];
      } 
 }

 @end

0
投票

sereisoglu 的解决方案会偶尔崩溃,可能是因为它在 defaultLeftView 静态变量中保存了不存在视图的子视图。

更稳定的解决方案:

extension UISearchBar {    
private static let leftViewSize: CGSize = {
    UISearchTextField().leftView?.frame.size ?? .zero
}()

private static let leftViewTint: UIColor? = {
    UISearchTextField().leftView?.tintColor
}()

private static let loadingLeftView: UIView = {
    let view = UIView(frame: .init(origin: .zero, size: leftViewSize))
    
    let activityIndicatorView = UIActivityIndicatorView(style: .medium)
    activityIndicatorView.transform = .init(scaleX: 0.9, y: 0.9)
    activityIndicatorView.startAnimating()
    
    view.addSubview(activityIndicatorView)
    
    activityIndicatorView.center = CGPoint(x: leftViewSize.width / 2, y: leftViewSize.height / 2)
    
    return view
}()

func startLoading() {
    DispatchQueue.main.async {
        self.searchTextField.leftView?.tintColor = .clear
        self.searchTextField.leftView?.addSubview(Self.loadingLeftView)
    }
}

func stopLoading() {
    DispatchQueue.main.async {
        self.searchTextField.leftView?.subviews[0].removeFromSuperview()
        self.searchTextField.leftView?.tintColor = Self.leftViewTint
    }
}

}

© www.soinside.com 2019 - 2024. All rights reserved.