1. 程式人生 > >Swift教程_零基礎學習Swift完整例項(八)_swift完整例項(新增View的動畫效果、新增View的陰影)

Swift教程_零基礎學習Swift完整例項(八)_swift完整例項(新增View的動畫效果、新增View的陰影)


6.新增View的動畫效果

本章節主要來做明細頁面點選後翻轉的動畫效果,該效果可以進行多種改變,以達到想要的效果。

1.首先我們需要進行翻轉的正反兩個view,前面我們已經做好了,分別是PKOElementDetailImageViewPKOElementDetailImageFlippedView,具體翻轉動畫在明細頁面的控制其中進行,觸發當然是PKOElementDetailImageView中的點選事件,前文已經提到。
2.PKOElementDetailImageView中的點選事件呼叫PKOElementDetailViewController中的flipImageView()方法,該方法具體實現翻轉功能,註釋中寫的很詳細。

程式碼如下。

//翻轉動畫
    func flipImageView() {
        UIView.beginAnimations(nil, context:nil)
        //平滑動畫效果
        UIView.setAnimationCurve(UIViewAnimationCurve.Linear)
        UIView.setAnimationDuration(1)
        
        var reflectionHeight: CGFloat
        var reflectedImage: UIImage?
        
        //點選正面
        if(self.frontViewIsVisible == true){
            UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.subView!, cache: true)
            self.detailImage.removeFromSuperview()
            self.subView?.addSubview(self.detailImageFlipped)
        }
        //點選反面
        else{
            UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView:self.subView!, cache:true)
            self.detailImageFlipped.removeFromSuperview()
            self.subView?.addSubview(self.detailImage)
        }
        //提交動畫
        UIView.commitAnimations()
        //設定是否正面顯示標識
        self.frontViewIsVisible = !self.frontViewIsVisible
    }

7.新增View的陰影

本章節主要來做明細頁面圖片的陰影效果,該效果可以進行高度設定,並且完全反射,包含所繪製的文字。

1.通過控制器PKOElementDetailViewController繪製明細圖的同時,繪製圖片的陰影,該陰影應該基於陰影的主圖,所以放在PKOElementDetailImageView中處理。
reflectedImageWithHeight(height: UInt) ->UIImage該方法將返回對應陰影image。
具體做法請看註釋,思路是:複製一個位圖並裁剪成需要大小-翻轉並絳色-填充漸變色
程式碼如下。

//通過指定高度生成倒影圖,方法完全照搬官方sample,
    func reflectedImageWithHeight(height: UInt) ->UIImage{
        //這裡注意,swift不能直接在CG方法中用nil,需要宣告一個變數
        var nilUnsafeMutablePointer: UnsafeMutablePointer<Void> = nil
        //rgb顏色容器,RGBA和CMYK的區別我會另開博文去說這個
        var colorSpace  = CGColorSpaceCreateDeviceRGB()
        var int32CGImageAlphaInfo = CGImageAlphaInfo.PremultipliedLast.toRaw()
        var bitmapInfo = CGBitmapInfo.fromRaw(int32CGImageAlphaInfo)
        
        //使用CG繪製點陣圖上下文,以下是方法的用法,網上抓的,大家可以試一下具體用法。
        //引數data指向繪圖操作被渲染的記憶體區域,這個記憶體區域大小應該為(bytesPerRow*height)個位元組。如果對繪製操作被渲染的記憶體區域並無特別的要求,那麼可以傳遞NULL給引數date。
        //引數width代表被渲染記憶體區域的寬度。
        //引數height代表被渲染記憶體區域的高度。
        //引數bitsPerComponent被渲染記憶體區域中元件在螢幕每個畫素點上需要使用的bits位,舉例來說,如果使用32-bit畫素和RGB顏色格式,那麼RGBA顏色格式中每個元件在螢幕每個畫素點上需要使用的bits位就為32/4=8。
        //引數bytesPerRow代表被渲染記憶體區域中每行所使用的bytes位數。
        //引數colorspace用於被渲染記憶體區域的“點陣圖上下文”。
        //引數bitmapInfo指定被渲染記憶體區域的“檢視”是否包含一個alpha(透視)通道以及每個畫素相應的位置,除此之外還可以指定元件式是浮點值還是整數值。
        var mainViewContentContext = CGBitmapContextCreate(nilUnsafeMutablePointer, UInt(self.bounds.size.width), height, UInt(8), UInt(0), colorSpace, bitmapInfo!)
        
        //注意,swift操作CG是不需要釋放的,CG內部的GC已經處理了
        
        //調整點陣圖位置,CGContextTranslateCTM為位移方法
        var translateVertical = CGFloat(self.bounds.size.height) - CGFloat(height)
        //這裡相當於翻轉
        CGContextTranslateCTM(mainViewContentContext, 0, -translateVertical)
        
        //將該點陣圖渲染到layer層,layer層是view的根層,這裡相當與copy一個self
        self.layer.renderInContext(mainViewContentContext)
        
        //根據點陣圖上下文生成點陣圖
        var mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext)
        
        //建立一個mask,確認剛才生成的點陣圖那些是需要顯示的,這裡主要用它的漸變功能,image mask就像是用於表徵色彩放在頁面的哪一部分
        var gradientMaskImage = PKOElementDetailImageView.AEViewCreateGradientImage(UInt(1), pixelsHigh: UInt(height))
        
        //將點陣圖需要顯示的部分顯示出來
        var reflectionImage = CGImageCreateWithMask(mainViewContentBitmapContext, gradientMaskImage)
        
        //通過image生成UIImage,並返回
        var theImage = UIImage(CGImage: reflectionImage)
        return theImage
    }
    
    class func AEViewCreateGradientImage ( pixelsWide: UInt, pixelsHigh: UInt) ->CGImageRef {
        var nilUnsafeMutablePointer: UnsafeMutablePointer<Void> = nil
        var colorSpace = CGColorSpaceCreateDeviceGray()
        var int32CGImageAlphaInfo = CGImageAlphaInfo.None.toRaw()
        var bitmapInfo = CGBitmapInfo.fromRaw(int32CGImageAlphaInfo)
        //使用CG繪製點陣圖上下文,漸變色點陣圖
        var gradientBitmapContext = CGBitmapContextCreate(nilUnsafeMutablePointer, pixelsWide, pixelsHigh,
            UInt(8), UInt(0), colorSpace, bitmapInfo!)
        
        //建立漸變物件,對於CG漸變我會在開博文詳細解釋
        var colors: [CGFloat] = [0.0, 1.0,1.0, 1.0]
        var nilUnsafePointer: UnsafePointer<CGFloat> = nil
        var grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, nilUnsafePointer, UInt(2))
        
        //漸變的開始點和結束點
        var gradientStartPoint = CGPointZero
        var gradientEndPoint = CGPointMake(0, CGFloat(pixelsHigh))
        
        //填充漸變色
        CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint, gradientEndPoint, CGGradientDrawingOptions())
        
        //通過image生成UIImage,並返回
        var theCGImage = CGBitmapContextCreateImage(gradientBitmapContext)
        return theCGImage
    }

2.在PKOElementDetailViewController中影象渲染時呼叫PKOElementDetailImageView中的reflectedImageWithHeight(height: UInt) ->UIImage返回image,將其新增在subview中。
程式碼如下。

//建立倒影圖
        var reflectionRect = imageRect
        reflectionRect.size.height = CGFloat(CGRectGetHeight(reflectionRect)) * CGFloat(reflectionRadio)
        reflectionRect = CGRectOffset(reflectionRect, 0, CGRectGetHeight(imageRect))
        var reflectionView = UIImageView(frame: reflectionRect)
        self.reflectionImage = reflectionView
        var height = (self.detailImage?.bounds.height as CGFloat!) * CGFloat(reflectionRadio)
        self.reflectionImage.image = self.detailImage?.reflectedImageWithHeight(UInt(height))
        self.reflectionImage.alpha = 0.3
        //新增倒影
        self.subView?.addSubview(self.reflectionImage)

3.在翻轉的同時需要更新倒影,使倒影應用於反面,再次翻轉時需要再次更新,保證陰影跟隨主圖的變幻而變化,在控制器的翻轉方法flipImageView()中進行處理即可 。
程式碼如下。

//翻轉動畫
    func flipImageView() {
        UIView.beginAnimations(nil, context:nil)
        //平滑動畫效果
        UIView.setAnimationCurve(UIViewAnimationCurve.Linear)
        UIView.setAnimationDuration(1)
        
        var reflectionHeight: CGFloat
        var reflectedImage: UIImage?
        
        //點選正面
        if(self.frontViewIsVisible == true){
            UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.subView!, cache: true)
            self.detailImage?.removeFromSuperview()
            self.subView?.addSubview(self.detailImageFlipped)
            
            // 更新倒影
            reflectionHeight = (self.detailImageFlipped.bounds.height as CGFloat) * CGFloat(reflectionRadio)
            reflectedImage = self.detailImageFlipped.reflectedImageWithHeight(UInt(reflectionHeight))
            self.reflectionImage.image = reflectedImage
        }
        //點選反面
        else{
            UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView:self.subView!, cache:true)
            self.detailImageFlipped.removeFromSuperview()
            self.subView?.addSubview(self.detailImage!)
            
            // 更新倒影
            reflectionHeight = (self.detailImage!.bounds.height as CGFloat) * CGFloat(reflectionRadio)
            reflectedImage = self.detailImage?.reflectedImageWithHeight(UInt(reflectionHeight))
            self.reflectionImage.image = reflectedImage
        }
        //提交動畫
        UIView.commitAnimations()
        //設定是否正面顯示標識
        self.frontViewIsVisible = !self.frontViewIsVisible
    }

至此全部改造完成,完整原始碼請去第一篇下載