<p>关于使用可见:滚动到底部或顶部响应的ScrollView使用</p><p>Demo APK 可以方便的查看效果,在各大应用商店搜索 trinea android 下载即可,如:Google Play。</p><p></p><p>两种实现方式的主要不同点在于判断滑动位置的地方,第一种方式在onScrollChanged函数中判断, 第二种在OnTouchListener的onTouch中判断。其他如是否滚动到边缘的判断、响应事件接口OnBorderListener、对外暴露的接口都一样。</p><p>第一种方式代码可见onScrollChanged BorderScrollView</p><p>第二种方式代码可见OnTouchListener BorderScrollView</p><p></p><p>1、判断是否已经滚动到顶部或底部,代码如下:</p><p>Java</p><pre class="brush:java;toolbar:false">privatevoiddoOnBorderListener(){
if(contentView!=null&&contentView.getMeasuredHeight()<=getScrollY()+getHeight()){
if(onBorderListener!=null){
onBorderListener.onBottom();
}
}elseif(getScrollY()==0){
if(onBorderListener!=null){
onBorderListener.onTop();
}
}
}
privatevoiddoOnBorderListener(){
if(contentView!=null&&contentView.getMeasuredHeight()<=getScrollY()+getHeight()){
if(onBorderListener!=null){
onBorderListener.onBottom();
}
}elseif(getScrollY()==0){
if(onBorderListener!=null){
onBorderListener.onTop();
}
}
}</pre><p>滚动到顶部判断:getScrollY() == 0</p><p>滚动到底部判断</p><p>View contentView = getChildAt(0);</p><p>contentView.getMeasuredHeight() <= getScrollY() + getHeight();</p><p>View contentView = getChildAt(0);</p><p>contentView.getMeasuredHeight() <= getScrollY() + getHeight();</p><p>其中getChildAt表示得到ScrollView的child View,因为ScrollView只允许一个child view,所以contentView.getMeasuredHeight()表示得到子View的高度, getScrollY()表示得到y轴的滚动距离,getHeight()为scrollView的高度。当getScrollY()达到最大时加上scrollView的高度就的就等于它内容的高度了啊~</p><p></p><p>2、定义到达顶部和底部响应事件接口OnBorderListener,包含onTop和onBottom函数</p><p>Java</p><pre class="brush:java;toolbar:false">/**
*OnBorderListener,Calledwhenscrolltotoporbottom
*
*@authorTrinea2013-5-22
*/
publicstaticinterfaceOnBorderListener{
/**
*Calledwhenscrolltobottom
*/
publicvoidonBottom();
/**
*Calledwhenscrolltotop
*/
publicvoidonTop();
}
/**
*OnBorderListener,Calledwhenscrolltotoporbottom
*
*@authorTrinea2013-5-22
*/
publicstaticinterfaceOnBorderListener{
/**
*Calledwhenscrolltobottom
*/
publicvoidonBottom();
/**
*Calledwhenscrolltotop
*/
publicvoidonTop();
}</pre><p>这个接口允许用户自定义到达底部和顶部的响应事件</p><p></p><p>第一种方式: 在onScrollChanged函数中判断,主要代码如下:</p><p>Java</p><pre class="brush:java;toolbar:false">@Override
protectedvoidonScrollChanged(intx,inty,intoldx,intoldy){
super.onScrollChanged(x,y,oldx,oldy);
doOnBorderListener();
@Override
protectedvoidonScrollChanged(intx,inty,intoldx,intoldy){
super.onScrollChanged(x,y,oldx,oldy);
doOnBorderListener();
}</pre><p>在ScrollView的onScrollChanged函数中判断是否到达顶部和底部,并进行相应事件调用,onScrollChanged函数在ScrollView中内容开始滚动时出发被调用。</p><p></p><p></p><p>第二种方式: 在OnTouchListener的onTouch中判断,主要代码如下:</p><p>Java</p><pre class="brush:java;toolbar:false">this.onBorderTouchListener=newOnTouchListener(){
@Override
publicbooleanonTouch(Viewv,MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_UP:
doOnBorderListener();
break;
}
returnfalse;
}
};
this.onBorderTouchListener=newOnTouchListener(){
@Override
publicbooleanonTouch(Viewv,MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_UP:
doOnBorderListener();
break;
}
returnfalse;
}
};</pre><p>表示在touch结束后,手指拿起时执行doOnBorderListener,进行判断和响应。</p><p></p><p>两种方式的比较:</p><p>第一种方式精确度高,但doOnBorderListener可能执行多次,因为ScrollView滑动中,onScrollChanged总是在不停被调用,需要用户自己做并发控制,也可以参考DropDownListView的写法让用户在自定义Listener执行结束后手动调用onBottomComplete函数。</p><p></p><p>第二种方式不会造成doOnBorderListener多次执行,但却可能一次都没有调用。比如你快速滑动,还未到达底部手指已经松开,由于惯性滚动到底部,可能并不会执行doOnBorderListener。因为onTouch的ACTION_UP事件在手指松开已经接收到这时候却还没有到达底部。</p><p>两种方式各有优劣,大家可酌情选择。我要求准确响应,所以选择了第一种,自己再做下控制确保不会多次执行。</p>