package com.com.mr_wrong.CustomView; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ScrollView; import com.example.mr_wrong.androidstudioproject.R; /** * Created by Mr_Wrong on 15/6/16. */ public class MyPullScrollView extends ScrollView { private static final float SCROLL_RATIO = 0.5F; private View mHeaderView; private int mHeaderHeight; private View mContent; private Rect mContentRect = new Rect(); private int mHeaderVisibleHeight; private boolean isMoving; private int mInitTop, mInitBottom; private int mCurrentTop, mCurrentBottom; private float mTouchDownY; private boolean istop; private enum State { UP, DOWN, NORMAL } private State mState = State.NORMAL; public MyPullScrollView(Context context) { this(context, null); } public MyPullScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyPullScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOverScrollMode(OVER_SCROLL_NEVER); if (null != attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PullScrollView); if (ta != null) { mHeaderHeight = (int) ta.getDimension(R.styleable.PullScrollView_headerHeight, -1); mHeaderVisibleHeight = (int) ta.getDimension(R.styleable .PullScrollView_headerVisibleHeight, -1); ta.recycle(); } } } @Override protected void onFinishInflate() { mContent = getChildAt(0); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (getScrollY() == 0) { istop = true; } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mTouchDownY = ev.getY(); mCurrentTop = mInitTop = mHeaderView.getTop(); mCurrentBottom = mInitBottom = mHeaderView.getBottom(); } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { if (mContent != null) { dotouchEvent(ev); } return super.onTouchEvent(ev); } private void dotouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_MOVE) { doActionMove(ev); } else if (ev.getAction() == MotionEvent.ACTION_UP) { //回滚动画 mHeaderView.layout(mHeaderView.getLeft(), mInitTop, mHeaderView.getRight(), mInitBottom); mContent.layout(mContentRect.left, mContentRect.top, mContentRect.right, mContentRect.bottom); } } private void doActionMove(MotionEvent ev) { if (getScrollY() == 0) { mState = State.NORMAL; if (istop) { istop = false; mTouchDownY = ev.getY(); } } float deltaY = ev.getY() - mTouchDownY; //判断滑动方向 if (deltaY < 0 && mState == State.NORMAL) { mState = State.UP; } else if (deltaY > 0 && mState == State.NORMAL) { mState = State.DOWN; } if (mState == State.UP) { isMoving = false; deltaY = deltaY < 0 ? deltaY : 0; } else if (mState == State.DOWN) { if (getScrollY() <= deltaY) { isMoving = true; } deltaY = deltaY > 0 ? deltaY : 0; } if (isMoving) {//向下拖拽 if (mContentRect.isEmpty()) { mContentRect.set(mContent.getLeft(), mContent.getTop(), mContent.getRight(), mContent.getBottom()); } //计算header移动的距离 float headerMoveHeight = deltaY * SCROLL_RATIO * 0.5f; mCurrentBottom = (int) (mInitBottom + headerMoveHeight); mCurrentTop = (int) (mInitTop + headerMoveHeight); //计算content的移动距离 float contentMoveHeight = deltaY * SCROLL_RATIO; int top = (int) (mContentRect.top + contentMoveHeight); int bottom = (int) (mContentRect.bottom + contentMoveHeight); if (mCurrentBottom >= top) { mHeaderView.layout(mHeaderView.getLeft(), mCurrentTop, mHeaderView.getRight(), mCurrentBottom); mContent.layout(mContentRect.left, top, mContentRect.right, bottom); } } } public void setHeader(View headview) { this.mHeaderView = headview; } }