没耐心的直接拿demo吧,下载(1分)
很多地方都会有listview下拉刷新数据,上拉加载更多的需求
网上找了一大堆,讲的都不是太明白,自己弄了一个下午勉强实现了,部分地方有一些BUG,欢迎探讨
首先是布局文件
整个页面分为三块,一个是中间的listview,上面的是下拉后显示的等待框,下面是上拉后显示的等待框
设定两个等待框的高度为0隐藏起来,再设定listview的布局在updatecontent的下方,waitcontent的上方
布局代码如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/updatecontent"
android:layout_width="wrap_content"
android:layout_height="1dp" >
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/RelativeLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/waitcontent"
android:layout_below="@+id/updatecontent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true" >
</ListView>
</RelativeLayout>
<RelativeLayout
android:id="@+id/waitcontent"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
</RelativeLayout>
接下来是上拉下拉的实现,
设定了listview有5种状态
public enum ListState //listview的状态
{
Normal, //一般
InBottom, //在最底部,再向上滑动就要获取数据
PullUp, //向上滑动中
Rflesh, //获取数据中
InTop, //在最顶部,再向下滑动就要更新数据
PullDown //向下滑动中
}
关系如下
渣工具,渣画法,大家凑活着看
核心思路在于,
为listview注册监听函数,在滑动过程中(MotionEvent.ACTION_MOVE)检测listview是否在顶部,或者底部
如果在顶部则跳到InTop状态,记录当前的触摸位置,如果继续滑动则跳到PullDown状态,用现在的触摸高度减去前面记录的高度
然后不断的设定updatecontent的高度,高度为前面减得的值,将listview挤下去
松手后(MotionEvent.ACTION_UP) 将updatecontent重新设为0隐藏起来
然后就可以开始更新数据
上拉加载也是同样的思路
核心代码如下
listView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_UP:
TouchUp(event);
break;
case MotionEvent.ACTION_MOVE:
TouchMove(event);
break;
};
//两种状态可以使listview滑动,其他状态则直接吃掉触摸事件,使listview不能滑动
if(state==ListState.Normal||state==ListState.InTop)
{
return false;
}
else
{
return true;
}
}
});
//滑动过程中事件的处理
protected void TouchMove(MotionEvent event) {
double height; //要设定的控件高度
int postion=listView.getLastVisiblePosition();
int f_postion=listView.getFirstVisiblePosition();
boolean isbottom=((postion+1)==list.size()); //是否在底部
boolean istop=(f_postion==0); //是否在顶部
switch(state.ordinal())
{
case 0: //正常
if(isbottom)
{
state=ListState.InBottom;
}
if(istop)
{
state=ListState.InTop;
}
break;
case 1: //在底部,准备上拉
bottomPostion=event.getY();
state=ListState.PullUp;
break;
case 2: //上拉过程中
height=bottomPostion-event.getY();
setWaitContent(height);
break;
case 3: //更新过程中
break;
case 4: //在顶部准备下拉
if(event.getY()>lasttop&&lasttop!=0) //判断是否是向下拉动
{
toppostion=event.getY();
state=ListState.PullDown;
}
lasttop=event.getY();
break;
case 5:
if(event.getY()>lasttop) //防止抖动
{
height=event.getY()-toppostion;
setUpdateContent(height);
lasttop=event.getY();
}
break;
}
}
protected void TouchUp(MotionEvent event) {
switch(state.ordinal())
{
case 0: //正常
state=ListState.Normal;
break;
case 1: //在底部,准备上拉
state=ListState.Normal;
break;
case 2: //上拉过程中
state=ListState.Rflesh;
setWaitContent(0); //不显示下方等待框
addListData(); //增加数据
state=ListState.Normal;
break;
case 3: //更新过程中
state=ListState.Normal;
break;
case 4: //在最顶部
state=ListState.Normal;
lasttop=0;
break;
case 5: //向下拖动中
setUpdateContent(0);
state=ListState.Normal;
lasttop=0;
break;
}
}
private void setUpdateContent(double height) {
if(height<0)
return;
if(height>150)
height=150;
LayoutParams params = (LayoutParams) UpdateLayout.getLayoutParams();
params.height=(int)height;
UpdateLayout.setLayoutParams(params);
}
另一个设置控件高度的代码基本一致
BUG在于,上拉加载的时候即使设定控件高度,listview也不会被挤上去,只会被覆盖
下拉刷新时会有抖动,所做做了个防止抖动的判断但是不知道为什么
额,希望大家多交流吧
demo下载(1分)