Hero閱讀

Hero

HeroTransitions/Hero: Elegant transition library for iOS & tvOS

Hero是一個(gè)自定義轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的框架。自定義跳轉(zhuǎn)自然是用了UIViewControllerInteractiveTransitioning嗅辣,Hero通過(guò)hero id對(duì)VC進(jìn)行解藕票编,同時(shí)也依賴(lài)hero id進(jìn)行UI變換,默認(rèn)實(shí)現(xiàn)是分扎,在路由時(shí)荆残,進(jìn)行截圖窝爪,然后拉伸

a在Hero里看見(jiàn)了Chameleon,懷念顾画,不過(guò)確實(shí)沒(méi)人維護(hù)了

因?yàn)槭菍?duì)截圖做變換,Hero的Transition主要是view的尺寸兆解、位置變化馆铁,而內(nèi)容的維護(hù)需要自己控制,比如我在A VC的hero id為"ironMan"的view內(nèi)增加了一個(gè)label锅睛,在轉(zhuǎn)場(chǎng)時(shí)埠巨,可以看到label被拉伸,并且现拒,如果在B VC中沒(méi)有添加這個(gè)label辣垒,那就會(huì)在視覺(jué)上丟失;同理在B VC印蔬,我把hero id為"ironMan"的view設(shè)置了另一個(gè)背景色勋桶,就會(huì)看到在路由結(jié)束之后,View突然從粉色變成灰色侥猬,沒(méi)有漸變


Simulator Screen Recording - iPhone SE (3rd generation) - 2022-08-11 at 13.32.28.gif

從代碼中例驹,看到有個(gè)Extension HeroContext,印證了之前的判斷:

extension HeroContext {
  /**
   - Returns: a snapshot view for animation
   */
  public func snapshotView(for view: UIView) -> UIView {
    // ...
  }
}

當(dāng)然退唠,把"ironMan" 設(shè)置為不使用快照之后(redView.hero.modifiers = [.useNoSnapshot])再?lài)L試鹃锈,就沒(méi)有那種明顯的拉伸感了。

Simulator Screen Recording - iPhone SE (3rd generation) - 2022-08-11 at 13.31.53.gif

Hero有兩個(gè)關(guān)鍵入口函數(shù):startanimate

Start函數(shù)比較長(zhǎng)瞧预,簡(jiǎn)單來(lái)說(shuō)包括:

  • 提取一張全屏快照屎债,用來(lái)防閃爍
  • 提取fromViews和toViews,標(biāo)準(zhǔn)是非hidden的view(會(huì)考慮容器和子view)并提取modifiers (HeroContext.process(views:,idMap:))寫(xiě)入<UIView, HeroTargetState>字典targetStates
  • processors處理fromViews和toViews垢油,這里有IgnoreSubviewModifiersPreprocessor盆驹、ConditionalPreprocessor、DefaultAnimationPreprocessor滩愁、MatchPreprocessor躯喇、SourcePreprocessor、CascadePreprocessor六個(gè)處理器硝枉,其中MatchPreprocessor以fromViews和toViews有id映射(MatchPreprocessor.process(fromViews:toViews:))為標(biāo)準(zhǔn)寫(xiě)入<UIView, HeroTargetState>字典targetStates玖瘸,SourcePreprocessor 提取剛才獲得的字典的view的參數(shù)(position、opacity檀咙、shadow等)
  • 提取animatingFromViews和animatingToViews雅倒,標(biāo)準(zhǔn)是字典 targetStates[view]的HeroTargetState有值
  • 調(diào)用animate()開(kāi)始動(dòng)畫(huà)

再看看HeroTransition的animate函數(shù):

extension HeroTransition {
  open func animate() {
    guard state == .starting else { return }
    state = .animating

    if let toView = toView {
      context.unhide(view: toView)
    }

    // auto hide all animated views
    for view in animatingFromViews {
      context.hide(view: view)
    }
    for view in animatingToViews {
      context.hide(view: view)
    }

    var totalDuration: TimeInterval = 0
    var animatorWantsInteractive = false

    if context.insertToViewFirst {
      for v in animatingToViews { _ = context.snapshotView(for: v) }
      for v in animatingFromViews { _ = context.snapshotView(for: v) }
    } else {
      for v in animatingFromViews { _ = context.snapshotView(for: v) }
      for v in animatingToViews { _ = context.snapshotView(for: v) }
    }

    // UIKit appears to set fromView setNeedLayout to be true.
    // We don't want fromView to layout after our animation starts.
    // Therefore we kick off the layout beforehand
    fromView?.layoutIfNeeded()

    for animator in animators {
      let duration = animator.animate(fromViews: animatingFromViews.filter({ animator.canAnimate(view: $0, appearing: false) }),
                                      toViews: animatingToViews.filter({ animator.canAnimate(view: $0, appearing: true) }))
      if duration == .infinity {
        animatorWantsInteractive = true
      } else {
        totalDuration = max(totalDuration, duration)
      }
    }

    self.totalDuration = totalDuration
    if let forceFinishing = forceFinishing {
      complete(finished: forceFinishing)
    } else if let startingProgress = startingProgress {
      update(startingProgress)
    } else if animatorWantsInteractive {
      update(0)
    } else {
      complete(after: totalDuration, finishing: true)
    }

    fullScreenSnapshot?.removeFromSuperview()
  }
}
  • hide隱藏了所有animatingFromViews和animatingToViews
  • 拍攝快照。
  • 調(diào)用animator實(shí)現(xiàn)動(dòng)畫(huà)

這個(gè)是簡(jiǎn)單例子弧可,app store的例子就要復(fù)雜很多和好看很多蔑匣。


Simulator Screen Recording - iPhone SE (3rd generation) - 2022-08-12 at 13.48.45.gif

在實(shí)現(xiàn)上多了很多細(xì)節(jié)劣欢,通過(guò)modifiers去實(shí)現(xiàn)細(xì)致的定制效果
首先還是通過(guò)hero id去做“復(fù)用”,也因此第二個(gè)cell不會(huì)在animatingFromViews裁良,要知道context.fromViews.count有24個(gè)凿将,但animatingFromViews只有兩個(gè),原因就在于价脾,MatchPreprocessor在處理的時(shí)候牧抵,從24個(gè)fromViews和15個(gè)toViews中,只匹配到了兩對(duì)id
同時(shí)侨把,不在from view里的detail label犀变,因?yàn)橛衜odifiers,在前面所述的提取fromViews和toViews步驟中秋柄,也被捕獲

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末获枝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子骇笔,更是在濱河造成了極大的恐慌省店,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笨触,死亡現(xiàn)場(chǎng)離奇詭異懦傍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)芦劣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)谎脯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人持寄,你說(shuō)我怎么就攤上這事∮榘常” “怎么了稍味?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)荠卷。 經(jīng)常有香客問(wèn)我模庐,道長(zhǎng),這世上最難降的妖魔是什么油宜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任掂碱,我火速辦了婚禮,結(jié)果婚禮上慎冤,老公的妹妹穿的比我還像新娘疼燥。我一直安慰自己,他們只是感情好蚁堤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布醉者。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撬即。 梳的紋絲不亂的頭發(fā)上立磁,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音剥槐,去河邊找鬼唱歧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛粒竖,可吹牛的內(nèi)容都是我干的颅崩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼温圆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挨摸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起岁歉,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤得运,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锅移,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體熔掺,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年非剃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了置逻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡备绽,死狀恐怖券坞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肺素,我是刑警寧澤恨锚,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站倍靡,受9級(jí)特大地震影響猴伶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塌西,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一他挎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捡需,春花似錦办桨、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贸街。三九已至,卻和暖如春狸相,著一層夾襖步出監(jiān)牢的瞬間薛匪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工脓鹃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逸尖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓瘸右,卻偏偏與公主長(zhǎng)得像娇跟,于是被迫代替她去往敵國(guó)和親仲墨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唁盏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

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