iOS swift交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)闹炉,提高動(dòng)畫(huà)與用戶交互性郎嫁,從而提升用戶體驗(yàn)奕筐。
通過(guò)手勢(shì)闽颇、重力感覺(jué)等交互操作非凌,使原本連貫的動(dòng)畫(huà)分解呛占,逐漸變化晌姚。

思路:
把原本的動(dòng)畫(huà)的過(guò)渡屿储,抽象成百分比形式(UIPercentDrivenInteractiveTransition協(xié)議實(shí)現(xiàn)原理)鹊奖,與交互操作的變化系數(shù)關(guān)聯(lián)起來(lái)店展。

UIPercentDrivenInteractiveTransition

UIViewControllerInteractiveTransitioning 協(xié)議為我們提供一系列便利的方法养篓,可以通過(guò)一個(gè)百分比控制交互切換的過(guò)程


api.png

從系統(tǒng)的api可以看出,交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)兼容iOS7以上

  • update(float)
    更新動(dòng)畫(huà)進(jìn)度的百分比赂蕴,一般通過(guò)手勢(shì)識(shí)別長(zhǎng)度計(jì)算出的值
  • cancel ( )
    取消交互柳弄,返回切換前的狀態(tài)
  • finish ( )
    完成交互,更新到切換后的狀態(tài)

demo

【交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)】概说,是建立在【非交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)】的基礎(chǔ)之上
【非交互式】只需要提供present和dismiss的動(dòng)畫(huà)即可
【交互式】則需要在【非交互式】基礎(chǔ)上多提供--交互式動(dòng)畫(huà)控制器

ps: <a href = "http://www.reibang.com/p/4e9ccd0699fb">非交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)</a>碧注,我之前也有文章涉及,這里就不作細(xì)述

新建一個(gè)工具類(lèi)繼承于UIPercentDrivenInteractiveTransition糖赔,實(shí)現(xiàn)交互切換的協(xié)議

import UIKit

//判斷是【交互式】還是【非交互式】
private var isInteractive = false

//判斷是presented還是dismiss
private var isPresenting  = false

class MenuTransitionHepler: UIPercentDrivenInteractiveTransition,UIViewControllerAnimatedTransitioning,UIViewControllerTransitioningDelegate {
    
    //step.4
    //實(shí)現(xiàn)UIPercentDrivenInteractiveTransition交互切換協(xié)議
    //present切換啟動(dòng)手勢(shì)
    private var enterPanGesture: UIScreenEdgePanGestureRecognizer!
    
    //present交互動(dòng)畫(huà)控制器
    var sourceViewController : UIViewController! {
        didSet{
            self.enterPanGesture = UIScreenEdgePanGestureRecognizer()
            self.enterPanGesture.addTarget(self, action: #selector(MenuTransitionHepler.handelOnStagePan(pan:)))
            self.enterPanGesture.edges=UIRectEdge.left
            self.sourceViewController.view.addGestureRecognizer(self.enterPanGesture)
            
        }
    }
    
    //present手勢(shì)長(zhǎng)度比率萍丐,控制動(dòng)畫(huà)進(jìn)度
    func handelOnStagePan(pan:UIPanGestureRecognizer){
        
        let view_transition = pan.translation(in: pan.view!.superview)
        //手勢(shì)滑動(dòng)長(zhǎng)度與屏幕寬度的比率,用于控制切換動(dòng)畫(huà)進(jìn)度
        let d = view_transition.x / (pan.view?.bounds.width)! * 0.5
        
        
        print(d)
        
        switch pan.state {
        case UIGestureRecognizerState.began:
            isInteractive=true
            //調(diào)用fromVC調(diào)用present方法放典,此方法是storyboard的線跳
            self.sourceViewController.performSegue(withIdentifier: "presentMenu", sender: self)
            
            break
        case UIGestureRecognizerState.changed:
            //更新切換動(dòng)畫(huà)進(jìn)度
            self.update(d)
            
            break
        default:
            isInteractive = false
            if(d > 0.2){
                //更新動(dòng)畫(huà)到完成狀態(tài)
                self.finish()
            }
            else {
                //返回動(dòng)畫(huà)到切換前的狀態(tài)
                self.cancel()
            }
            break
        }
        
    }
    
    //dismiss切換啟動(dòng)手勢(shì)
    private var exitPanGesture: UIPanGestureRecognizer!
    
    //dismiss交互動(dòng)畫(huà)控制器
    var menuViewController: UIViewController! {
        didSet {
            self.exitPanGesture = UIPanGestureRecognizer()
            self.exitPanGesture.addTarget(self, action:#selector(MenuTransitionHepler.handleOffstagePan(pan:)))
            self.menuViewController.view.addGestureRecognizer(self.exitPanGesture)
        }
    }
    
    //dismiss手勢(shì)長(zhǎng)度比率逝变,控制動(dòng)畫(huà)進(jìn)度
    func handleOffstagePan(pan: UIPanGestureRecognizer){
        let view_transition = pan.translation(in: pan.view!)
        
        let d = view_transition.x / (pan.view?.bounds.width)! * -0.5
        
        switch pan.state {
        case UIGestureRecognizerState.began:
            isInteractive=true
            self.menuViewController.dismiss(animated: true, completion: nil)
            
            break
        case UIGestureRecognizerState.changed:
            self.update(d)
            
            break
        default:
            isInteractive = false
            if(d > 0.1){
                self.finish()
            }
            else {
                self.cancel()
            }
            break
        }
    }
    
}

上述代碼中,主要實(shí)現(xiàn)幾個(gè)功能:
1奋构、添加present和dismiss的動(dòng)畫(huà)切換控制器(即VC)
2壳影、為VC添加交互手勢(shì)
3、設(shè)置手勢(shì)響應(yīng)方法声怔,判斷手勢(shì)狀態(tài)更新切換進(jìn)度

在MenuTransitionHepler工具類(lèi)最外面态贤,添加 UIViewControllerTransitioningDelegate的實(shí)現(xiàn)方法

 

//step.1
//UIViewControllerTransitioningDelegate代理方法
extension MenuTransitionHepler{
    //presented
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        isPresenting=true
        return self
    }
    
    //dismissed
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        isPresenting=false
        return self
    }
    
    func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return isInteractive ? self : nil
    }
    
    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return isInteractive ? self : nil
    }
}

接下來(lái)就是實(shí)現(xiàn)非交互切換的方法(交互式切換需要實(shí)現(xiàn)此方法),這里就賣(mài)個(gè)關(guān)子醋火,感興趣的童鞋可以看demo源碼

最后在fromVC設(shè)置自定義present的動(dòng)畫(huà)控制器和代理

 

import UIKit

class fromVC: UIViewController {

    //step.5
    //初始化自定義轉(zhuǎn)場(chǎng)動(dòng)畫(huà)協(xié)議對(duì)象
    let transitionHelper = MenuTransitionHepler()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //step.6
        //設(shè)置轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的fromVC
        self.transitionHelper.sourceViewController=self
    }
    
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        //step.7
        //設(shè)置轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的toVC
        let menu = segue.destination as! MenuVC
         
        //step.8
        //設(shè)置transitioningDelegate為【自定義轉(zhuǎn)場(chǎng)協(xié)議】
        menu.transitioningDelegate = self.transitionHelper

        self.transitionHelper.menuViewController = menu
    }
    
}

finish悠汽!如果在左邊緣開(kāi)始滑動(dòng)箱吕,效果如下圖:P

效果圖.gif

總結(jié)

總體來(lái)說(shuō),iOS7后實(shí)現(xiàn)轉(zhuǎn)場(chǎng)動(dòng)畫(huà)確實(shí)很方便

非交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)柿冲,實(shí)現(xiàn)轉(zhuǎn)場(chǎng)協(xié)議茬高,設(shè)置動(dòng)畫(huà)時(shí)間、動(dòng)畫(huà)邏輯假抄、動(dòng)畫(huà)實(shí)現(xiàn)即可

交互式轉(zhuǎn)場(chǎng)動(dòng)畫(huà)怎栽,則在非交互式的基礎(chǔ)上,多設(shè)置動(dòng)畫(huà)控制器(VC)宿饱、觸發(fā)交互的方法

附帶 <a >Demo</a>傳送門(mén)熏瞄,demo實(shí)現(xiàn)效果比較簡(jiǎn)單,后期也有改成側(cè)滑框架的可能

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谬以,一起剝皮案震驚了整個(gè)濱河市强饮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌为黎,老刑警劉巖邮丰,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異铭乾,居然都是意外死亡剪廉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)炕檩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)斗蒋,“玉大人,你說(shuō)我怎么就攤上這事捧书〈蹬荩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵经瓷,是天一觀的道長(zhǎng)爆哑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)舆吮,這世上最難降的妖魔是什么揭朝? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮色冀,結(jié)果婚禮上潭袱,老公的妹妹穿的比我還像新娘。我一直安慰自己锋恬,他們只是感情好屯换,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般彤悔。 火紅的嫁衣襯著肌膚如雪嘉抓。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,692評(píng)論 1 305
  • 那天晕窑,我揣著相機(jī)與錄音抑片,去河邊找鬼。 笑死杨赤,一個(gè)胖子當(dāng)著我的面吹牛敞斋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疾牲,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼植捎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了阳柔?” 一聲冷哼從身側(cè)響起鸥跟,我...
    開(kāi)封第一講書(shū)人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盔沫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枫匾,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡架诞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了干茉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谴忧。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖角虫,靈堂內(nèi)的尸體忽然破棺而出沾谓,到底是詐尸還是另有隱情,我是刑警寧澤戳鹅,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布均驶,位于F島的核電站,受9級(jí)特大地震影響枫虏,放射性物質(zhì)發(fā)生泄漏妇穴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一隶债、第九天 我趴在偏房一處隱蔽的房頂上張望腾它。 院中可真熱鬧,春花似錦死讹、人聲如沸瞒滴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)妓忍。三九已至虏两,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間单默,已是汗流浹背碘举。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搁廓,地道東北人引颈。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像境蜕,于是被迫代替她去往敵國(guó)和親蝙场。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容