1. 程式人生 > >如何基於WKWebView開發一個功能完善的資訊內容頁

如何基於WKWebView開發一個功能完善的資訊內容頁

可能 方便 styles 運行 文本框 是我 優雅 pan 主題樣式

前言

對於資訊類的APP來說 良好的閱讀體驗是必不可少的, 那麽如何去開發一個功能完善的資訊文章頁面就是本文要說的重點.
相信本文會對很多在做同類功能開發的道友們有很大的幫助 , 如果某只大佬路過也歡迎指點一二.

廢話不多說 開講(chui)~

分析

數據

對於圖文混排的富文本形式 , 最好最通用的數據格式當屬 HTML , 再加上 CSS 和 JS 的配合, 可以隨心所欲的展示出成百上千在不同的樣式.
當然 , 除了 HTML 也不排除有使用其他規則的數據格式來表示.
但這裏我們還是選擇使用 HTML 的數據格式 , 畢竟主流嘛.

展示

我們常見的有幾種方式來實現富文本的展示

  • UIWebView
    對於這個控件我們並不陌生, 基於UIKit框架, 使用方式簡單, 但是任何東西都有缺點, 無解的內存問題一直讓人很頭疼, 而且因為接口限制 可以做的東西也不多, 他更適合做一些普通的Web瀏覽操作.

  • WKWebView
    iOS8後的強大Web控件, 基於WebKit框架, 有豐富的API, 更高的性能, 更小的內存 更小的內存 更小的內存等, 當然缺點也是必不可少, 例如Cookie問題 白屏問題 樣式異常問題等等, 不過這些問題隨著時間的推移 當然難不倒偉大的猴子們, 其實我個人認為 iOS9之後的WebKit才是真正的WebKit (iOS8的是假的) , 在克服了重重奇葩的BUG後 我還是決定使用WKWebView來作為HTML的展示控件 , 這裏不多說 後面再談.

  • CoreText
    強大的核心文本框架 , iOS中幾乎所有文字的東東都是通過它來實現的. 這麽強大的框架實現一個圖文混排當然不在話下, 可是重點是如何解析HTML的樣式來讓CoreText知道該怎麽做! 這一點的代表我覺得非 DTCoreText 莫屬了, 它可以解析HTML中的大部分樣式 通過CoreText繪制出來 當然例如一些圖片和視頻等元素 可以通過UIImageView等原生控件來顯示, 灰常666 , 但是! 這種強行的轉換對於很多復雜的HTML來說肯定力不從心的, 對於HTML的支持肯定是不如WebView的, 不過簡單的還是應對自如 , 這裏不多說 , 以後我會抽時間寫一個基於它來展示文章的Demo.

功能

那麽確定了數據格式和展現方式 , 現在我們來說一說功能.
一個文章頁面應該包含哪些功能呢?

  • 字號調節
    因每個人的閱讀習慣不同 字號調節這個功能當然也是必不可少 , 動態的改變字體大小.

  • 離線閱讀
    這個功能的目的在於用戶對於收藏過的或者加載過的文章能夠在網絡不佳或無網絡的情況下繼續閱讀 , 實現的重點在於文章數據的持久化緩存.

  • 日夜間模式(黑白主題樣式)
    我個人覺得日夜間的閱讀模式是最基本的兩種 , 更好的是可以動態改變字體樣式和背景顏色或背景圖 , 以滿足不同用戶的體驗 , 當然這也是分產品的 , 讀書類的產品當然是要有的 因為長時間的沈浸式閱讀對於這方面的體驗需求是很細膩的 , 可是對於資訊新聞類的產品卻並不是必須的 因為這類產品的用戶偏向於舒適快速的閱讀 .
    實現重點在於動態改變文字大小和背景的顏色以及優雅自然的過渡.

  • 圖片瀏覽
    當然這個必不可少, 用戶在對感興趣的圖片可以進行放大等方式查看 , 並且可以保存到相冊等等.

  • 圖片狀態
    這個不得不說一下 , 每個圖片的顯示從無到有都是分為不同的狀態 例如: 初始加載 - 加載中 - 加載完成 - 加載失敗 - 點擊加載等等 , 對於每個狀態的處理我相信很多人都會忽略掉 , 就拿加載失敗來說 , 我見過太多APP的文章圖片加載失敗了顯示出來一個裂圖或是問號圖 , 真的惡心 , 如果就想看這個圖 只能退出這個頁面 從新進來看能不能出來 , 這樣的體驗是灰常糟糕的 , 在開發時你可能不會在意 畢竟一個圖片加載失敗的概率並不高 可能從開發開始到結束發版都沒遇到過一次 , 但是我想說 細節決定成敗, 有良好的提示 對於那些網絡不佳的用戶們來說無疑是最貼心的.

  • 流量優化
    這個很重要 , 用戶們灰常在意自己的流量問題 (因為流量 == 錢) , 對於縮略圖的處理是必不可少的 , 合理的控制可以節省大量不必要的流量消耗 , 對於省流量模式(僅Wifi網絡加載圖片)的控制的確是某些用戶的剛需 , 這點對於動輒幾MB的GIF圖尤為重要 , 沒有哪個用戶喜歡用幾十分鐘就花掉100MB流量的APP , 如果這樣的APP還沒被卸載 說明用戶可能一直沒用過. 實現重點在於如何區分該加載的類型 如何有效的利用已經加載過的圖片.

  • 橫豎屏適配
    這點並不是必需的 , 還是如果能支持當然是最好了, 實際需不需要還是要看產品本身 , 因為對於某些產品來說 橫屏並不是一個好的選擇.

開發思路

我們分析完了所包含的功能和要使用的展現形式 , 現在就該整理一下開發的思路了.

首先我們要了解所使用的控件的特性以及要註意的問題 , 根據控件的特性找出最佳的實現方法 , 結合上面我們所提到的功能 我來敘述一下我的開發思路:

文章內容的數據格式是HTML , 使用WKWebView 來加載HTML展現內容.

通常來說 服務端的接口數據並不會把一個完整的HTML字符串給我們 , 而是只有內容部分的HTML字符串 , 基本上是這樣的格式:

<p>女朋友和她姐姐是雙胞胎,總是分不清!</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/6eee549a554b1d66409)
<p>貓:喜歡猴子養一個唄,在這折騰我幹嘛?</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_3/19/a3b81ed6cff11fa4658.gif)
<p>一看就知道是只痛快狗!</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_3/19/99c786d4b149effb163.gif)
<p>被這個槍電一下不知道會不會死</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/8bff874e8d875c75083.gif)
<p>今天我們要練習帶球撞人</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/6280e10eeeca7e28181.gif)
<p>居然翻車了,一定不是純血的阿三</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/0a594d192a861b94511.gif)
<p>可以吹一輩子了,那麽我看你怎麽拿下來</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/da49d9ad2345eb34986.gif)
<p>藍翔畢業典禮</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/86e383fac9e24d15935.gif)
<p>請問這鎖有何用?</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/987a7cab7cfe1e79269.gif)
<p>兄弟你有毛病啊~有話直說何必要動手動腳呢~</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/5c11b1c7185d2141335.gif)
<p>一秒就擊倒了……不會是演戲吧?</p>
![](http://img.xxxxxxxxxxxxx.com/crawl/1707_9/19/17eeea5639b2f31b856.gif)
<p><span>開心一刻</span></p>
<p>帶女朋友回家見家長:“媽,這是我女朋友。”媽打量了女朋友一番說:“你咋找個這樣的?”女朋友瞬間臉色就變了,我趕緊打圓場。“媽,她是我女朋友,說話客氣點,我們是真心相愛的。”沒想到,媽拉過女朋友說:“閨女你那麽漂亮,你咋找個這樣的,這讓我咋跟你爸媽交待……”</p>

這樣做的好處是可以讓我們更方便的擴展和調整 , 拿到這些後 我們首先要處理這些字符串 根據需要替換修改 , 最後組裝成一個完整的HTML , 然後交給WKWebView顯示 , 完整的HTML格式大致如下:

<html>
<head>
<meta http-equiv ="Content-Type" content="text/html;charset=utf-8"/>
<meta name = "viewport" content="width = device-width, initial-scale = 1, user-scalable=no"/>                           
<title></title>
<link href="../css/style.css" rel="stylesheet" type="text/css"/>
<script src="../js/jquery.min.js"></script>
</head>
<body>
<div class="content">
<!-- 內容 -->
</div>                           
</body>                        
</html>

為了實現離線閱讀 那麽就要做到圖片下載的可控, 這裏我們可以將頁面圖片的加載放到原生端來做, 也就是說不通過WebView加載圖片, 而是通過原生加載圖片的方式來加載頁面中的圖片, 這樣做有幾點好處:

  1. 原生加載可控性更高 可以更好掌控下載進度 以及下載完成後對圖片的其他處理.
  2. 圖片緩存的利用率更好, 圖片下載完成以後 Web頁面可以使用 原生的圖片瀏覽頁也可以使用.
  3. 圖片緩存的大小更方便統計以及清理等等.

雖然好處多多 , 但是這樣做法並不適用於任何Web頁面, 因為別人的HTML寫法天知道什麽樣子, 你很難去處理, 所以說 這種方法僅僅適用於固定樣式 固定HTML寫法的情況.

優點和缺點講完了, 我現在簡單闡述一下實現Web頁面圖片原生加載的大致流程.

首先在HTML給WebView加載之前, 要將所有需要使用原生加載的<img>標簽過濾出來 , 並且得到每個<img>標簽的真實圖片地址, 也就是src屬性的值, 然後在<img>標簽中添加一個自定義屬性data-original將真實圖片地址設置為它的值, 同時將src的屬性值設置為默認的占位圖本地圖片地址...

<img>標簽修改完成後 , 就可以交給WebView去加載了, 這樣一來沒有圖片要加載的頁面加載速度會大幅度提高, 在頁面加載完成後, 就可以開始下載圖片了.

通過JS獲取到所有需要下載的<img>標簽的data-original屬性值 (真實的圖片地址), 然後通過原生加載圖片的方式進行下載, 下載完成後將圖片緩存到本地(沙盒), 最後使用JS將每個圖片對應的 <img>標簽的src屬性設置成本地的圖片緩存地址. 此時WebView頁面中就會顯示本地的緩存圖片了.

大致思路就是這樣 , 具體實現起來會涉及到很多細節, 例如WKWebView控件的特性問題, 例如縮略圖的處理, 圖片加載的控制, Gif圖片加載的進度等等 , 這裏不多啰嗦, Demo已經完成, 內附有比較完善的流程圖, 大家可以結合這個思路去閱讀代碼 運行Demo 自行體會.

如何基於WKWebView開發一個功能完善的資訊內容頁