SweepListView,item滑动listview代码
public class SweepListView extends ListView{
private SweepLayout mDownView;
private SweepLayout mLastDownView;
private int mDownX, mDownY;
private boolean mInterceptlEvent = false;
private int mSlop;
private final static int TAN = 2;
private int mState = INIT_STATE;
private final static int INIT_STATE = 0; //初始状态
private final static int HORIZONTAL_STATE = 1; //item在水平滚动状态
private final static int VERTICAL_STATE = 2; //item在垂直滚动状态
private int mScrolledState = NO_VIEW_SCROLLED;
private final static int NO_VIEW_SCROLLED = 3; //没有item处于scroll状态
private final static int CURRENT_VIEW_SCROLLED = 4; //当前的item处于scroll状态(点击的item为scroll的item)
private final static int LAST_VIEW_SCROLLED = 5; //上一个item处于scroll状态
private boolean mIsListViewCanPull = true;
private int mScrollState = 0;
private int mMinFlingVelocity;
private int mMaxFlingVelocity;
private VelocityTracker mVelocityTracker;
private int mFirstVisiblePosition;
private View mHeaderView;
@SuppressLint("Recycle")
public SweepListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
ViewConfiguration vc = ViewConfiguration.get(context);
mSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
mVelocityTracker = VelocityTracker.obtain();
this.setOnScrollListener(new OnScrollListener(){
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
mScrollState = scrollState;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
mFirstVisiblePosition = firstVisibleItem;
}
});
mHeaderView = View.inflate(getContext(), R.layout.header, null);
this.addHeaderView(mHeaderView);
}
public View getHeaderView(){
return this.mHeaderView;
}
public boolean canPull(){
return (mFirstVisiblePosition == 0) && mIsListViewCanPull;
}
@Override
public boolean onTouchEvent(MotionEvent event){
//if(mPull) return true;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mDownX = (int)event.getX();
mDownY = (int)event.getY();
mDownView = (SweepLayout)getPointTouchView(mDownX, mDownY);
mState = INIT_STATE;
mScrolledState = NO_VIEW_SCROLLED;
if(mDownView != null){
if(mDownView.getScrollState()){
mScrolledState = CURRENT_VIEW_SCROLLED;
}
}
if(mDownView != mLastDownView){
if(mLastDownView != null){
if(mLastDownView.getScrollState()){
mScrolledState = LAST_VIEW_SCROLLED;
mLastDownView.shrik(100);
mDownView = null;
}
}
}
if(mState == INIT_STATE) mInterceptlEvent = false;
mVelocityTracker.addMovement(event);
if(mScrollState == OnScrollListener.SCROLL_STATE_FLING) {
return super.onTouchEvent(event);
}
return true;
case MotionEvent.ACTION_MOVE:
if(mScrolledState == LAST_VIEW_SCROLLED || mScrolledState == CURRENT_VIEW_SCROLLED) mInterceptlEvent = true;
if(mDownView == null) break;
if(mScrollState == OnScrollListener.SCROLL_STATE_FLING) break;
int deltaX = (int)event.getX() - mDownX;
int deltaY = (int)event.getY() - mDownY;
if(Math.abs(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) >= Math.pow(mSlop, 2) && (float)Math.abs(deltaX) / Math.abs(deltaY) > TAN){
mState = HORIZONTAL_STATE;
mInterceptlEvent = true;
mIsListViewCanPull = false;
} else if(Math.abs(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) >= Math.pow(mSlop, 2) && (float)Math.abs(deltaX) / Math.abs(deltaY) <= TAN){
if(mState != HORIZONTAL_STATE) mState = VERTICAL_STATE;
}
if(mState != HORIZONTAL_STATE) break;
int distance = 0;
if(mScrolledState == CURRENT_VIEW_SCROLLED){
distance = mDownView.getHolderWidth() - deltaX;
}else{
distance = 0 - deltaX;
}
if(distance > mDownView.getHolderWidth()) distance = mDownView.getHolderWidth();
if(distance < 0) distance = 0;
mVelocityTracker.addMovement(event);
mDownView.scrollTo(distance, 0);
mDownView.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
boolean showSlide = false;
if(mDownView != null && mDownView.getScrollX() > 0.3 * mDownView.getHolderWidth()){
showSlide = true;
}else{
showSlide = false;
}
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = mVelocityTracker.getXVelocity();
float velocityY = mVelocityTracker.getYVelocity();
if (mMinFlingVelocity <= Math.abs(velocityX) && Math.abs(velocityX) <= mMaxFlingVelocity && Math.abs(velocityY) < Math.abs(velocityX)){
if(velocityX <= 0) showSlide = true;
else showSlide = false;
}
if(mScrolledState == CURRENT_VIEW_SCROLLED && mState != HORIZONTAL_STATE) {
mInterceptlEvent = true;
showSlide = false;
}
if(mDownView != null && showSlide){
mDownView.showSlide(100);
}else if(mDownView != null){
mDownView.shrik(100);
}
if(mScrolledState == LAST_VIEW_SCROLLED){
mInterceptlEvent = true;
}
mLastDownView = mDownView;
if(mDownView == null || !mDownView.getScrollState()){
mIsListViewCanPull = true;
}else{
mIsListViewCanPull = false;
}
mDownView = null;
mVelocityTracker.clear();
break;
}
if(mInterceptlEvent) {
return true;
}
return super.onTouchEvent(event);
}
private View getPointTouchView(int x, int y){
Rect rect = new Rect();
for(int i = 0; i < this.getChildCount(); i ++){
View view = this.getChildAt(i);
view.getHitRect(rect);
if(rect.contains(x, y)) {
return view;
}
}
return null;
}
}
public class PullOnTouchListener implements OnTouchListener {
private SweepListView mListView;
private View mRefreshView;
private ImageView mArrow;
private TextView mRefreshInfo;
private ProgressBar mRefreshProgressBar;
private Animation animation, reverseAnimation;
private int mDownX, mDownY;
private boolean mPull;
private final static int RELEASE_TO_REFRESH = 0;
private final static int PULL_TO_REFRESH = 1;
private final static int REFRESHING = 2;
private final static int DONE = 3;
private int mState;
private int mRefreshHeight = 100;
private boolean isBack;
public PullOnTouchListener(SweepListView listView, View refreshView){
mListView = listView;
animation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(250);
animation.setFillAfter(true);
reverseAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reverseAnimation.setInterpolator(new LinearInterpolator());
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);
mRefreshView = refreshView;
mArrow = (ImageView)mRefreshView.findViewById(R.id.arrow);
mRefreshInfo = (TextView)mRefreshView.findViewById(R.id.refresh_info);
mRefreshProgressBar = (ProgressBar)mRefreshView.findViewById(R.id.head_progressBar);
mRefreshHeight = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, mRefreshHeight, mRefreshView.getContext().getResources()
.getDisplayMetrics()));
mState = DONE;
}
private static Handler handler = new Handler();
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(!mListView.canPull()) return false;
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mDownX = (int)event.getRawX();
mDownY = (int)event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int)event.getRawX() - mDownX;
int deltaY = (int)event.getRawY() - mDownY;
if(deltaY < 0) {
mRefreshView.getLayoutParams().height = 0;
mRefreshView.requestLayout();
return false;
}
if(Math.abs(deltaY) > Math.abs(deltaX)){
mPull = true;
}
if(mPull){
//mListView.onStartPull();
//mListView.onPullToRefresh(deltaY);
if(mState == RELEASE_TO_REFRESH){
if(deltaY < mRefreshHeight){
isBack = true;
mState = PULL_TO_REFRESH;
changeHeaderViewByState();
}
}
if(mState == PULL_TO_REFRESH){
if(deltaY >= mRefreshHeight){
mState = RELEASE_TO_REFRESH;
changeHeaderViewByState();
}
}
if(mState == DONE){
mState = PULL_TO_REFRESH;
changeHeaderViewByState();
}
mRefreshView.getLayoutParams().height = deltaY;
mRefreshView.requestLayout();
return true;
}
break;
case MotionEvent.ACTION_UP:
if(mPull){
mPull = false;
//mListView.onFinishPull();
if(mState == RELEASE_TO_REFRESH){
mState = REFRESHING;
mRefreshView.getLayoutParams().height = mRefreshHeight;
mRefreshView.requestLayout();
changeHeaderViewByState();
handler.postDelayed(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
mRefreshView.getLayoutParams().height = 0;
mRefreshView.requestLayout();
mState = DONE;
changeHeaderViewByState();
}
}, 2000);
}
if(mState == PULL_TO_REFRESH){
mState = DONE;
mRefreshView.getLayoutParams().height = 0;
mRefreshView.requestLayout();
changeHeaderViewByState();
}
//mListView.onFinishPull();
isBack = false;
return true;
}
break;
}
return false;
}
private void changeHeaderViewByState()
{
switch (mState)
{
case RELEASE_TO_REFRESH:
mArrow.setVisibility(View.VISIBLE);
mRefreshInfo.setVisibility(View.VISIBLE);
mRefreshProgressBar.setVisibility(View.GONE);
mArrow.clearAnimation();
mArrow.startAnimation(animation);
mRefreshInfo.setText("下拉刷新");
break;
case PULL_TO_REFRESH:
mArrow.setVisibility(View.VISIBLE);
mRefreshInfo.setVisibility(View.VISIBLE);
mRefreshProgressBar.setVisibility(View.GONE);
mArrow.clearAnimation();
// 是由RELEASE_To_REFRESH状态转变来的
if (isBack) {
isBack = false;
mArrow.clearAnimation();
mArrow.startAnimation(reverseAnimation);
}
mRefreshInfo.setText("下拉刷新");
break;
case REFRESHING:
mArrow.clearAnimation();
mArrow.setVisibility(View.GONE);
mRefreshInfo.setVisibility(View.VISIBLE);
mRefreshInfo.setText("正在刷新");
mRefreshProgressBar.setVisibility(View.VISIBLE);
break;
case DONE:
mArrow.setVisibility(View.VISIBLE);
mRefreshInfo.setVisibility(View.VISIBLE);
mRefreshProgressBar.setVisibility(View.GONE);
break;
}
}
}
源码下载: 源码