iScroll框架解析——Android 设备页面内 div(容器,非页面)overflow:scroll; 失效解决(转)

时间:2021-07-22 15:20:58

移动平台的活,兼容问题超多,今儿又遇到一个。客户要求在弹出层容器内显示内容,但内容条数过多,容器显示滚动条。按说是So easy,容器设死宽、高,CSS加属性

overflow:scroll;
-webkit-overflow-scrolling:touch;

完事!可拿设备去测的时候有趣了,Pc all browser正常,ios正常 ,android失效。泥马在android下效果与 overflow:hidden;一样,溢出部分隐藏了!

水平有限,用尽吃奶力各种解决未果,网上一顿乱搜,Google搜索有人说是android系统BUG,最后查到比较靠谱的解决是国外某高手开发了个JS库,名曰iScroll 4。 亲测,好用,唯独效率不敢恭维(拿别人的东西用,少TM废话)。下载地址:http://cubiq.org/iscroll-4

使用方法:
1. 引入 iscroll.js

<script type="application/javascript" src="http://istyles.blog.163.com/blog/js/iscroll.js"></script>
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('DOMContentLoaded', loaded, false);
window.onload = function() {
setTimeout(function(){ new iScroll(document.getElementById('scroller')) }, 100)
};
</script>

注明:iScroll必须在调用之前实例化

2. 添加必要的样式

<style type="text/css">
#wrapper {
position:relative;
z-index:;
height:200px; /* Desired element height */
height:200px; /* Desired element height */
overflow:/* hidden|auto|scroll */;
}
</style>

3. 容器加 id="wrapper" , 内容加 id="scroller"

<div id="wrapper">
<ul id="scroller">
<li></li>
...
<li></li>
</ul>
</div>

iscroll 需要两个参数,第一个很简单就是外容器的id,第二个参数是一个参数对象。通过这个对象可以传入iscroll的各项参数来配置iscroll。
参数基本分为四个部分

    • 基础
    • 滚动条
    • 放大缩小
    • 事件回调

-------------------------------------------俺混乱的分界线-----------------------------

iScroll框架解析(翻译)

iScroll 4 这个版本完全重写了iScroll这个框架的原始代码。这个项目的产生完全是因为移动版webkit浏览器(诸如iPhone,iPad,Android这些系统上广泛使用)提供了一种本地化的方式来对一个限定了高度和宽度的元素的内容进行滑动。很不幸的是,这种情况下所有的web应用的页面就不能够包含具有position:absolute的头、页尾或者是一个内容可滚动的中间区域。

然而,Android系统最新修订版已经可以支持这种功能了(尽管支持的力度还不是特别好),Apple公司似乎不太情愿将one-finger滑动事件运用到div元素上。

除了以前版本的iScroll的特性以外,iScroll 4还包括如下的特性:

  1. 缩放(Pinch/Zoom)
  2. 拉动刷新(Pull up/down to refresh)
  3. 速度和性能提升
  4. 精确捕捉元素
  5. 自定义滚动条

友情提示:iScroll 4并不是iScroll 3的简易替代版本,API文档已经不一样了。同时考虑到此版本正处于测试期,一些API 可能会有细微的变化。

使用指南

插件的调用需要在页面完全加载之后。你可以通过以下3种方法来实现。

iScroll对所要进行滚动的元素进行初始化,并且不限定一个页面中使用iScroll的元素的个数(这里不考虑您的硬件配置)。滚动元素中内容的类型和长度在一定程度上将会影响iScroll脚本库里可以同时使用的元素的个数。使用iScroll这个脚本库时,DOM树的结构要足够简单,移除不必要的标签,尽量避免过多的标签嵌套使用。最优的使用iScroll的结构如下所示:

<div id="wrapper">
<ul>
<li></li>
.....
</ul>
</div>

在这个小例子中,ul标签将会被滚动。iScroll一定要与滚动内容外面的wrapper进行联系才会产生效果。

【注意事项】:只有wrapper里的第一个子元素才可以滚动,如果你想要更多的元素可以滚动,那么你可以试试下面的这种写法:

<div id="wrapper">
<div id="scroller">
<ul>
<li></li>
...
</ul>
<ul>
<li></li>
...
</ul>
</div>
</div>

在这个例子中,scroller这个元素可以滚动,即便它包含两个ul元素

iScroll框架解析——Android 设备页面内 div(容器,非页面)overflow:scroll; 失效解决(转)

从上图中可以看出,wrapper之于scroller,就像viewport之于document.

iScroll必须在调用之前实例化,你可以在下面几种情况下对iScroll进行实例化(插件的调用需要在页面完全加载之后):

  1. 设置onDOMContentLoaded事件
  2. 设置onLoad事件
  3. 把调用代码放到页面的最后,以内联inline方式

下面我们逐个来讲讲这三种用法的优缺点

1. ONDOMContentLoaded

适用:滚动区域的长宽是固定的,滚动内容只包含文字、图片,并且所有的图片都有固定的尺寸

使用方法:(在head标签中添加如下代码)

<script src="iscroll.js"></script>
<script>
var myscroll;
function loaded(){
myscroll=new iScroll("wrapper");
}
window.addEventListener("DOMContentLoaded",loaded,false);
</script>

注意:myscroll这个变量是全局的,可以在任何时候调用插件,在任何地方调用它的函数

2. 设置onLoad事件

因为DOMContentLoaded事件是载入DOM结构后就会被调用,所以在图片等元素未载入前可能无法确定滚动区域的长宽,此时可以使用onLoad事件来实现。

有些时候在DOMContentLoaded的状态下就初始化iScroll其实是有点草率的,因此此时页面的资源可能还没有全部加载完毕。如果你遇到了一些很怪异的行为可以试试下面的写法:

<script src="iscroll.js"><script>
<script>
var myscroll;
function loaded(){
setTimeout(function(){
myscroll=new iScroll("wrapper");
},100 );
}
window.addEventListener("load",loaded,false);
</script>

如上代码,在页面加载完100毫秒后调用插件。如果这个时间后还有元素未完全载入导致无法计算滚动区域长宽,可能会导致错误。但这是目前最好的方法了。

这种情况下iScroll会在页面资源(包括图片)加载完毕100ms之后得到初始化,这应该是一种比较安全的调用iScroll的方式。

3. inline初始化

这种情况会在页面加载到js的时候就进行调用,此方法不推荐使用,但是很多javascript的大牛都在用这种方式,我又有什么理由不赞成呢?

<script src="iscroll.js"></script>
<div id="wrapper">
<ul>
<li></li>
...
</ul>
</div>
<script type="text/javascript">
var myscroll=new iScroll("wrapper");
</script>       

不过建议你使用一些框架的ready方法来安全调用iScroll(比如jquery里的ready())。

-------------------------------------------俺混乱的分界线-----------------------------

iScroll参数设置

iScroll里的第二个参数允许你自定义一些内容,比如下面的这段代码:

<script>
var myscroll=new iScroll("wrapper",{hScrollbar:false, vScrollbar:false});
</script>      

第二个参数通常都是一个对象,像上面的这个例子里就设定了不显示滚动条。常用的参数如下:

  • hScroll            false 禁止横向滚动 true横向滚动 默认为true
  • vScroll            false 精致垂直滚动 true垂直滚动 默认为true
  • hScrollbar       false隐藏水平方向上的滚动条
  • vScrollbar       false 隐藏垂直方向上的滚动条
  • fixedScrollbar  在iOS系统上,当元素拖动超出了scroller的边界时,滚动条会收缩,设置为true可以禁止滚动条超出scroller的可见区域。默认在Android上为true,                               iOS上为false
  • fadeScrollbar  false 指定在无渐隐效果时隐藏滚动条
  • hideScrollbar  在没有用户交互时隐藏滚动条 默认为true
  • bounce            启用或禁用边界的反弹,默认为true
  • momentum     启用或禁用惯性,默认为true,此参数在你想要保存资源的时候非常有用
  • lockDirection    false取消拖动方向的锁定, true拖动只能在一个方向上(up/down 或者left/right)为了保持资源的完整性,建议去除滚动条

-------------------------------------------俺混乱的分界线-----------------------------

各种效果的实现

1、拉动刷新(pull to refresh)

自从Twitter和一些Apple的本地化应用出现了这个效果之后,这个效果就变得非常流行。你可以看看这儿先一睹为快。我最近把"pull to refresh"这个部分单分出来作为iScroll的一个额外插件。你可以点击这儿看看pull to refresh是如何工作  滴。你只需要做的就是自定义pullDownAction()这个方法。你可能需要一个ajax来加载新的内容,不过一旦DOM树发生了变化要记得调用refresh这个方法来。需要记住的是在例子中我们加了1秒的延迟来模拟网络的延迟效果。当然,如果你不想使用这个延迟,那就把setTimeout方法去掉就行了。

2. 缩放(pinch / zoom)

我们不得不面对一个事实,那就是光有滚动其实没什么新意的。这就是为什么在iScroll 4这个版本里我们允许你可以放大和缩小。想要这个功能,只需要设置放大的参数zoom 为true即可实现利用手势来放大和缩小。你可以看看这儿。双击放大和缩小的功能在iScroll 4里也是得到支持的。要使用缩放功能,你至少需要如下配置:

var myScroll =new iScroll("wrapper",{zoom:true});

如果你想对缩放功能进行深度的自定义的话可以使用下面的一些选项:

zoomMax   指定允许放大的最大倍数,默认为4

【注意事项】:如果想要图片缩放的效果很好的话要把他们放到硬件的合成层中。通俗点说,就是在所有需要缩放的img元素上使用-webkit-transform:translate3d(0,0,0)来实现,而且尤为重要的是,硬件的加速会占用大量资源,要谨慎使用,否则你的应用可能就此崩溃。

3. 捕捉元素(snap and snap to element)

SNAP功能是判断元素是否滑动到指定位置。通过这个效果可以制作花哨的跑马灯效果。插件会自动分析滚动区域内相同标签或相同大小的元素做为捕捉对象,也可以通过参数指定捕捉的对象

捕捉的功能会促使scroller去重新定义位置,这样可以制作更加花哨的传送带效果。点击这里有个小例子。默认情况下,iScroll将scroller分成四分体,或者是相同大小的wrapper。iScroll 4加入了这个属性允许捕捉scroller里的 任何元素,不考虑外部wrapper的大小。如果你想要实现这样的传送带效果,我建议你使用“quadrant”分割。最佳的设置如下:

 var myscroll=new iScroll("wrapper",{
snap:true,
momentum:false,
hScrollbar:false,
vScrollbar: false
});              

可以通过设置snap参数为指定标签来设定捕捉对象。比如捕捉li标签

         var myscroll=new iScroll("wrapper",{
snap:"li",
momentum:false,
hScrollbar:false,
vScrollbar:false
});      

在这个例子中scroller可以捕捉到滚动区域中最左上角的li元素

在snap属性的值为指定标签的时候,插件会通过 scroller.querySelectorAll(snap_string)的方法来获取对象。所以要注意不要写成"$scroller li",这是错误的。只要写'li'。

3. 自定义滚动条(custom scrollbars)

在iScroll 4这个版本中,可以利用一系列的css来自定义滚动条的呈现。可以给滚动条添加一个class参数,如下:

                  var myscroll=new iScroll("wrapper",{scrollbarClass: "myScrollbar"});

你可以点击这里看一个小例子,在这个小例子里,myScrollbarH这个类被添加到了水平滚动条上,myScrollbarV这个类则被添加给了垂直方向上的滚动条上了。需要提醒的是,滚动条是由两个元素组合而成的:容器和显示器。容器同wrapper的高度相同,而显示器则代表的是滚动条本身。

滚动条的HTML结构如下:

<div class="myScrollbarV">
<div></div>
</div> .myscrollbarV{
position:absolute;z-index:100;width:8px;bottom:7px;top:2px;right:1px;
} .myScrollbarV > div {
position:absolute;
z-index:100;
width:100%;
/* The following is probably what you want to customize */
background:-webkit-gradient(linear, 0 0, 100% 0, from(#f00), to(#900));
border:1px solid #800;
-webkit-background-clip:padding-box;
-webkit-box-sizing:border-box;
-webkit-border-radius:4px;
-webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
}                 

内部方法:

iScroll还提供了一些公共方法。比如说refresh。在改变滚动区域里内容的时候都必须调用refresh方法。因为iScroll是通过实例化一个全局变量来实现的,所以使用者可在任何情况下调用这些方法。

调用方法: myScroll.name_of_the_function(参数)

  1. refresh                     在DOM树发生变化时,应该调用此方法
  2. scrollTo()                 滚动到某个位置         eg: myscroll.scrollTo(0,10,200,true);
  3. scrollToElement()      滚动到某个元素         eg: myscroll.scrollToElement("li:nth-child(10)",100);
  4. detroy()                   完全消除myscroll及其占用的内存空间          eg: myscroll.destroy()

1、refresh方法

iScroll需要知道滚动区域的大小和滚动条才能正常工作。在实例化的时候iScroll会自动计算一次。但如果滚动区域里的内容发生变化后,需要告诉iScroll内容发生了变化。

每次改变元素的高度/宽度或以任何方式修改(如: appendChild或innerHTML的)HTML结构时,浏览器会重新渲染页面。javascript就需要重新分析新的DOM结构和新的属性,有时候,这个不是即时的。

为了确保javascript分析新的页面,可以实例化一个新的iScroll。

ajax('page.php', onCompletion);
function onCompletion () {
setTimeout(function () {
myScroll.refresh();
}, 0);
};

2、JAVASCRIPT SCROLLING

iScroll还提供了scrollTo, scrollToElement和scrollToPage三个方法让你能够通过javascript来控制滚动效果。

scrollTo(x, y, time, relative):在指定的time时间内让内容滚动条x/y的位置。如myScroll.scrollTo(0, -100, 200) 在200毫秒内Y轴向下滚动100像素。 myScroll.scrollTo(0, 10, 200, true)可以实现相对当前位置在200毫秒内Y轴向上滚动10像素的效果。

scrollToElement(element, time):在指定的时间内滚动到指定的元素。如myScroll.scrollToElement('li:nth-child(10)', 100) 在100毫秒内滚动到第10个li元素的位置。第1个参数可以用CSS3中的选择器来筛选元素。

snapToPage(pageX, pageY, time):在200毫秒内从第1页滚动到第2页(0代表第1页,1代表第2页)。这个使用SNAP功能的时候可以调用这个函数。

3、注销iScroll

通过调用destroy()函数下注销iScroll来释放内存。

myScroll.destroy(); myScroll = null;

4、LITE版iScroll

如果你只希望在移动设备中使用iScroll,请使用iscroll-lite.js

LITE版是一个精简版,它支持移动设备(没有桌面兼容性)滚动。所占的资源更少。

iScroll的发展方向

  • 表单域的支持
  • 缩放的优化
  • 更好的桌面浏览器的兼容性
  • onScrol事件的优化
  • 加个哈希值的变化
  • DOM改变后自动刷新

转载: