今天一天做了一个仿照网易的下拉刷新,先上效果图:
代码还有一点问题。我先说怎么用把:
1. 布局文件。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<com.flyme.mylistview.PullTop
android:paddingTop="30dip"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="180dip"
/>
<com.flyme.mylistview.PullToRefreshLayout
android:id="@+id/move"
android:text="@string/hello_world"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:divider="@null"
android:dividerHeight="0dip"
android:background="#ffffff"
android:id="@+id/mlistview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</com.flyme.mylistview.PullToRefreshLayout>
</RelativeLayout>
我写的是PullToRefreshLayout,在这个继承了RelativeLayout的类中,只能添加一个ListView布局。
PullTop则是显示的红标题,这个可以随意的添加。
2.主要类就是PullToRefreshLayout类了,我觉得在主要的难点依然是手势的控制。
直接上代码:
分发手势:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = stateY = (int) ev.getRawY();
return super.dispatchTouchEvent(ev);
case MotionEvent.ACTION_MOVE:
return dispatchMoveTouch(ev);
case MotionEvent.ACTION_UP:
return dispatchUpTouch(ev);
}
return super.dispatchTouchEvent(ev);
}
private boolean dispatchMoveTouch(MotionEvent ev){
if (getScrollY() < 0 ) {
onTouchEvent(ev);
return true;
}
if (verdictLocation()){
int moveY = (int) ev.getRawY();
int dy = moveY - startY;
if (dy > 16 ){
onTouchEvent(ev);
return true ;
}
}
startY = (int) ev.getRawY();
return super.dispatchTouchEvent(ev);
}
private boolean dispatchUpTouch(MotionEvent ev){
int moveY = (int) ev.getRawY();
if (Math.abs((moveY - stateY)) < 16) {
return super.dispatchTouchEvent(ev);
}
if (getScrollY() < - minDistance) {
startMove(getScrollY(),minDistance);
if (!isRefreshing) {
if (mPullToRefreshListener != null) {
isRefreshing = true ;
mPullToRefreshListener.onRefresh();
}
}
totelDistance = 0 ;
return true;
}else {
if (!isRefreshing) {
startMove(getScrollY() ,0);
return super.dispatchTouchEvent(ev);
}
if (isRefreshing && !verdictLocation()) {
return super.dispatchTouchEvent(ev);
}
totelDistance = 0 ;
return true ;
}
} 处理手势:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
return super.onTouchEvent(event);
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (verdictLocation()){
pullListView(event);
return true;
}else {
return super.onTouchEvent(event);
}
}
return super.onTouchEvent(event);
}
private void pullListView(MotionEvent event){
int moveY = (int) event.getRawY();
int dy = slowPullDy(startY - moveY);
scrollTo(0, dy + getScrollY());
startY = (int) event.getRawY();
if (mPullToDistanceListener != null && !isRefreshing) {
mPullToDistanceListener.pullDistance(Math.abs(totelDistance));
}
}
这些都是核心的代码。
3.代码中的主要问题,已知的bug:
1)可以从效果图上看出来,在手势按下去的一刻,ListView中的Item是被选中的状态,你下拉的时候是正常的下拉,但是当你的手指松开的时候,Item的选中状态依然是选中的。我分析的原因是,我在MotionEvent.DOWN 的时候,返回的super.dispatchTouchEvent,导致的选中状态。这个是不可避免的。因为我尝试在Move的时候去调用ListVIew的分发方法,但是没效果。如果直接返回true,则ListVIew就不会接受事件了。
有哪位大牛能够解决这个问题,请及时的不吝赐教告知,谢谢。
附上源码下载地址:http://pan.baidu.com/s/1dDENnHZ
我的github上也可以下载。
我的github地址:https://github.com/flyme2012