StretchContainer.class
package com.lucas.yanfriends.myview.smoothscroll;import android.content.Context;import android.content.res.TypedArray;import android.support.annotation.AttrRes;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.ViewConfiguration;import android.view.animation.DecelerateInterpolator;import android.widget.FrameLayout;import android.widget.Scroller;import com.lucas.yanfriends.R;/** * @author Gimpo create on 2017/9/1 10:54 * @email : jimbo922@163.com */public class StretchContainer extends FrameLayout {    /**     * 弹性系数  越小说明这个view越难被拉动     */    private float ratio;    /**     * view作出反应最小滑动距离     */    private int mTouchSlop;    /**     * 这个scroller可以让滑动更加的顺滑 不是很突兀的那种  写法固定     */    private Scroller mScroller;    /**     * 允许最大的下拉距离     */    private float maxY = 600;    /**     * 包裹的滚动view 可以是所有的view 这个view最好能滚动     */    private StretchScrollView mScrollView;    /**     * 最大滑动距离     */    private float mLastY;    /**     * 当前view被拖拽     */    private boolean mIsDraging;    /**     * 回弹时间     */    private int duration = 500;    public StretchContainer(@NonNull Context context) {        super(context);        initView(context, null);    }    public StretchContainer(@NonNull Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initView(context, attrs);    }    public StretchContainer(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView(context, attrs);    }    public void initView(Context context, AttributeSet attrs) {        if (attrs != null) {            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StretchContainer);            ratio = a.getFloat(R.styleable.StretchContainer_ratio, 1.0f);        }        ViewConfiguration config = ViewConfiguration.get(context);        mTouchSlop = config.getScaledTouchSlop();        DecelerateInterpolator interpolator = new DecelerateInterpolator();        mScroller = new Scroller(context, interpolator);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mScrollView = (StretchScrollView) getChildAt(0);    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        float currentY = ev.getY();        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                mLastY = currentY;                break;            case MotionEvent.ACTION_MOVE:                float distanceY = currentY - mLastY;                if (mIsDraging) {                    if (distanceY <= 0) {                        if(mScrollView.isScrolledToTop()) {                            scrollTo(0, 0);                            mIsDraging = false;                            return super.dispatchTouchEvent(ev);                        }                    }else{                        if(mScrollView.isScrolledToBottom()){                            scrollTo(0, 0);                            mIsDraging = false;                            return super.dispatchTouchEvent(ev);                        }                    }                    scrollTo(0, (int) (-distanceY * ratio));                    return true;                } else {                    if (Math.abs(distanceY) > mTouchSlop) {                        if (distanceY > 0) {  // 向下                            if (mScrollView.isScrolledToTop()) {                                mLastY = currentY;                                mIsDraging = true;                            }                        }else{                            if(mScrollView.isScrolledToBottom()){                                mLastY = currentY;                                mIsDraging = true;                            }                        }                    }                }                break;            case MotionEvent.ACTION_UP:                if (mIsDraging) {                    int scrollY = getScrollY();                    mScroller.startScroll(0, scrollY, 0, -scrollY, duration);                    mIsDraging = false;                    invalidate();                    return true;                }                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    public void computeScroll() {        //判断是否还在滚动,还在滚动为true        if (mScroller.computeScrollOffset()) {            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            //更新界面            postInvalidate();        }        super.computeScroll();    }}

 

StretchScrollView.class
package com.lucas.yanfriends.myview.smoothscroll;import android.content.Context;import android.util.AttributeSet;import android.widget.ScrollView;/** * @author Gimpo create on 2017/9/1 12:06 * @email : jimbo922@163.com */public class StretchScrollView extends ScrollView {    private boolean isScrolledToTop = true;    private boolean isScrolledToBottom;    public StretchScrollView(Context context) {        super(context);    }    public StretchScrollView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public StretchScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        if (getScrollY() == 0) {    // 小心踩坑1: 这里不能是getScrollY() <= 0            setScrolledToTop(true);            setScrolledToBottom(false);        } else if (getScrollY() + getHeight() - getPaddingTop()-getPaddingBottom() == getChildAt(0).getHeight()) {            // 小心踩坑2: 这里不能是 >=            // 小心踩坑3(可能忽视的细节2):这里最容易忽视的就是ScrollView上下的padding             setScrolledToTop(false);            setScrolledToBottom(true);        } else {            setScrolledToTop(false);            setScrolledToBottom(false);        }    }    public boolean isScrolledToTop() {        return isScrolledToTop;    }    public void setScrolledToTop(boolean scrolledToTop) {        isScrolledToTop = scrolledToTop;    }    public boolean isScrolledToBottom() {        return isScrolledToBottom;    }    public void setScrolledToBottom(boolean scrolledToBottom) {        isScrolledToBottom = scrolledToBottom;    }}

 

更多相关文章

  1. Android 读写文件的N种写法
  2. Android 虚拟摇杆,多种模式回调,返回距离级别,方向,角度。
  3. android中Selector中的相关属性及配置写法
  4. android 底部菜单写法之FragmentTabHost
  5. Android获取RecyclerView滑动距离
  6. android中求区域内两个坐标之间的距离的实现
  7. Android点击事件的四种写法
  8. 通话距离感应实现源码
  9. android图形叠加背景的写法

随机推荐

  1. Android activity启动模式理解
  2. Android使用Thread+Handler实现非UI线程
  3. Android(安卓)创建自定Dialog
  4. SSDP协议的Android实现以及使用
  5. 用Eneter实现Android与.NET间通讯
  6. 活动与任务
  7. 打造android ORM框架opendroid(四)——优
  8. PHP android ios相互兼容的AES加密算法
  9. Android界面加载完成后自动弹出软键盘的
  10. 快速体验Android(安卓)2.3