Activity indicator with custom image

后端 未结 10 1271
甜味超标
甜味超标 2021-01-31 05:58

I am loading a UIWebView and in the meantime I wan\'t to show a blank page with this\"spinner\" activity indic

相关标签:
10条回答
  • 2021-01-31 06:41

    You can set an images to your activityIndicator. I created a function for add custom image to activityIndicator. Here is what I created.

    public func showProgressView(view: UIView) -> UIImageView {
        let containerView = UIView()
        let progressView = UIView()
        var activityIndicatorImageView = UIImageView()
    
        if let statusImage = UIImage(named: Constants.ActivityIndicatorImageName1) {
            let activityImageView = UIImageView(image: statusImage)
            containerView.frame = view.frame
            containerView.backgroundColor = UIColor(hex: 0xffffff, alpha: 0.3)
            progressView.frame = CGRectMake(0, 0, 80, 80)
            progressView.center = CGPointMake(view.bounds.width / 2, view.bounds.height / 2)
            progressView.backgroundColor = UIColor(hex: 0x18bda3, alpha: 0.7)
            progressView.clipsToBounds = true
            progressView.layer.cornerRadius = 10
            activityImageView.animationImages = [UIImage(named: Constants.ActivityIndicatorImageName1)!,
                UIImage(named: Constants.ActivityIndicatorImageName2)!,
                UIImage(named: Constants.ActivityIndicatorImageName3)!,
                UIImage(named: Constants.ActivityIndicatorImageName4)!,
                UIImage(named: Constants.ActivityIndicatorImageName5)!]
            activityImageView.animationDuration = 0.8;
            activityImageView.frame = CGRectMake(view.frame.size.width / 2 - statusImage.size.width / 2, view.frame.size.height / 2 - statusImage.size.height / 2, 40.0, 48.0)
            activityImageView.center = CGPointMake(progressView.bounds.width / 2, progressView.bounds.height / 2)
            dispatch_async(dispatch_get_main_queue()) {
                progressView.addSubview(activityImageView)
                containerView.addSubview(progressView)
                view.addSubview(containerView)
                activityIndicatorImageView = activityImageView
            }
        }
        return activityIndicatorImageView
    }
    

    You can call this method everywhere in your code. And just call the startAnimating method. If you want to hide just call the stopAnimating method.

    0 讨论(0)
  • 2021-01-31 06:42

    Swift 5

    Another answer working perfect

    Step 1.

    Create swift file "CustomLoader.swift" and put this code in that file

    import UIKit
    import CoreGraphics
    import QuartzCore
    
    class CustomLoader: UIView
    {
        //MARK:- NOT ACCESSABLE OUT SIDE
    
        fileprivate var duration : CFTimeInterval! = 1
        fileprivate var isAnimating :Bool = false
        fileprivate var backgroundView : UIView!
    
        //MARK:- ACCESS INSTANCE ONLY AND CHANGE ACCORDING TO YOUR NEEDS   *******
        let colors : [UIColor] = [.red,  .blue,  .orange, .purple]
        var defaultColor : UIColor = UIColor.red
        var isUsrInteractionEnable : Bool = false
        var defaultbgColor: UIColor = UIColor.white
        var loaderSize : CGFloat = 80.0
        /// **************** ******************  ////////// **************
    
        //MARK:- MAKE SHARED INSTANCE
        private static var Instance : CustomLoader!
        static let sharedInstance : CustomLoader = {
    
            if Instance == nil
            {
                Instance = CustomLoader()
            }
    
            return Instance
        }()
    
        //MARK:- DESTROY TO SHARED INSTANCE
        @objc fileprivate func destroyShardInstance()
        {
            CustomLoader.Instance = nil
        }
    
        //MARK:- SET YOUR LOADER INITIALIZER FRAME ELSE DEFAULT IS CENTER
        func startAnimation()
        {
            let win = UIApplication.shared.keyWindow
    
            backgroundView = UIView()
            backgroundView.frame = (UIApplication.shared.keyWindow?.frame)!
            backgroundView.backgroundColor = UIColor.init(white: 0, alpha: 0.4)
            win?.addSubview(backgroundView)
    
            self.frame = CGRect.init(x: ((UIScreen.main.bounds.width) - loaderSize)/2, y: ((UIScreen.main.bounds.height) - loaderSize)/2, width: loaderSize, height: loaderSize)
    
            self.addCenterImage()
            self.isHidden = false
            self.backgroundView.addSubview(self)
    
            self.layer.cornerRadius = loaderSize/2
            self.layer.masksToBounds = true
            backgroundView.accessibilityIdentifier = "CustomLoader"
    
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NSExtensionHostDidBecomeActive, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(CustomLoader.ResumeLoader), name: NSNotification.Name.NSExtensionHostDidBecomeActive, object: nil)
    
            self.layoutSubviews()
        }
    
        //MARK:- AVOID STUCKING LOADER WHEN CAME BACK FROM BACKGROUND
        @objc fileprivate func ResumeLoader()
        {
            if isAnimating
            {
                self.stopAnimation()
                self.AnimationStart()
            }
        }
    
        override func layoutSubviews()
        {
            super.layoutSubviews()
    
            self.backgroundColor = defaultbgColor
            UIApplication.shared.keyWindow?.isUserInteractionEnabled = isUsrInteractionEnable
            self.AnimationStart()
        }
    
        @objc fileprivate func addCenterImage()
        {
            /// add image in center
            let centerImage = UIImage(named: "Logo")
            let imageSize = loaderSize/2.5
    
            let centerImgView = UIImageView(image: centerImage)
            centerImgView.frame = CGRect(
                x: (self.bounds.width - imageSize) / 2 ,
                y: (self.bounds.height - imageSize) / 2,
                width: imageSize,
                height: imageSize
            )
    
            centerImgView.contentMode = .scaleAspectFit
            centerImgView.layer.cornerRadius = imageSize/2
            centerImgView.clipsToBounds = true
            self.addSubview(centerImgView)
    
        }
    
    
        //MARK:- CALL IT TO START THE LOADER , AFTER INITIALIZE THE LOADER
        @objc fileprivate func AnimationStart()
        {
            if isAnimating
            {
                return
            }
    
            let size = CGSize.init(width: loaderSize , height: loaderSize)
    
            let dotNum: CGFloat = 10
            let diameter: CGFloat = size.width / 5.5   //10
    
            let dot = CALayer()
            let frame = CGRect(
                x: (layer.bounds.width - diameter) / 2 + diameter * 2,
                y: (layer.bounds.height - diameter) / 2,
                width: diameter/1.3,
                height: diameter/1.3
            )
    
            dot.backgroundColor = colors[0].cgColor
            dot.cornerRadius = frame.width / 2
            dot.frame = frame
    
            let replicatorLayer = CAReplicatorLayer()
            replicatorLayer.frame = layer.bounds
            replicatorLayer.instanceCount = Int(dotNum)
            replicatorLayer.instanceDelay = 0.1
    
            let angle = (2.0 * M_PI) / Double(replicatorLayer.instanceCount)
    
            replicatorLayer.instanceTransform = CATransform3DMakeRotation(CGFloat(angle), 0.0, 0.0, 1.0)
    
            layer.addSublayer(replicatorLayer)
            replicatorLayer.addSublayer(dot)
    
            let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
            scaleAnimation.toValue = 0.4
            scaleAnimation.duration = 0.5
            scaleAnimation.autoreverses = true
            scaleAnimation.repeatCount = .infinity
            scaleAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
            dot.add(scaleAnimation, forKey: "scaleAnimation")
    
            let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
            rotationAnimation.toValue = -2.0 * Double.pi
            rotationAnimation.duration = 6.0
            rotationAnimation.repeatCount = .infinity
            rotationAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
            replicatorLayer.add(rotationAnimation, forKey: "rotationAnimation")
    
            if colors.count > 1 {
    
                var cgColors : [CGColor] = []
                for color in colors {
                    cgColors.append(color.cgColor)
                }
    
                let colorAnimation = CAKeyframeAnimation(keyPath: "backgroundColor")
                colorAnimation.values = cgColors
                colorAnimation.duration = 2
                colorAnimation.repeatCount = .infinity
                colorAnimation.autoreverses = true
                dot.add(colorAnimation, forKey: "colorAnimation")
    
            }
    
            self.isAnimating = true
            self.isHidden = false
    
        }
    
    
        //MARK:- CALL IT TO STOP THE LOADER
        func stopAnimation()
        {
            if !isAnimating
            {
                return
            }
            UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
            let winSubviews = UIApplication.shared.keyWindow?.subviews
            if (winSubviews?.count)! > 0
            {
                for viw in winSubviews!
                {
                    if viw.accessibilityIdentifier == "CustomLoader"
                    {
                        viw.removeFromSuperview()
                        //  break
                    }
                }
            }
    
            layer.sublayers = nil
    
            isAnimating = false
            self.isHidden = true
    
            self.destroyShardInstance()
        }
        //MARK:- GETTING RANDOM COLOR , AND MANAGE YOUR OWN COLORS
        @objc fileprivate func randomColor()->UIColor
        {
            let randomRed:CGFloat = CGFloat(drand48())
            let randomGreen:CGFloat = CGFloat(drand48())
            let randomBlue:CGFloat = CGFloat(drand48())
            return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
        }
        override func draw(_ rect: CGRect)
        {
        }
    }
    

    find the func name and "addCenterImage" and replace the image name with your custom image.

    Step 2

    Create the AppDelegate class instance out side of the AppDelegate class like this.

    var AppInstance: AppDelegate!
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate
    {    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
    {
        AppInstance = self
    }
    

    Step 3.

    put these two func in your AppDelegate

    //MARK: - Activity Indicator -
        func showLoader()
        {
            CustomLoader.sharedInstance.startAnimation()
        }
        func hideLoader()
        {
            CustomLoader.sharedInstance.stopAnimation()
        }
    

    Step 4. Use the functions like this whenever you want to animate your loader and stop.

    AppInstance.showLoader()
    AppInstance.hideLoader()
    

    HAPPY LOADING...

    0 讨论(0)
  • 2021-01-31 06:44

    Most of this is found in Stack Overflow. Let me summarize:

    Create an UIImageView which will serve as an activity indicator (inside storyboard scene, NIB, code ... wherever you wish). Let's call it _activityIndicatorImage

    Load your image: _activityIndicatorImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"activity_indicator"]];

    You need to use animation to rotate it. Here is the method I use:

    + (void)rotateLayerInfinite:(CALayer *)layer
    {
        CABasicAnimation *rotation;
        rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
        rotation.fromValue = [NSNumber numberWithFloat:0];
        rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
        rotation.duration = 0.7f; // Speed
        rotation.repeatCount = HUGE_VALF; // Repeat forever. Can be a finite number.
        [layer removeAllAnimations];
        [layer addAnimation:rotation forKey:@"Spin"];
    }
    

    Inside my layoutSubviews method I initiate rotation. You could place this in your webViewDidStartLoad and webViewDidFinishLoad if this is better for your case:

    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
        // some other code 
    
        [Utils rotateLayerInfinite:_activityIndicatorImage.layer];
    }
    

    You could always always stop rotation using [_activityIndicatorImage.layer removeAllAnimations];

    0 讨论(0)
  • 2021-01-31 06:48

    You can create your custom activity Indicator with this in Swift 3 & 4:

    Create a new file with name: UIViewExtension.Swift and copy this code and paste in your new file file:

    import UIkit
    
    extension UIView{
       func customActivityIndicator(view: UIView, widthView: CGFloat? = nil,backgroundColor: UIColor? = nil, message: String? = nil,colorMessage:UIColor? = nil ) -> UIView{
    
        //Config UIView
        self.backgroundColor = backgroundColor ?? UIColor.clear
        self.layer.cornerRadius = 10
    
    
        var selfWidth = view.frame.width - 100
        if widthView != nil{
            selfWidth = widthView ?? selfWidth
        }
    
        let selfHeigh = CGFloat(100)
        let selfFrameX = (view.frame.width / 2) - (selfWidth / 2)
        let selfFrameY = (view.frame.height / 2) - (selfHeigh / 2)
        let loopImages = UIImageView()
    
        //ConfigCustomLoading with secuence images
        let imageListArray = [UIImage(named:""),UIImage(named:""), UIImage(named:"")]
        loopImages.animationImages = imageListArray
        loopImages.animationDuration = TimeInterval(1.3)
        loopImages.startAnimating()
        let imageFrameX = (selfWidth / 2) - 17
        let imageFrameY = (selfHeigh / 2) - 35
        var imageWidth = CGFloat(35)
        var imageHeight = CGFloat(35)
    
        if widthView != nil{
            imageWidth = widthView ?? imageWidth
            imageHeight = widthView ?? imageHeight
        }
    
        //ConfigureLabel
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .gray
        label.font = UIFont.boldSystemFont(ofSize: 17)
        label.numberOfLines = 0
        label.text = message ?? ""
        label.textColor = colorMessage ?? UIColor.clear
    
        //Config frame of label
        let labelFrameX = (selfWidth / 2) - 100
        let labelFrameY = (selfHeigh / 2) - 10
        let labelWidth = CGFloat(200)
        let labelHeight = CGFloat(70)
    
        //add loading and label to customView
        self.addSubview(loopImages)
        self.addSubview(label)
    
        //Define frames
        //UIViewFrame
        self.frame = CGRect(x: selfFrameX, y: selfFrameY, width: selfWidth , height: selfHeigh)
    
        //ImageFrame
        loopImages.frame = CGRect(x: imageFrameX, y: imageFrameY, width: imageWidth, height: imageHeight)
    
        //LabelFrame
        label.frame = CGRect(x: labelFrameX, y: labelFrameY, width: labelWidth, height: labelHeight)
    
        return self
    
    }
    
    }
    

    And then you can use it in your ViewController like this:

    import UIKit
    
    
    class ExampleViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.view.addSubview(UIView().customActivityIndicator(view: self.view,backgroundColor: UIColor.green))
    
        }
    
       //function for stop and desappear loading
       func deseappearLoading(){
          self.view.subviews.last?.removeFromSuperview()
       }
    }
    

    Don't forget replace [UIImage(named:" "),UIImage(named:" "), UIImage(named:" ")] with your names of images and adjust the TimeInterval(1.3). Enjoy it.

    0 讨论(0)
提交回复
热议问题