如何基于WKWebView开发一个功能完善的资讯内容页

前言

对于资讯类的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 自行体会.

时间: 2024-10-11 20:09:12

如何基于WKWebView开发一个功能完善的资讯内容页的相关文章

基于SpringBoot开发一个Restful服务,实现增删改查功能

在去年的时候,在各种渠道中略微的了解了SpringBoot,在开发web项目的时候是如何的方便.快捷.但是当时并没有认真的去学习下,毕竟感觉自己在Struts和SpringMVC都用得不太熟练.不过在看了很多关于SpringBoot的介绍之后,并没有想象中的那么难,于是开始准备学习SpringBoot. 在闲暇之余的时候,看了下SpringBoot实战以及一些大神关于SpringBoot的博客之后,开始写起了我的第一个SpringBoot的项目.在能够对SpringBoot进行一些简单的开发Re

Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1)

Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1) 本文转载至深入理解Cocos2d-x 3.x:一步一步通过ClippingNode实现一个功能完善的跑马灯公告(1) 这篇文章主要是通过一步一步实现一个功能完善的跑马灯公告来展示ClippingNode的用法并且最终深入ClippingNode的源码,了解其实现原理. 首先,先介绍一下ClippingNode,ClippingNode也叫裁剪节点,能将一些内容通过使用模板裁剪出来显示在界面上,可以实现一些

【深入了解cocos2d-x 3.x】一步一步通过ClippingNode实现一个功能完善的跑马灯公告(1)

这篇文章主要是通过一步一步实现一个功能完善的跑马灯公告来展示ClippingNode的用法并且最终深入ClippingNode的源码,了解其实现原理. 首先,先介绍一下ClippingNode,ClippingNode也叫裁剪节点,能将一些内容通过使用模板裁剪出来显示在界面上,可以实现一些很炫酷的效果.来看看今天要实现的效果 1.ClippingNode类分析 先来看看ClippingNode的声明文件 看看其中的public方法 class CC_DLL ClippingNode : publ

基于Django开发一个BBS案例

一.数据库表设计(models.py文件) #!/usr/bin/env python # -*- coding:utf-8 -*- from __future__ import unicode_literals from django.db import models #导入django用户认证表 from django.contrib.auth.models import  User # Create your models here. class Article(models.Model)

iOS开发UI篇—无限轮播(功能完善)

iOS开发UI篇—无限轮播(功能完善) 一.自动滚动 添加并设置一个定时器,每个2.0秒,就跳转到下一条. 获取当前正在展示的位置. 1 [self addNSTimer]; 2 } 3 4 -(void)addNSTimer 5 { 6 // NSTimer timerWithTimeInterval:<#(NSTimeInterval)#> target:<#(id)#> selector:<#(SEL)#> userInfo:<#(id)#> repe

基于c++11新标准开发一个支持多线程高并发的网络库

背景 新的c++11标准出后,c++语法得到了很多的扩展,比起以往任何时候都要灵活和高效,提高了程序编码的效率,为软件开发人员节省了不少的时间. 之前我也写过基于ACE的网络服务器框架,但ACE毕竟有些臃肿,内部对象关系错综复杂,容易给人造成只见树木不见森林的错觉. 所以打算用c++11开发一个较为简洁,高效,支持高并发的网络库. 开源         花了两三周,终于把基础的结构开发完成,代码也开源在github上,网址是 https://github.com/lichuan/fly 欢迎各位

基于ASP.NET MVC的快速开发平台,给你的开发一个加速度!

基于ASP.NET MVC的快速开发平台,给你的开发一个加速度! bingo炸了 2017/4/6 11:07:21 阅读(37) 评论(0) 现在的人做事情都讲究效率,最好能达到事半功倍那种效果,软件行业也不例外.但是需求的一再变动,架构和业务功能的一改再改,往往使得软件的开发事倍功半.软件行业急需突破现现状,所以快速开发框架就这么应运而生了.但是市面上快速开发框架种类繁多,今天我给大家带来的是一套界面风格简洁大方.多业务功能.基于ASP.NET+MVC的快速开发框架. 体验地址我会在下文附上

软件工程团队开发——第一次冲刺会议总结,数据库设计,及功能完善

时间:2015年5月16日 地点:学一食堂二楼 与会人员:全部组员 第一次冲刺已结束,我们的订餐软件只实现了最基础的功能,而且没有优化界面,很多功能有待完善.为了方便以后的开发和功能的整合,今天晚上我们进行了数据库的设计,设计好数据库,表以及表的内容,以后大家都使用同样的名字. 下图是我们进行的数据库设计: 下图是我们对功能设计的完善(包括实现的和未实现的及待定的): 附:合照

整合了一个功能强大完善的OA系统源码,php全开源 界面漂亮美观

整合了一个功能强大完善的OA系统源码,php全开源界面漂亮美观.需要的同学联系Q:930948049