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中实现一个DrawerLayout滑动菜单
  2. android手势识别总结
  3. Android(安卓)中文 API (100) —— ScrollView
  4. android 让TextView自带滚动条
  5. Android滑动卡片效果:Swipecards
  6. android Scroller
  7. Android(安卓)Material Design : CollapsingToolbarLayout使用简
  8. Android(安卓)ListView强制停止滚动
  9. Android省市区三级联动滚轮选择(真实项目中提取出来的组件)

随机推荐

  1. SQL SERVER数据操作类代码
  2. 用SQL统计SQLServe表存储空间大小的代码
  3. 浅谈SQL Server中统计对于查询的影响分析
  4. INSERT INTO SELECT语句与SELECT INTO FR
  5. SQL Server中的执行引擎入门 图解
  6. 分析SQL语句性能3种方法分享
  7. sqlserver中重复数据值只取一条的sql语句
  8. SQL 特殊语句(学习笔记)
  9. sqlserver通用的删除服务器上的所有相同
  10. SQL Server修改标识列方法 如自增列的批