package com.cheng.animationstudy.customview.autohome; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.AbsListView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.cheng.animationstudy.R; import com.cheng.utils.ViewFinder; /** * Created by Administrator on 2015/11/9. */ public class AutoHomeListView extends ListView implements AbsListView.OnScrollListener { private static final int DONE = 0; private static final int PULL_TO_REFRESH = 1; private static final int RELEASE_TO_REFRESH = 2; private static final int REFRESHING = 3; private static final int RATIO = 3; private LinearLayout mHeaderView; private AutoHome mAutoHome; private TextView mPullToRefreshTV; private FrameLayout mAnimContainer; private PointerView mAutoHomeAnim; private Animation mAnimation; private OnAutoHomeRefreshListener mOnAutoHomeRefreshListener; private int mHeaderViewHeight; private float mStartY; private float mOffsetY; private int mState; private int mFirstVisibleItem; private boolean mIsRecord; private boolean mIsEnd; private boolean mIsRefreable; public interface OnAutoHomeRefreshListener{ void onRefresh(); } public AutoHomeListView(Context context) { super(context); init(context); } public AutoHomeListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public AutoHomeListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { setOverScrollMode(View.OVER_SCROLL_NEVER); setOnScrollListener(this); this.mHeaderView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.imitateautohome_header, null, false); this.mAutoHome = ViewFinder.findViewById(mHeaderView, R.id.sdi_autohome); this.mPullToRefreshTV = ViewFinder.findViewById(mHeaderView, R.id.sdi_pulltorefresh_tv); mAnimContainer = ViewFinder.findViewById(mHeaderView, R.id.sdi_animcontainer_fl); mAutoHomeAnim = ViewFinder.findViewById(mHeaderView, R.id.sdi_animpointer_iv); mAnimation = AnimationUtils.loadAnimation(context, R.anim.sda_autohome_pointer_rotate); measureView(mHeaderView); addHeaderView(mHeaderView); mHeaderViewHeight = mHeaderView.getMeasuredHeight(); mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0); mState = DONE; mIsEnd = true; mIsRefreable = false; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.mFirstVisibleItem = firstVisibleItem; } public void setOnAutoHomeRefreshListener(OnAutoHomeRefreshListener onRefreshListener){ mOnAutoHomeRefreshListener = onRefreshListener; mIsRefreable = true; } public void setOnRefreshComplete(){ mIsEnd = true; mState = DONE; changeHeaderByState(mState); } @Override public boolean onTouchEvent(MotionEvent ev) { if (!mIsEnd) return super.onTouchEvent(ev); if (!mIsRefreable) return super.onTouchEvent(ev); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: if (mFirstVisibleItem == 0 && !mIsRecord) { mIsRecord = true; mStartY = ev.getY(); } break; case MotionEvent.ACTION_MOVE: float tempY = ev.getY(); if (mFirstVisibleItem == 0 && !mIsRecord) { mIsRecord = true; mStartY = tempY; } if (mState!=REFRESHING && mIsRecord ) { mOffsetY = tempY - mStartY; float currentHeight = (-mHeaderViewHeight+mOffsetY/RATIO); float currentProgress = 1+currentHeight/mHeaderViewHeight; if (currentProgress >= 1) { currentProgress = 1; } if (mState == RELEASE_TO_REFRESH && mIsRecord) { setSelection(0); if (-mHeaderViewHeight+mOffsetY/RATIO < 0) { mState = PULL_TO_REFRESH; changeHeaderByState(mState); }else if (mOffsetY <= 0) { mState = DONE; changeHeaderByState(mState); } } if (mState == PULL_TO_REFRESH && mIsRecord) { setSelection(0); if (-mHeaderViewHeight+mOffsetY/RATIO >= 0) { mState = RELEASE_TO_REFRESH; changeHeaderByState(mState); }else if (mOffsetY <= 0) { mState = DONE; changeHeaderByState(mState); } } if (mState == DONE && mIsRecord) { if (mOffsetY>=0) { mState = PULL_TO_REFRESH; } } if (mState == PULL_TO_REFRESH) { mHeaderView.setPadding(0,(int)(-mHeaderViewHeight+mOffsetY/RATIO), 0, 0); mAutoHome.setCurrentProgress(currentProgress); mAutoHome.postInvalidate(); } if (mState == RELEASE_TO_REFRESH) { mHeaderView.setPadding(0,(int)(-mHeaderViewHeight+mOffsetY/RATIO), 0, 0); mAutoHome.setCurrentProgress(currentProgress); mAutoHome.postInvalidate(); } } break; case MotionEvent.ACTION_UP: if (mState == PULL_TO_REFRESH) { this.smoothScrollBy((int)(-mHeaderViewHeight+mOffsetY/RATIO)+mHeaderViewHeight, 500); changeHeaderByState(mState); } if (mState == RELEASE_TO_REFRESH) { this.smoothScrollBy((int)(-mHeaderViewHeight+mOffsetY/RATIO), 500); mState = REFRESHING; mOnAutoHomeRefreshListener.onRefresh(); changeHeaderByState(mState); } mIsRecord = false; break; } return super.onTouchEvent(ev); } private void changeHeaderByState(int state){ switch (state) { case DONE: mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0); //第一状态的view显示出来 mAutoHome.setVisibility(View.VISIBLE); //先停止一下第二阶段view的动画 mAutoHomeAnim.clearAnimation(); //将第二阶段view隐藏起来 mAnimContainer.setVisibility(View.GONE); break; case RELEASE_TO_REFRESH: mPullToRefreshTV.setText("放开刷新"); break; case PULL_TO_REFRESH: mPullToRefreshTV.setText("下拉刷新"); //第一状态view显示出来 mAutoHome.setVisibility(View.VISIBLE); //停止第二阶段动画 mAutoHomeAnim.clearAnimation(); //将第二阶段view隐藏 mAnimContainer.setVisibility(View.GONE); break; case REFRESHING: mPullToRefreshTV.setText("正在刷新"); //将第一阶段view隐藏 mAutoHome.setVisibility(View.GONE); //将第二阶段view显示出来 mAnimContainer.setVisibility(View.VISIBLE); //先停止第二阶段动画 mAutoHomeAnim.clearAnimation(); //启动第二阶段动画 mAutoHomeAnim.startAnimation(mAnimation); break; default: break; } } private void measureView(View child) { ViewGroup.LayoutParams lp = child.getLayoutParams(); if (lp == null) { lp = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, lp.width); int lpHeight = lp.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); } }