原理:

addHeaderView里做的事:

1.测量出header的宽高,调用了measureView方法
2.设置LayoutParams,宽:MATCH_PARENT,高:10
3.设置topMargin的值为负的header的高度,即将header隐藏在屏幕最上方


onInterceptTouchEvent:

如果滑动距离为零,让onInterceptTouchEvent处理。屏幕没有滑动效果。

onTouchEvent:
如果滑动距离大于零,让onTouchEvent处理。在滑动过程中不断的计算header的topMargin,让屏幕有滑动效果。


代码:

/**  * android回弹效果 by haidaye  */ public class HaidayeView extends LinearLayout {    private int mLastMotionY;    /**  * 头部view  */  private View mHeaderView;    private LayoutInflater mInflater;    private ScrollView mScrollView;    /**  * 头部view的高  */  private int mHeaderViewHeight;    public HaidayeView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public HaidayeView(Context context) {        super(context);        init();    }    private void init() {        // Load all of the animations we need in code rather than through XML        mInflater = LayoutInflater.from(getContext());        // header view 在此添加,保证是第一个添加到linearlayout的最上端        addHeaderView();    }    private void addHeaderView() {        // header view        mHeaderView = mInflater.inflate(R.layout.header, this, false);        measureView(mHeaderView);        mHeaderViewHeight = mHeaderView.getMeasuredHeight();        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,                mHeaderViewHeight);        // 设置topMargin的值为负的header View高度,即将其隐藏在最上方        params.topMargin = -(mHeaderViewHeight);        addView(mHeaderView, params);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        initContentAdapterView();    }    private void initContentAdapterView() {        mScrollView = (ScrollView) getChildAt(1);    }    private void measureView(View child) {        ViewGroup.LayoutParams p = child.getLayoutParams();        if (p == null) {            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,                    ViewGroup.LayoutParams.WRAP_CONTENT);        }        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);        int lpHeight = p.height;        int childHeightSpec;        if (lpHeight > 0) {            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,                    MeasureSpec.EXACTLY);        } else {            childHeightSpec = MeasureSpec.makeMeasureSpec(0,                    MeasureSpec.UNSPECIFIED);        }        child.measure(childWidthSpec, childHeightSpec);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent e) {        int y = (int) e.getRawY();        switch (e.getAction()) {            case MotionEvent.ACTION_DOWN:                // 首先拦截down事件,记录y坐标                mLastMotionY = y;                break;            case MotionEvent.ACTION_MOVE:                // deltaY > 0 是向下运动,< 0是向上运动                int deltaY = y - mLastMotionY;                if (isRefreshViewScroll(deltaY)) {                    return true;                }                mLastMotionY = y;                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                break;        }        return false;    }    /*     * 如果在onInterceptTouchEvent()方法中没有拦截(onInterceptTouchEvent()方法中 return     * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由HaidayeView自己来处理)     */    @Override    public boolean onTouchEvent(MotionEvent event) {        int y = (int) event.getRawY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                // onInterceptTouchEvent已经记录                // mLastMotionY = y;                break;            case MotionEvent.ACTION_MOVE:                int deltaY = y - mLastMotionY;                headerPrepareToRefresh(deltaY);                mLastMotionY = y;                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                int topMargin = getHeaderTopMargin();                setHeaderTopMargin(-mHeaderViewHeight);                break;            case MotionEvent.ACTION_POINTER_DOWN://设置多点触控                this.mLastMotionY = y;                break;        }        return super.onTouchEvent(event);    }    /**  * 是否应该到了父View,PullToRefreshView滑动  *  * @param deltaY , deltaY > 0 是向下运动,< 0是向上运动  * @return  */  private boolean isRefreshViewScroll(int deltaY) {        // 对于ScrollView        if (mScrollView != null) {            // scroll view滑动到最顶端            View child = mScrollView.getChildAt(0);            if (deltaY > 0 && mScrollView.getScrollY() == 0) {                return true;            } else if (deltaY < 0                    && child.getMeasuredHeight() <= getHeight()                    + mScrollView.getScrollY()) {                return true;            }        }        return false;    }    /**  * header 准备刷新,手指移动过程,还没有释放  *  * @param deltaY ,手指滑动的距离  */  private void headerPrepareToRefresh(int deltaY) {        int newTopMargin = changingHeaderViewTopMargin(deltaY);    }    private int changingHeaderViewTopMargin(int deltaY) {        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();        float newTopMargin = params.topMargin + deltaY * 0.3f;        params.topMargin = (int) newTopMargin;        mHeaderView.setLayoutParams(params);        invalidate();        return params.topMargin;    }    /**  * 设置header view topMargin的值  */  private void setHeaderTopMargin(int topMargin) {        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();        params.topMargin = topMargin;        mHeaderView.setLayoutParams(params);        invalidate();    }    private int getHeaderTopMargin() {        LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();        return params.topMargin;    }}

致敬海大爷



更多相关文章

  1. Android(安卓)studio设置背景图片
  2. Android(安卓)ImageView设置图片原理
  3. Android学习笔记(20):时钟(AnalogClock和TextClock)和计时器(Chr
  4. Android(安卓)Design新控件之TextInputLayout 文本输入布局与自
  5. 状态栏提示Notification
  6. Android(安卓)沉浸式状态栏归纳
  7. Android(安卓)自定义控件
  8. Android学习笔记7&s3c2440学习系列8
  9. Android(安卓)7.0 Audio :通话中的音频调用接口

随机推荐

  1. Kotlin编程之Glide v4 Generated API(Unr
  2. Android图片加载框架Picasso最全使用教程
  3. android 成长 UI 学习之 Activity 透明,半
  4. XML属性
  5. ANR Bug分析
  6. android--使用Struts2服务端与android交
  7. 关于Android界面编程与视图(View)组件
  8. 【转】Android-Action Bar使用方法
  9. Android GDI之SurfaceFlinger
  10. Android merge抽象布局介绍