Swift:UIView扩展之歌词控件(扩展添加属性 )

效果图:
在这里插入图片描述

一共由五种模式 :

  1. 歌词模式
  2. 解锁模式从左到右
  3. 解锁模式从右到左
  4. 解锁模式从左右循环
  5. 整体闪烁

代码如下

//
//  UIView+FQshimmeringView.swift
//  FQUIKit
//

import Foundation
import UIKit


let kFQBackLabel: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQbackLabel".hashValue)
let kFQFrontLabel: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQfrontLabel".hashValue)

let kFQ_shimmeringText: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "FQ_shimmeringText".hashValue)
let kFQ_shimmeringTextAlignment: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringTextAlignment".hashValue)
let kFQ_shimmeringBackColor: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringBackColor".hashValue)
let kFQ_shimmeringForeColor: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringForeColor".hashValue)
let kFQ_shimmeringTextfont: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringTextfont".hashValue)
let kFQ_shimmeringTextEdgeInsets: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringTextEdgeInsets".hashValue)
let kFQ_shimmeringStyle: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQ_shimmeringStyle".hashValue)

extension UIView{
    
    enum FQshimmeringViewStyle:NSInteger {
        case  FQShimmeringViewStyleOverallFilling = 1 // 歌词模式
        case  FQShimmeringViewStyleFadeLeftToRight = 2  // 从左到右解锁模式
        case  FQShimmeringViewStyleFadeRightToLeft = 3   // 从右到左解锁模式
        case  FQShimmeringViewStyleFadeReverse = 4 // 从左右循环
        case  FQShimmeringViewStyleFadeAll = 5 // 整体闪烁
    }
    
    
    private var FQ_BackLabel:FQ_label?{
        
        get{
            return objc_getAssociatedObject(self,kFQBackLabel) as? FQ_label
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQBackLabel, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    private var FQ_FrontLabel:FQ_label?{
        
        get{
            return objc_getAssociatedObject(self,kFQFrontLabel) as? FQ_label
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQFrontLabel, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    /**
     *  准备shimmering的文字
     */
    var FQ_shimmeringText:NSString?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringText) as? NSString)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringText, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            self.FQ_FrontLabel?.text = newValue as String?
            self.FQ_BackLabel?.text = newValue as String?
            
        }
    }
    
    /**
     *  shimmering文字的对其方式
     */
    var FQ_shimmeringTextAlignment:NSTextAlignment?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringTextAlignment) as? NSTextAlignment)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringTextAlignment, newValue, .OBJC_ASSOCIATION_ASSIGN)
            self.FQ_BackLabel?.textAlignment = newValue ?? NSTextAlignment.center
            self.FQ_FrontLabel?.textAlignment = newValue ?? NSTextAlignment.center
        }
    }
    /**
     *  shimmering文字的底层颜色
     */
    var FQ_shimmeringBackColor:UIColor?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringBackColor) as? UIColor)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringBackColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            self.FQ_BackLabel?.textColor = newValue
        }
    }
    /**
     *  shimmering文字的闪动颜色
     */
    var FQ_shimmeringForeColor:UIColor?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringForeColor) as? UIColor)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringForeColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            self.FQ_FrontLabel?.textColor = newValue
        }
    }
    /**
     *  shimmering文字的大小
     */
    var FQ_shimmeringTextfont:UIFont?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringTextfont) as? UIFont)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringTextfont, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            self.FQ_BackLabel?.font = newValue
            self.FQ_FrontLabel?.font = newValue
            
        }
    }
    
    /**
     *  shimmering文字的边距
     */
    var FQ_shimmeringTextEdgeInsets:UIEdgeInsets?{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringTextEdgeInsets) as? UIEdgeInsets)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringTextEdgeInsets, newValue, .OBJC_ASSOCIATION_ASSIGN)
            self.FQ_BackLabel?.FQ_textEdgeInsets = newValue
            self.FQ_FrontLabel?.FQ_textEdgeInsets = newValue
        }
    }
    
    
    /**
     *  shimmeringhh动画类型
     */
    var FQ_shimmeringStyle:FQshimmeringViewStyle{
        get{
            return (objc_getAssociatedObject(self,kFQ_shimmeringStyle) as! FQshimmeringViewStyle)
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQ_shimmeringStyle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    convenience init(frame:CGRect,shimmeringStyle:FQshimmeringViewStyle) {
        self.init(frame:frame)
        
        self.FQ_BackLabel = FQ_label(frame: self.bounds)
        self.addSubview(FQ_BackLabel!)
        
        self.FQ_FrontLabel = FQ_label(frame: self.bounds)
        self.addSubview(FQ_FrontLabel!)
        
        self.FQ_shimmeringStyle = shimmeringStyle
    }
    
    func FQ_shimmeringBeginWith(duration:TimeInterval){
        self.FQ_FrontLabel?.layer.removeAllAnimations()
        if (self.FQ_shimmeringStyle == .FQShimmeringViewStyleOverallFilling) {
            
            self.createFadeRightMask()
            let basicAnimation:CABasicAnimation = CABasicAnimation()
            basicAnimation.keyPath = "transform.translation.x"
            basicAnimation.fromValue = 0
            basicAnimation.toValue = self.bounds.size.width
            basicAnimation.duration = duration
            basicAnimation.repeatCount = Float(LONG_MAX)
            basicAnimation.isRemovedOnCompletion = false
            basicAnimation.fillMode = CAMediaTimingFillMode.forwards
            self.FQ_FrontLabel?.layer.mask?.add(basicAnimation, forKey: nil)
            
        }else if (self.FQ_shimmeringStyle == .FQShimmeringViewStyleFadeLeftToRight) {
            
            self.createiPhoneFadeMask()
            let basicAnimation:CABasicAnimation = CABasicAnimation()
            basicAnimation.keyPath = "transform.translation.x"
            basicAnimation.fromValue = 0
            basicAnimation.toValue = self.bounds.size.width + self.bounds.size.width/2.0
            basicAnimation.duration = duration
            basicAnimation.repeatCount = Float(LONG_MAX)
            basicAnimation.isRemovedOnCompletion = false
            basicAnimation.fillMode = CAMediaTimingFillMode.forwards
            self.FQ_FrontLabel?.layer.mask?.add(basicAnimation, forKey: nil)
            
        }else if(self.FQ_shimmeringStyle == .FQShimmeringViewStyleFadeRightToLeft){
            
            self.createiPhoneFadeMask()
            let basicAnimation:CABasicAnimation = CABasicAnimation()
            basicAnimation.keyPath = "transform.translation.x"
            basicAnimation.fromValue = self.bounds.size.width + self.bounds.size.width/2.0
            basicAnimation.toValue = 0
            basicAnimation.duration = duration
            basicAnimation.repeatCount = Float(LONG_MAX)
            basicAnimation.isRemovedOnCompletion = false
            basicAnimation.fillMode = CAMediaTimingFillMode.forwards
            self.FQ_FrontLabel?.layer.mask?.add(basicAnimation, forKey: nil)
            
        }else if(self.FQ_shimmeringStyle == .FQShimmeringViewStyleFadeReverse){
            
            self.createiPhoneFadeMask()
            let basicAnimation:CABasicAnimation = CABasicAnimation()
            basicAnimation.keyPath = "transform.translation.x"
            basicAnimation.fromValue =  0
            basicAnimation.toValue = self.bounds.size.width + self.bounds.size.width/2.0
            basicAnimation.duration = duration
            basicAnimation.repeatCount = Float(LONG_MAX)
            basicAnimation.isRemovedOnCompletion = false
            basicAnimation.autoreverses = true;
            basicAnimation.fillMode = CAMediaTimingFillMode.forwards
            self.FQ_FrontLabel?.layer.mask?.add(basicAnimation, forKey: nil)
            
        }else if(self.FQ_shimmeringStyle == .FQShimmeringViewStyleFadeAll){
             self.createShimmerAllMask()
            let basicAnimation:CABasicAnimation = CABasicAnimation(keyPath: "opacity")
            basicAnimation.repeatCount = MAXFLOAT;
            basicAnimation.autoreverses = true;
            basicAnimation.fromValue = 0
            basicAnimation.toValue = 1.0
            basicAnimation.duration = duration
            
            self.FQ_FrontLabel?.layer.add(basicAnimation, forKey: "start")
            self.FQ_FrontLabel?.layer.mask?.add(basicAnimation, forKey: nil)
        
        }
    }
    
    private func createFadeRightMask(){
        self.FQ_FrontLabel?.layer.removeAllAnimations()
        let layer:CAGradientLayer = CAGradientLayer()
        layer.frame = self.bounds
        layer.colors = [UIColor.clear.cgColor,UIColor.red.cgColor,UIColor.black.cgColor,UIColor.clear.cgColor]
        layer.locations = [0.01,0.1,0.9,0.99]
        self.FQ_FrontLabel?.layer.mask = layer
    }
    
    private func createShimmerAllMask(){
        self.FQ_FrontLabel?.layer.removeAllAnimations()
        let layer:CAGradientLayer = CAGradientLayer()
        layer.frame = self.bounds
        layer.colors = [UIColor.clear.cgColor,UIColor.red.cgColor,UIColor.black.cgColor,UIColor.clear.cgColor]
        layer.transform = CATransform3DIdentity
        self.FQ_FrontLabel?.layer.mask = layer
    }
    
    private func createiPhoneFadeMask(){
        self.FQ_FrontLabel?.layer.removeAllAnimations()
        let layer:CAGradientLayer = CAGradientLayer()
        layer.frame = self.bounds
        layer.colors = [UIColor.clear.cgColor,UIColor.red.cgColor,UIColor.clear.cgColor]
        layer.locations = [0.25,0.5,0.75];
        layer.startPoint = CGPoint(x: 0, y: 0);
        layer.endPoint = CGPoint(x: 1, y: 0);
        self.FQ_FrontLabel?.layer.mask = layer
        layer.position = CGPoint(x: -self.bounds.size.width/4.0, y: self.bounds.size.height/2.0);
    
    } 
}

记录一下坑:
其中swift 扩展动态添加属性的方法为

let kFQBackLabel: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "kFQbackLabel".hashValue)

private var FQ_BackLabel:FQ_label?{
        
        get{
            return objc_getAssociatedObject(self,kFQBackLabel) as? FQ_label
        }
        set(newValue){
            objc_setAssociatedObject(self, kFQBackLabel, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

项目地址:https://github.com/FORMAT-qi/FQUIkit

原本是OC写的,现在用swift重新优化写一遍。
后续会持续更新该项目其它扩展和控件。

原创文章 18 获赞 102 访问量 7944

猜你喜欢

转载自blog.csdn.net/weixin_46602773/article/details/105817295