这篇文章算个总结吧,前面几篇都是分别单独实现的,但是当把它们整合到一起的时候,可能会出现各种手势冲突,所以这篇文章给大家介绍一个自我感觉还比较完美的demo吧。
这里我把margin实现的下拉刷新也放进去了,只是为了便于大家比较两种效果。
建议还是用scroller实现的。
反正可以切换的。
现在主要说下与单独实现相比需要改写的一些地方,主要是为了避免冲突:
MyFreshLayoutScroller.java
package com.example.refreshdemo;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.Scroller;
public class MyFreshLayoutScroller extends LinearLayout {
private int mTouchSlop;
private LinearLayout headView;
private float yDown, iyDown,xDown;
private int hideHeaderHeight;
private LayoutParams headerLayoutParams;
private MyOnFreshListener myOnFreshListener;
private ScrollView scrollView;
private boolean isCancel,isFreshing;
private ListView listView;
private boolean ableToPul;
private Scroller mScroller;
public MyFreshLayoutScroller(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
headView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.view_head, null);
headView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
hideHeaderHeight = -headView.getMeasuredHeight();
addView(headView);
mScroller = new Scroller(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if (headerLayoutParams == null) {
init();
}
}
public void setOnFreshListener(MyOnFreshListener myOnFreshListener) {
this.myOnFreshListener = myOnFreshListener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (listView != null) {
initAbleToPul();
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
iyDown = event.getRawY();
yDown = event.getRawY();
xDown = event.getRawX();
break;
case MotionEvent.ACTION_MOVE:
float yMove = event.getRawY();
float xMove = event.getRawX();
int dy = (int) (yMove - iyDown);
int dx = (int) (xMove-xDown);
boolean istoup = false;
if (listView != null) {
if(listView instanceof MyScrollListView &&((MyScrollListView)listView).isScrolling()){
return false;
}
istoup = ableToPul;
} else {
istoup = scrollView.getScrollY() == 0;
}
if (dy > 0 && istoup&&dy>Math.abs(dx)) {
return true;
}
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
yDown = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float yMove = event.getRawY();
int distance = (int) (yMove - iyDown);
if (distance <= 0) {
break;
}
int d =(int) (yDown - event.getRawY());
if(Math.abs(d)>=mTouchSlop){
smoothScrollBy(0, d, 0);
yDown = event.getRawY();
}
break;
case MotionEvent.ACTION_UP:
if(yDown-iyDown>=-hideHeaderHeight){
smoothScrollBy(0, -(int) mScroller.getFinalY() + hideHeaderHeight, 1000);
handler.postDelayed(runnable, 1100);
}else{
smoothScrollBy(0, -(int) mScroller.getFinalY(), 1000);
}
break;
default:
break;
}
return false;
}
private void init() {
headerLayoutParams = (LayoutParams) headView.getLayoutParams();
headerLayoutParams.topMargin = hideHeaderHeight;
headView.setLayoutParams(headerLayoutParams);
if (getChildAt(1) instanceof ScrollView) {
scrollView = (ScrollView) getChildAt(1);
} else if (getChildAt(1) instanceof ListView) {
listView = (ListView) getChildAt(1);
} else {
throw new IllegalArgumentException("下拉刷新只能包含一个子控件,而且该子控件必须为listview或者scrollView");
}
}
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if(myOnFreshListener!=null&&!isFreshing){
isFreshing = true;
myOnFreshListener.onFreshing();
}
}
};
private Runnable runnable2 = new Runnable() {
@Override
public void run() {
if (isCancel) {
isCancel = false;
isFreshing = false;
smoothScrollBy(0, -mScroller.getFinalY(), 1000);
}
}
};
public interface MyOnFreshListener {
void onFreshing();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
handler.removeCallbacksAndMessages(null);
}
public void cancelRefresh() {
if (!isCancel) {
isCancel = true;
handler.postDelayed(runnable2, 1000);
}
}
private void initAbleToPul() {
View firstChild = listView.getChildAt(0);
if (firstChild == null) {
ableToPul = true;
return;
}
int firstVisiblePos = listView.getFirstVisiblePosition();
ableToPul = (firstVisiblePos == 0 && firstChild.getTop() == 0);
}
// 调用此方法设置滚动的相对偏移
private void smoothScrollBy(int dx, int dy, int time) {
// 设置mScroller的滚动偏移量
if (time == 0) {
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
} else {
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, time);
}
invalidate();// 这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
}
@Override
public void computeScroll() {
// 先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset()) {
// 这里调用View的scrollTo()完成实际的滚动
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 必须调用该方法,否则不一定能看到滚动效果
invalidate();
// Log.e("tttext", mScroller.getFinalY()+"jj"+getScrollY());
// if(mScroller.getFinalY()==0&&getScrollY()==0){
// isCancel = false;
// }
}
super.computeScroll();
}
}
就是改了这里,在这里避免侧滑与下拉的手势冲突,是不是很简单!
if(listView instanceof MyScrollListView &&((MyScrollListView)listView).isScrolling()){
return false;
}
最后是下载地址:
http://download.csdn.net/detail/feiyang877647044/9484970