package com.ljp.laucher.myview; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import com.ljp.laucher.R; public class PullToRefreshListView extends LinearLayout{ public static final int STATE_IDLE = 0; public static final int STATE_PULL = 1; public static final int STATE_RELEASE = 2; public static final int STATE_LOADING = 3; private int REFRESH_VIEW_HEIGHT = 60; private int mCurRefreshViewHeight = 40; private boolean mCurReleaseState; private RotateAnimation mFlipAnimation; private float mInterceptY; private int mLastMotionY; private ListView mList; private RelativeLayout mRefreshView; private ImageView mRefreshViewImage; private TextView mRefreshViewText; private RotateAnimation mReverseFlipAnimation; private boolean mScrollingList = true; private int mState; private ProgressBar mRefreshProgress; private OnChangeStateListener mOnChangeStateListener; private int now; private Context mContext; public PullToRefreshListView(Context context) { super(context); init(context); } public PullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void applyHeaderHeight(MotionEvent ev) { final int historySize = ev.getHistorySize(); if (historySize > 0) { for (int h = 0; h < historySize; h++) { int historicalY = (int) (ev.getHistoricalY(h)); updateRefreshView((historicalY - mLastMotionY) / 2); } } else { int historicalY = (int) ev.getY(); updateRefreshView((historicalY - mLastMotionY) / 2); now = (historicalY - mLastMotionY) / 2; } } private void changeRefreshView(boolean paramBoolean) { if (mCurReleaseState != paramBoolean) { mRefreshViewImage.setImageResource(R.drawable.arrow_down); mRefreshViewImage.clearAnimation(); mRefreshViewImage.startAnimation(mReverseFlipAnimation); }else{ mCurReleaseState = paramBoolean; mRefreshViewImage.clearAnimation(); mRefreshViewImage.startAnimation(mFlipAnimation); } } private void changeState(int state) { switch (state) { case STATE_IDLE: setRefreshViewHeight(1); break; case STATE_PULL: mRefreshViewImage.setVisibility(View.VISIBLE); mRefreshProgress.setVisibility(View.GONE); mRefreshViewText.setText("继续下拉刷新"); changeRefreshView(true); break; case STATE_RELEASE: mRefreshViewImage.setVisibility(View.VISIBLE); mRefreshProgress.setVisibility(View.GONE); mRefreshViewText.setText("松手开始刷新"); changeRefreshView(false); break; case STATE_LOADING: mRefreshViewImage.setVisibility(View.GONE); mRefreshProgress.setVisibility(View.VISIBLE); mRefreshViewText.setText("正在努力的为你加载数据"); setRefreshViewHeight(80); break; } mState = state; notifyStateChanged(); } private void init(Context context) { mState = STATE_IDLE; this.mContext=context; float densityFactor = context.getResources().getDisplayMetrics().density; REFRESH_VIEW_HEIGHT *= densityFactor; setVerticalFadingEdgeEnabled(false); setVerticalScrollBarEnabled(false); mFlipAnimation = new RotateAnimation(0.0F, -180.0F, 1, 0.5F, 1, 0.5F); mFlipAnimation.setDuration(250L);mFlipAnimation.setFillAfter(true); mReverseFlipAnimation = new RotateAnimation(-180.0F, 0.0F, 1, 0.5F, 1,0.5F); mReverseFlipAnimation.setDuration(250L);mReverseFlipAnimation.setFillAfter(true); } public void setRefreshViewHeight(int height) { if (height == 1) { mRefreshView.setLayoutParams(new LayoutParams(1, 1)); } else { mCurRefreshViewHeight = height; mRefreshView.setLayoutParams(new LayoutParams( LayoutParams.FILL_PARENT, height)); } } private void updateRefreshView(int height) { if (height <= 0) { return; } if ((REFRESH_VIEW_HEIGHT / 4 <= mCurRefreshViewHeight) && (mCurRefreshViewHeight < REFRESH_VIEW_HEIGHT)) { setRefreshViewHeight(height); if(mState == STATE_IDLE){ mRefreshViewText.setText("继续下拉刷新"); mState = STATE_PULL; mRefreshViewImage.setVisibility(View.VISIBLE); mRefreshProgress.setVisibility(View.GONE); notifyStateChanged(); }else if(mState!=STATE_PULL&&mState != STATE_IDLE) changeState(STATE_PULL); } else if (mCurRefreshViewHeight > REFRESH_VIEW_HEIGHT) { if (height > REFRESH_VIEW_HEIGHT) { height = (int) (REFRESH_VIEW_HEIGHT + (height - REFRESH_VIEW_HEIGHT) * REFRESH_VIEW_HEIGHT * 2.45f / height); } setRefreshViewHeight(height); if(mState!=STATE_RELEASE) changeState(STATE_RELEASE); } else { setRefreshViewHeight(height); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_CANCEL: break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { float oldLastY = mInterceptY; mInterceptY = ev.getY(); if (mState == STATE_LOADING) { return false; } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mLastMotionY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: if (mList.getFirstVisiblePosition() == 0 && (mList.getChildCount() == 0 || mList.getChildAt(0) .getTop() == 0)) { if ((mInterceptY - oldLastY > 5) || (mState == STATE_PULL) || (mState == STATE_RELEASE)) { mScrollingList=true; break; } else { break; } }else { break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: break; } if(mScrollingList){ mScrollingList=!mScrollingList; return true; } return false; } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: applyHeaderHeight(ev); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (mState == STATE_RELEASE) { TranslateAnimation am = new TranslateAnimation(0, 0,mCurRefreshViewHeight/mContext.getResources().getDisplayMetrics().density,0); am.setDuration(300l); startAnimation(am); mList.setFocusable(false); mList.setSelected(false); mRefreshViewImage.clearAnimation(); refresh(); }else if(mState==STATE_PULL){ TranslateAnimation am = new TranslateAnimation(0, 0, now, 0); am.setDuration(300l); am.setInterpolator(AnimationUtils.loadInterpolator( getContext(), android.R.anim.accelerate_decelerate_interpolator)); startAnimation(am); changeState(STATE_IDLE); } else{ changeState(STATE_IDLE); } break; } return true; } public ListView getList() { return mList; } protected void onFinishInflate() { mRefreshView = (RelativeLayout) findViewById(R.id.refresh_view); mRefreshViewText = (TextView) findViewById(R.id.pull_to_refresh_text); mRefreshViewImage = (ImageView) findViewById(R.id.pull_to_refresh_image); mRefreshProgress = (ProgressBar) findViewById(R.id.pull_to_refresh_progress); mRefreshViewImage.setImageResource(R.drawable.arrow_down); mList = (ListView) findViewById(R.id.lv_weibo); mList.setSelected(false); mList.setFocusable(false); } private void notifyStateChanged() { if (mOnChangeStateListener != null) { mOnChangeStateListener.onChangeState(this, mState); } } public void onRefreshComplete() { mList.setFocusable(true); mList.setSelected(true); changeState(STATE_IDLE); TranslateAnimation am = new TranslateAnimation(0, 0, 80, 1); am.setDuration(600l); am.setInterpolator(AnimationUtils.loadInterpolator(getContext(), android.R.anim.accelerate_decelerate_interpolator)); startAnimation(am); } public void refresh() { changeState(STATE_LOADING); } public void clickrefresh() { TranslateAnimation am = new TranslateAnimation(0, 0, -80, 0); am.setDuration(600l); am.setInterpolator(AnimationUtils.loadInterpolator(getContext(), android.R.anim.accelerate_decelerate_interpolator)); startAnimation(am); changeState(STATE_LOADING); } public void setOnChangeStateListener(OnChangeStateListener listener) { mOnChangeStateListener = listener; } public interface OnChangeStateListener { public void onChangeState(PullToRefreshListView container, int state); } }