tableView中uiimage的指示符

时间:2017-02-17 12:50:47

标签: ios swift

所以我完全能够从我的解析服务器将图像加载到我的tableview中,但如果它滞后则单元格只是白色。所以我想要做的是在背景中添加一个自定义旋转指示器,它将旋转直到图像完全加载。这是指标。它来自github的存储库。存储库是" https://github.com/Tueno/MaterialLoadingIndicator"它的代码如下。我需要帮助的是有人向我展示如何在图像加载之前在单元格中实现此指示器。

下面是指标的代码 `class MaterialLoadingIndicator:UIView {

let MinStrokeLength: CGFloat = 0.05
let MaxStrokeLength: CGFloat = 0.7
let circleShapeLayer = CAShapeLayer()

override init(frame: CGRect) {
    super.init(frame: frame)
    backgroundColor = UIColor.clear
    initShapeLayer()
}

required
init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func initShapeLayer() {
    circleShapeLayer.actions = ["strokeEnd" : NSNull(),
                                "strokeStart" : NSNull(),
                                "transform" : NSNull(),
                                "strokeColor" : NSNull()]
    circleShapeLayer.backgroundColor = UIColor.clear.cgColor
    circleShapeLayer.strokeColor     = UIColor.blue.cgColor
    circleShapeLayer.fillColor       = UIColor.clear.cgColor
    circleShapeLayer.lineWidth       = 5
    circleShapeLayer.lineCap         = kCALineCapRound
    circleShapeLayer.strokeStart     = 0
    circleShapeLayer.strokeEnd       = MinStrokeLength
    let center                       = CGPoint(x: bounds.width*0.5, y: bounds.height*0.5)
    circleShapeLayer.frame           = bounds
    circleShapeLayer.path            = UIBezierPath(arcCenter: center,
                                                    radius: center.x,
                                                    startAngle: 0,
                                                    endAngle: CGFloat(M_PI*2),
                                                    clockwise: true).cgPath
    layer.addSublayer(circleShapeLayer)
}

func startAnimating() {
    if layer.animation(forKey: "rotation") == nil {
        startColorAnimation()
        startStrokeAnimation()
        startRotatingAnimation()
    }
}

private func startColorAnimation() {
    let color      = CAKeyframeAnimation(keyPath: "strokeColor")
    color.duration = 10.0
    color.values   = [UIColor(hex: 0x4285F4, alpha: 1.0).cgColor,
                      UIColor(hex: 0xDE3E35, alpha: 1.0).cgColor,
                      UIColor(hex: 0xF7C223, alpha: 1.0).cgColor,
                      UIColor(hex: 0x1B9A59, alpha: 1.0).cgColor,
                      UIColor(hex: 0x4285F4, alpha: 1.0).cgColor]
    color.calculationMode = kCAAnimationPaced
    color.repeatCount     = Float.infinity
    circleShapeLayer.add(color, forKey: "color")
}

private func startRotatingAnimation() {
    let rotation            = CABasicAnimation(keyPath: "transform.rotation.z")
    rotation.toValue        = M_PI*2
    rotation.duration       = 2.2
    rotation.isCumulative     = true
    rotation.isAdditive       = true
    rotation.repeatCount    = Float.infinity
    layer.add(rotation, forKey: "rotation")
}

private func startStrokeAnimation() {
    let easeInOutSineTimingFunc = CAMediaTimingFunction(controlPoints: 0.39, 0.575, 0.565, 1.0)
    let progress: CGFloat     = MaxStrokeLength
    let endFromValue: CGFloat = circleShapeLayer.strokeEnd
    let endToValue: CGFloat   = endFromValue + progress
    let strokeEnd                   = CABasicAnimation(keyPath: "strokeEnd")
    strokeEnd.fromValue             = endFromValue
    strokeEnd.toValue               = endToValue
    strokeEnd.duration              = 0.5
    strokeEnd.fillMode              = kCAFillModeForwards
    strokeEnd.timingFunction        = easeInOutSineTimingFunc
    strokeEnd.beginTime             = 0.1
    strokeEnd.isRemovedOnCompletion   = false
    let startFromValue: CGFloat     = circleShapeLayer.strokeStart
    let startToValue: CGFloat       = fabs(endToValue - MinStrokeLength)
    let strokeStart                 = CABasicAnimation(keyPath: "strokeStart")
    strokeStart.fromValue           = startFromValue
    strokeStart.toValue             = startToValue
    strokeStart.duration            = 0.4
    strokeStart.fillMode            = kCAFillModeForwards
    strokeStart.timingFunction      = easeInOutSineTimingFunc
    strokeStart.beginTime           = strokeEnd.beginTime + strokeEnd.duration + 0.2
    strokeStart.isRemovedOnCompletion = false
    let pathAnim                 = CAAnimationGroup()
    pathAnim.animations          = [strokeEnd, strokeStart]
    pathAnim.duration            = strokeStart.beginTime + strokeStart.duration
    pathAnim.fillMode            = kCAFillModeForwards
    pathAnim.isRemovedOnCompletion = false
    CATransaction.begin()
    CATransaction.setCompletionBlock {
        if self.circleShapeLayer.animation(forKey: "stroke") != nil {
            self.circleShapeLayer.transform = CATransform3DRotate(self.circleShapeLayer.transform, CGFloat(M_PI*2) * progress, 0, 0, 1)
            self.circleShapeLayer.removeAnimation(forKey: "stroke")
            self.startStrokeAnimation()
        }
    }
    circleShapeLayer.add(pathAnim, forKey: "stroke")
    CATransaction.commit()
}

func stopAnimating() {
    circleShapeLayer.removeAllAnimations()
    layer.removeAllAnimations()
    circleShapeLayer.transform = CATransform3DIdentity
    layer.transform            = CATransform3DIdentity
}

}

  extension UIColor {

convenience init(hex: UInt, alpha: CGFloat) {
    self.init(
        red: CGFloat((hex & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((hex & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(hex & 0x0000FF) / 255.0,
        alpha: CGFloat(alpha)
    )
}

}`

这是我的代码从我的服务器加载图像。

    let query = PFQuery(className: "Users")
    query.addDescendingOrder("createdAt")
    query.findObjectsInBackground(block: { (objects, error) -> Void in
        if error == nil {

            // clean up
            self.UserNameArray.removeAll(keepingCapacity: false)
            self.ImageArray.removeAll(keepingCapacity: false)

            // find related objects
            for object in objects! {
                self.UserNameArray.append(object.object(forKey: "User") as! String)
                self.ImageArray.append(object.object(forKey: "Image") as! PFFile)
            }

            //ADD THIS
            self.horizontalContacts.reloadData()

        } else {
            print(error!.localizedDescription)
        }
    })

3 个答案:

答案 0 :(得分:0)

//something like that
class ImageTableViewCell: UITableViewCell {
    var contentImage: UIImage?{
        didSet{
            if contentImage == nil{
                self.imageView.addSubview(MaterialLoadingIndicator)
            }else{

                self.imageView = UIImageView(image: contentImage )
            }
        }
    }


    //and in TableViewController

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! ImageTableViewCell
        if images[indexPath.row] == nil{
            cell.image = nil
        }else{
            cell.image = images[indexPath.row]
            return cell
        }
}

答案 1 :(得分:0)

创建MaterialLoadingIndicator并将其添加为subview的{​​{1}}。

imageView

当您从解析服务器获取图片时,只需致电let indicator = MaterialLoadingIndicator(frame: CGRect(x: 0, y: 0, width: imageView.frame.size.width, height: imageView.frame.size.height)) indicator.center = imageView.center imageView.addSubview(indicator) //Start animating the loader indicator.startAnimating() 并将图片设置为indicator.stopAnimating()

答案 2 :(得分:0)

您可以通过创建自定义UIImageView类轻松实现此目的。然后,只要您想在项目中异步加载图像,就可以使用它。

首先创建一个新的coca touch class文件作为UIImageView的子类,并提供一个有意义的名称,我建议将AsyncImageView作为名称。

然后将代码段下方的粘贴复制到创建的文件中(如果不相应更改类名,我将AsyncImageView视为您创建的文件名),

import UIKit

class AsyncImageView: UIImageView {

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

    func downloadedFrom(url: URL, defaultImage:UIImage, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        contentMode = mode

    self.image = defaultImage

    let activityView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
    activityView.frame = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: self.frame.size.width, height: self.frame.size.height))
    activityView.layer.cornerRadius = self.layer.cornerRadius
    activityView.center = self.center
    activityView.backgroundColor = UIColor.clear
    activityView.startAnimating()
    self.superview?.addSubview(activityView)

        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
                let data = data, error == nil,
                let image = UIImage(data: data)
                else { return }
            DispatchQueue.main.async() { () -> Void in
                self.image = image
                activityView.stopAnimating()
                activityView.removeFromSuperview()
            }
            }.resume()
    }
func downloadedFrom(link: String, defaultImage:UIImage, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        guard let url = URL(string: link) else { return }
        downloadedFrom(url: url, defaultImage:defaultImage, contentMode: mode)
    }

}

多数民众赞成我们做过的!只需保存文件并使用此自定义类而不是UIImageView(在Xcode的Identity Inspector中设置类名)。通过拖动在控制器中创建imageview的插座后,您可以使用以下代码段异步加载图像

 @IBOutlet weak var asyncImageView: AsyncImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        asyncImageView.downloadedFrom(link: "https://s29.postimg.org/qqxoigjbr/Arun_Photo.png", defaultImage:UIImage(named:"noImage")!)
        // change image link to your image in parse server & default image means you can set a background image at time of indicator run
    }

我知道作为一个更新鲜的你仍然怀疑在这些步骤中为了更清晰我做了一个示例项目,你可以从here下载它 https://bitbucket.org/arunjos007/swfit_asyncimageview/downloads