2017-02-17 44 views
0

所以我完全能夠從我的分析服務器將圖像加載到我的tableview中,但是如果它滯後,那麼這個單元格就是白色的。所以我想要做的是添加一個自定義旋轉指示器到背景上,這個背景會旋轉直到圖像完全加載。這是指標。它關閉了github的一個倉庫。存儲庫是「https://github.com/Tueno/MaterialLoadingIndicator」,其代碼如下。我需要幫助的是有人向我展示如何在圖像加載之前在單元中實現此指示器以旋轉。在tableView中顯示uiimage的指標

繼承人的指示 `類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) 
     } 
    }) 
+0

從你的問題中刪除objective-c標記,因爲你使用的是swift代碼。 –

回答

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 
     } 
} 
+0

多數民衆贊成多多少少,但你可以幫助我執行materialloadingindicator – john

+0

你認爲什麼 – john

+0

[鏈接](https://www.evernote.com/l/ARIEicjI3AFF1aev0NAjIVt2ot1Md8WOSMg)[鏈接](https://www.evernote.com/l/ARJqhrEZ0l5IMIeLUn1IkjZ1ear94QtFUsE) –

0

創建MaterialLoadingIndicator,並將其添加爲imageViewsubview

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()和設定的圖像imageView

+0

我試過了它沒有工作 – john

+0

這沒有用你認爲你可以幫我嗎 – john

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

+0

雖然我有一個問題。我正在從解析中加載圖像。你可以看看我的項目 – john

+0

你認爲怎麼樣 – john

+0

哦,當然請給我的項目文件,並指定是什麼錯誤 – arunjos007