UIView 的扩展

Posted

技术标签:

【中文标题】UIView 的扩展【英文标题】:Extension of UIView 【发布时间】:2015-11-10 04:16:37 【问题描述】:

我的代码是用 Swift 2.0 编写的,部署目标是 ios 8.0 或更高版本。我正在尝试扩展 UIView,以便我可以使用我的自定义函数,而不是使用 UIView.animateWithDuration()。我想取一个UIView,它是一个圆形并保留它,使其角半径保持其高度和宽度的一半,但填充一个正方形。所以UIView 应该以其当前形状扩展,直到达到矩形边界。我想在 UIView 上使用扩展。如下。

extension UIView 
       func customAnimation() 

       

有效的代码是。

let ViewFrame: CGRect = CGRect(x: 100, y: 100, width: 10, height: 10)

let View: UIView = UIView(frame: ViewFrame)

View.layer.cornerRadius = 5 
View.bounds = CGRect(x: 0, y: 0, width: 300, height: 300)
View.layer.masksToBounds = true
UIView.animateWithDuration(duration: 10.0, delay: 0.0, options: .CurveEaseInOut, animation: 
    View.transform = CGAffineTransformMakeScale(100.0, 100.0)
, completion: nil)

【问题讨论】:

【参考方案1】:
enum AIEdge:Int 
case
Top,
Left,
Bottom,
Right,
Top_Left,
Top_Right,
Bottom_Left,
Bottom_Right,
All,
None

extension UIView 

//MARK:- HEIGHT / WIDTH

var width:CGFloat 
    return self.frame.size.width

var height:CGFloat 
    return self.frame.size.height

var xPos:CGFloat 
    return self.frame.origin.x

var yPos:CGFloat 
    return self.frame.origin.y


//MARK:- DASHED BORDER
func drawDashedBorderAroundView() 
    let cornerRadius: CGFloat = self.frame.size.width / 2
    let borderWidth: CGFloat = 0.5
    let dashPattern1: Int = 4
    let dashPattern2: Int = 2
    let lineColor = WHITE_COLOR

    //drawing
    let frame: CGRect = self.bounds
    let shapeLayer = CAShapeLayer()
    //creating a path
    let path: CGMutablePath = CGMutablePath()

    //drawing a border around a view
    path.move(to: CGPoint(x: CGFloat(0), y: CGFloat(frame.size.height - cornerRadius)), transform: .identity)
    path.addLine(to: CGPoint(x: CGFloat(0), y: CGFloat(cornerRadius)), transform: .identity)
    path.addArc(center: CGPoint(x: CGFloat(cornerRadius), y: CGFloat(cornerRadius)), radius: CGFloat(cornerRadius), startAngle: CGFloat(M_PI), endAngle: CGFloat(-M_PI_2), clockwise: false, transform: .identity)
    path.addLine(to: CGPoint(x: CGFloat(frame.size.width - cornerRadius), y: CGFloat(0)), transform: .identity)
    path.addArc(center: CGPoint(x: CGFloat(frame.size.width - cornerRadius), y: CGFloat(cornerRadius)), radius: CGFloat(cornerRadius), startAngle: CGFloat(-M_PI_2), endAngle: CGFloat(0), clockwise: false, transform: .identity)
    path.addLine(to: CGPoint(x: CGFloat(frame.size.width), y: CGFloat(frame.size.height - cornerRadius)), transform: .identity)
    path.addArc(center: CGPoint(x: CGFloat(frame.size.width - cornerRadius), y: CGFloat(frame.size.height - cornerRadius)), radius: CGFloat(cornerRadius), startAngle: CGFloat(0), endAngle: CGFloat(M_PI_2), clockwise: false, transform: .identity)
    path.addLine(to: CGPoint(x: CGFloat(cornerRadius), y: CGFloat(frame.size.height)), transform: .identity)
    path.addArc(center: CGPoint(x: CGFloat(cornerRadius), y: CGFloat(frame.size.height - cornerRadius)), radius: CGFloat(cornerRadius), startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI), clockwise: false, transform: .identity)

    //path is set as the _shapeLayer object's path

    shapeLayer.path = path
    shapeLayer.backgroundColor = UIColor.clear.cgColor
    shapeLayer.frame = frame
    shapeLayer.masksToBounds = false
    shapeLayer.setValue(NSNumber(value: false), forKey: "isCircle")
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = lineColor.cgColor
    shapeLayer.lineWidth = borderWidth
    shapeLayer.lineDashPattern = [NSNumber(integerLiteral: dashPattern1),NSNumber(integerLiteral: dashPattern2)]
    shapeLayer.lineCap = kCALineCapRound

    self.layer.addSublayer(shapeLayer)
    //self.layer.cornerRadius = cornerRadius



//MARK:- ROTATE
func rotate(angle: CGFloat) 
    let radians = angle / 180.0 * CGFloat(M_PI)
    self.transform = self.transform.rotated(by: radians);





//MARK:- BORDER
func applyBorderDefault() 
    self.applyBorder(color: UIColor.red, width: 1.0)

func applyBorderDefault1() 
    self.applyBorder(color: UIColor.green, width: 1.0)

func applyBorderDefault2() 
    self.applyBorder(color: UIColor.blue, width: 1.0)

func applyBorder(color:UIColor, width:CGFloat) 
    self.layer.borderColor = color.cgColor
    self.layer.borderWidth = width



//MARK:- CIRCLE
func applyCircle() 
    self.layer.cornerRadius = min(self.frame.size.height, self.frame.size.width) * 0.5
    self.layer.masksToBounds = true
    self.clipsToBounds = true

func applyCircleWithRadius(radius:CGFloat) 
    self.layer.cornerRadius = radius
    self.layer.masksToBounds = true


//MARK:- CORNER RADIUS
func applyCornerRadius(radius:CGFloat) 
    self.layer.cornerRadius = radius
    self.layer.masksToBounds = true


func applyCornerRadiusDefault() 
    self.applyCornerRadius(radius: 5.0)



//MARK:- SHADOW
func applyShadowDefault()   
    self.applyShadowWithColor(color: UIColor.black, opacity: 0.5, radius: 1)


func applyShadowWithColor(color:UIColor)    
    self.applyShadowWithColor(color: color, opacity: 0.5, radius: 1)


func applyShadowWithColor(color:UIColor, opacity:Float, radius: CGFloat)    
    self.layer.shadowColor = color.cgColor
    self.layer.shadowOpacity = opacity
    self.layer.shadowOffset = CGSize.zero
    self.layer.shadowRadius = radius
    self.clipsToBounds = false




func applyShadowWithColor(color:UIColor, opacity:Float, radius: CGFloat, edge:AIEdge, shadowSpace:CGFloat)  

    var sizeOffset:CGSize = CGSize.zero
    switch edge 
    case .Top:
        sizeOffset = CGSize(width: 0, height: -shadowSpace) //CGSizeMake(0, -shadowSpace)
    case .Left:
        sizeOffset = CGSize(width: -shadowSpace, height: 0) //CGSizeMake(-shadowSpace, 0)
    case .Bottom:
        sizeOffset = CGSize(width: 0, height: shadowSpace) //CGSizeMake(0, shadowSpace)
    case .Right:
        sizeOffset = CGSize(width: shadowSpace, height: 0) //CGSizeMake(shadowSpace, 0)


    case .Top_Left:
        sizeOffset = CGSize(width: -shadowSpace, height: -shadowSpace) //CGSizeMake(-shadowSpace, -shadowSpace )
    case .Top_Right:
        sizeOffset = CGSize(width: shadowSpace, height: -shadowSpace) //CGSizeMake(shadowSpace, -shadowSpace)
    case .Bottom_Left:
        sizeOffset = CGSize(width: -shadowSpace, height: shadowSpace) //CGSizeMake(-shadowSpace, shadowSpace)
    case .Bottom_Right:
        sizeOffset = CGSize(width: shadowSpace, height: shadowSpace) //CGSizeMake(shadowSpace, shadowSpace)


    case .All:
        sizeOffset = CGSize(width: 0, height: 0) //CGSizeMake(0, 0)
    case .None:
        sizeOffset = CGSize.zero
    

    self.layer.shadowColor = color.cgColor
    self.layer.shadowOpacity = opacity
    self.layer.shadowOffset = sizeOffset
    self.layer.shadowRadius = radius
    self.clipsToBounds = false



func addBorderWithColor(color:UIColor, edge:AIEdge, thicknessOfBorder:CGFloat)  

    // dispatch_async(dispatch_get_main_queue()) 

    DispatchQueue.main.async 

        var rect:CGRect = CGRect.zero

        switch edge 
        case .Top:
            rect = CGRect(x: 0, y: 0, width: self.width, height: thicknessOfBorder) //CGRectMake(0, 0, self.width, thicknessOfBorder);
        case .Left:
            rect = CGRect(x: 0, y: 0, width: thicknessOfBorder, height:self.width ) //CGRectMake(0, 0, thicknessOfBorder, self.height);
        case .Bottom:
            rect = CGRect(x: 0, y: self.height - thicknessOfBorder, width: self.width, height: thicknessOfBorder) //CGRectMake(0, self.height - thicknessOfBorder, self.width, thicknessOfBorder);
        case .Right:
            rect = CGRect(x: self.width-thicknessOfBorder, y: 0, width: thicknessOfBorder, height: self.height) //CGRectMake(self.width-thicknessOfBorder, 0,thicknessOfBorder, self.height);
        default:
            break
        

        let layerBorder = CALayer()
        layerBorder.frame = rect
        layerBorder.backgroundColor = color.cgColor
        self.layer.addSublayer(layerBorder)
    



func animateVibrate() 

    let duration = 0.05

    UIView.animate(withDuration: duration ,
                               animations: 
                                self.transform = self.transform.translatedBy(x: 5, y: 0)
    ,
                               completion:  finish in

                                UIView.animate(withDuration: duration ,
                                                           animations: 
                                                            self.transform = self.transform.translatedBy(x: -10, y: 0)
                                ,
                                                           completion:  finish in


                                                            UIView.animate(withDuration: duration ,
                                                                                       animations: 
                                                                                        self.transform = self.transform.translatedBy(x: 10, y: 0)
                                                            ,
                                                                                       completion:  finish in


                                                                                        UIView.animate(withDuration: duration ,
                                                                                                                   animations: 
                                                                                                                    self.transform = self.transform.translatedBy(x: -10, y: 0)
                                                                                        ,
                                                                                                                   completion:  finish in

                                                                                                                    UIView.animate(withDuration: duration)
                                                                                                                        self.transform = CGAffineTransform.identity
                                                                                                                    
                                                                                        )
                                                            )
                                )
    )

【讨论】:

【参考方案2】:

你真的只需要像这样将动画逻辑移动到扩展函数中

extension UIView 
    func customAnimtation() 
        UIView.animateWithDuration(10.0, delay: 0.0, options: .CurveEaseInOut, animations: 
            self.transform = CGAffineTransformMakeScale(100.0, 100.0)
        , completion: nil)
    



let ViewFrame: CGRect = CGRect(x: 100, y: 100, width: 10, height: 10)
let View: UIView = UIView(frame: ViewFrame)
View.layer.cornerRadius = 5
View.bounds = CGRect(x: 0, y: 0, width: 300, height: 300)
View.layer.masksToBounds = true
View.customAnimtation()

【讨论】:

以上是关于UIView 的扩展的主要内容,如果未能解决你的问题,请参考以下文章

如何将 circleView 进度添加到 UIView 扩展到所有 UIView?

为啥 UIView 的扩展对除了放置在 IB 上的 UIView 之外的其他控件没有直接影响?

苹果手表应用冲突uiview扩展

UIView 扩展获取 UITableViewCell?

使用径向渐变作为 UIView 的扩展

在 Swift 中平滑扩展 UIView 动画