所以我完全能够从我的解析服务器将图像加载到我的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)
}
})
答案 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