高仿QQlistview滑动删除+下拉刷新

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;
	}
}


OnTouchListener负责下拉刷新,思路仿照 http://blog.csdn.net/singwhatiwanna/article/details/9223363

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;  
        }  
    }

	
	
}

源码下载: 源码



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值