簡介: 隨着移動互聯網設備和技術的發展,各類移動設備屏幕尺寸層出不窮,摺疊屏、分屏、懸浮窗等等,面對愈來愈多樣的屏幕,若是爲每種尺寸單獨進行適配,不只費時費力,還會增長端側代碼的開發與維護壓力。如何讓一套代碼適配全部尺寸變化,加強App的通用能力?阿里巴巴文娛技術 氚雨 將分享優酷APP在iOS響應式佈局技術上的實踐和落地。數據結構
響應式是基於同一套代碼,開發一個APP可以兼容多尺寸、多終端設備的顯示,可以動態調整頁面的佈局以及容器的佈局,充分利用當前屏幕的尺寸,爲用戶提供更好的瀏覽體驗,提高APP開發效率和迭代效率。架構
當下,iOS端的主要尺寸類型有五種:iPhone、iPad豎屏、iPad橫屏、iPad浮窗、iPad分屏。一般,App是按iPhone尺寸開發的,須要適配剩餘的四種iPad尺寸。app
iPad橫、豎屏比較常見,旋轉設備便可,比較特殊的是浮窗和分屏模式。自蘋果iPad iOS 9開始,用戶在打開一個應用時,從最底部上滑打開Dock,便可拖拽另外一個App進入浮窗模式:框架
在支持分屏的iPad上拖拽到更邊緣的地方便可開啓分屏模式:佈局
其中浮窗模式全部升級iOS 9的設備都支持,分屏模式只有最新版的硬件設備iPad mini 四、iPad Air 2及iPad Pro支持:性能
響應式佈局的核心是設計統一的適配規則,並在屏幕尺寸發生變化時按佈局規則從新佈局,以適配不一樣屏幕尺寸,而大多數App在開發時通常只有適配iPhone的版本,在經過響應式適配更多機型時主要要解決三個方面的問題,即如何獲取、更新響應式狀態以進行對應的適配,如何計算在不一樣屏幕寬度下App內容的寬度、列數等佈局參數,如何進行響應式下的數據處理以解決較難適配的組件、減小頁面留白等,基於此咱們開發了響應式佈局SDK,負責統一管理響應式狀態、處理佈局邏輯、裁剪映射數據等。ui
App除了配置爲universal版以外,要支持浮窗或分屏模式還須要進行一些配置:阿里雲
(1)須要提供LaunchScreen.storyboard做爲啓動圖,因爲App支持的運行尺寸太多,再也不適合用圖片做爲啓動圖。spa
(2)須要在info.plist中配置支持全部屏幕方向:設計
(3)注意不能勾選Requires full screen配置項或配置UIRequiresFullScreen爲YES,如此會聲明App要求全屏運行,天然表示不支持浮窗或分屏:
(4)支持分屏要求App的主Window須要使用系統UIWindow,不能繼承,而且要經過init方法或initWithFrame:[UIScreen mainScreen].bounds方式初始化。
經過以上步驟開啓浮窗、分屏能力後,在App內就沒法再經過相關代碼控制設備方向,以往經過以下代碼可控制ViewController爲豎屏,而支持分屏後以下方法系統再也不調用,默認全部ViewController支持全部屏幕方向:
以下強制設置屏幕方向的黑方法也已失效:
這種設計的主要緣由是,當一個App支持分屏後,就再也不單獨佔用整個屏幕,當另外一個App同時運行時,同一塊屏幕不可能出現一個橫屏、另外一個豎屏。此類問題沒有完美的解決方案,爲了保證用戶體驗,支持分屏的App必須全部頁面適配全部屏幕方向,這也體現了蘋果對用戶體驗的極致追求,參見DeveloperForums中開發人員的討論:
https://developer.apple.com/forums/thread/19578
響應式狀態管理
響應式狀態提供了當前是否開啓響應式、響應式佈局尺寸類型、當前佈局window尺寸等相關狀態量,響應式SDK會在屏幕尺寸變化後更新響應式狀態,並經過系統通知和自定義通知機制,通知相關業務方。
// 響應式開啓關閉狀態 typedefNS_ENUM(NSInteger, YKRLLayoutStyle) { YKRLLayoutStyleNormal =0, // 響應式狀態關閉 YKRLLayoutStyleResponsive =1, // 響應式狀態開啓}; // 響應式屏幕尺寸類型,頁面可依據此類型區分是否分屏等 typedefNS_ENUM(NSInteger, YKRLLayoutSizeType) { YKRLLayoutSizeTypeS =0, // eg. phone pad浮窗 YKRLLayoutSizeTypeL =1, // pad YKRLLayoutSizeTypeXL =2, // 預留 }; // 響應式屏幕狀態類型(一共有十種類型) typedefNS_OPTIONS(NSUInteger, YKRLLayoutScreenType) { YKRLLayoutScreenTypeUnknown = (1<<0), //未知 YKRLLayoutScreenTypePortrait = (1<<1), //豎屏全屏 YKRLLayoutScreenTypeLandscapeLeft = (1<<2), //橫屏全屏左 … … };
響應式SDK聲明瞭YKRLLayoutStyle、YKRLLayoutSizeType、YKRLLayoutScreenType三種枚舉狀態標記當前的響應式狀態,分別表示響應式開啓關閉狀態,當前尺寸類型及具體屏幕類型,通常業務方只須要獲取是不是響應式設備狀態,對於在不一樣寬度下頁面佈局不一致的業務方能夠經過尺寸類型狀態進行區分適配,而對於須要具體知道當前屏幕狀態的業務方能夠經過屏幕類型獲取,屏幕類型只包含當前iOS設備已支持的屏幕狀態,隨着設備類型的豐富,如出現摺疊屏等,屏幕類型會做相應擴展。每當設備旋轉或用戶開啓分屏時,響應式SDK都會在系統回調中更新當前響應式狀態,並通知業務方響應式狀態的改變。
響應式佈局規則
優酷響應式佈局規則主要包含列數適配規則、寬度適配規則等,好比多列均分組件的列數在不一樣屏幕寬度下是可變的,響應式SDK會根據當前的響應式狀態輸出合適的佈局列數等,對於每個佈局規則,響應式SDK中都有相應的佈局適配邏輯,響應式佈局規則知足優酷App總體UI規範,業務方直接指定本身所須要的規則便可,除少數特殊規則以外,大部分佈局規則都用於組件列數和組件寬度佈局,此類響應式佈局規則中會指定一個標準寬度,並根據組件原始佈局列數和標準寬度計算出組件標準寬度,進而根據當前屏幕寬度計算出適配後的組件列數,可用以下公式表達:
響應式適配列數(標準屏幕寬度下組件列數) = (當前屏幕寬度÷(標準屏幕寬度÷標準屏幕寬度下組件列數×scale))
其中,scale爲組件放大參數,標準屏幕寬度下組件原寬度投放到iPad上會太小,能夠經過scale參數進行適當放大。
對於組件寬度適配,響應式規則會先計算標準屏幕寬度下的組件列數並進行列數適配,再經過適配後的列數計算適配寬度:
響應式適配寬度(標準屏幕寬度下組件寬度) = (當前屏幕寬度 - 邊距間距)÷響應式適配列數(標準屏幕寬度÷標準屏幕寬度下組件寬度)
在以上公式中調整標準屏幕寬度及組件放大scale便可獲得適配效果較好的通用佈局規則,通過設計同窗在各類設備尺寸下的調整總結,當前優酷中使用的標準屏幕寬度爲440dp,scale爲1.2倍,適配效果最佳。組件適配邏輯已在響應式SDK佈局規則中統一實現,業務方直接調用便可,也方便設計同窗對整個App的組件適配進行統一調整。
響應式SDK中YKRLCompLayoutManager類封裝了相關佈局邏輯,業務方也可經過YKRLCompLayoutAdapterProtocol協議二次處理,以定製響應式佈局邏輯,在App統一架構中直接調用YKRLCompLayoutManager的相關接口便可獲取按照響應式規則計算後的佈局參數,如列數、寬度等,當監聽響應式狀態發生變化時從新佈局便可完成響應式佈局。
響應式數據處理
響應式數據處理包括數據映射、數據過濾、數據合併、數據補齊,數據處理邏輯兩端一致,詳細介紹能夠參見:一個APP如何適配多個Android終端?,下面簡單介紹一下iOS響應式數據映射的實現。
有些組件沒法經過規則適配不一樣的屏幕尺寸,好比在手機上佔整個屏幕寬度的組件(下圖左側帶視頻播放預定組件),若是採用等比放大的適配規則,在iPad端會顯得過大,此類組件能夠映射成相對簡單的組件,以適配不一樣的屏幕尺寸。
優酷採用了統一抽象的數據結構,在組件映射方面比較容易實現,只需修改對應的組件標誌便可。得益於統一架構的廣泛推廣和使用,咱們在統一架構內添加了組件映射能力,方便各業務方調用,響應式SDK中提供了數據裁剪映射規則,業務方能夠查詢、增長相應的裁剪映射規則。對於未接入統一架構的業務方則須要業務方實現相關數據處理。
優酷響應式業務流程兩端一致,響應式佈局須要進行數據處理、響應式狀態管理、觸發佈局等工做,優酷響應式SDK會在接口返回後處理相關數據,爲統一架構提供相應佈局接口,監控屏幕尺寸變化並觸發佈局等。
iOS開發中常常採用絕對佈局,而實現響應式的主要工做是將「絕對佈局」修改成「相對佈局」,接入工做較安卓更爲繁瑣。
iOS響應式能夠按Window->ViewController->容器->組件的層級完成接入。
Window在配置支持分屏後會由系統自動佈局,在RootViewController樹中的子ViewController也會隨Window自動佈局,而特殊ViewController,如多tab頁面的子ViewController等,未加入RootViewController樹,須要手動修改成相對佈局,頁面可經過Autoresizing或監聽響應式狀態實現相對佈局。
接入統一架構的頁面容器由統一架構提供,統一架構容器的佈局列數管理、佈局寬度管理等都已接入響應式SDK,爲業務方接入減小了大量工做,業務方只需指定自身所採用的佈局規則便可,ViewController和容器實現相對佈局後,每當屏幕尺寸變化時響應式SDK會通知容器從新佈局,變換組件列數或寬度等,組件卡片只須要按容器提供的尺寸進行佈局便可。
組件卡片內通常使用Frame絕對佈局,須要修改成相對佈局,簡單的佈局邏輯可使用Autoresizing實現,方便快捷,複雜的佈局可使用AutoLayout或Masonry等自動佈局框架(性能較差)實現,也能夠在layoutSubviews方法中從新計算佈局,業務方能夠選擇合適的方式實現自動佈局,以減小接入成本。
對於未接入統一架構的頁面則須要在本頁面佈局邏輯中手動接入響應式SDK相關佈局接口。
落地過程當中發現許多組件卡片佈局時依賴了屏幕寬度,不符合響應式開發規範,致使適配響應式時工做量較大。每一層View只應依賴父層View佈局,各層View實現相對佈局後,每當屏幕尺寸改變時各層View會自動適配,同時容器的組件列數和尺寸會按響應式規則進行適配,一套代碼便可適配全部屏幕尺寸,實現響應式佈局。
目前優酷全端已具有響應式佈局的能力,八月份已上線universal版本,一套代碼支持iPhone、iPad豎屏、iPad橫屏、浮窗、各類比例分屏,爲用戶提供了更好更豐富的用戶體驗。
響應式能力是多端投放能力的第一步,優酷實現響應式佈局後對開發、設計和產品都提出了更高的要求,同時鑑於iPad低端設備佔比較高,業務開發過程當中不只要考慮通投能力,更要求App始終保持更高的性能和穩定性,這是咱們持續在努力的。
蘋果2020年末將推出基於ARM架構的MacBook,也有媒體曝光,蘋果正在申請摺疊屏相關的專利,相信將來蘋果設備的尺寸會愈來愈豐富,App適配提效是繞不開的話題,而優酷響應式的開發極大擴展了iPhone版App的適用場景,是解決多種設備支持的更好途徑,爲適應將來更復雜的設備場景打下堅實基礎。
原文連接本文爲阿里雲原創內容,未經容許不得轉載。