Android自定义弹性滑动View

1.记录一下自己自定义View

2.直接子View只能是一个

public class SlideView extends ViewGroup {
    private static final String TAG = "ScrollLinearLayout";
    private int lastY;//记录上一个位置
    private Scroller mScroller;//回弹的动画效果
    private View mChildView;

    public SlideView(Context context) {
        this(context, null);
    }

    public SlideView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public SlideView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private void initView(Context context) {
        mScroller = new Scroller(context);
        setClickable(true);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        int childCount = getChildCount();
        if (childCount > 1) {
            throw new RuntimeException("只能有一个子View");
        }
        mChildView = getChildAt(0);
        if (mChildView == null) {
            throw new RuntimeException("没有子View");
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        Log.e(TAG, "onTouchEvent: y==" + y);
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:

                int mScrollY = lastY - y;//手指滑动的距离
                Log.e(TAG, "dispatchTouchEvent: mScrollY==" + mScrollY + " getScrollY()==" + getScrollY());

                /**
                 * 子View在中间,触摸事件交给子View
                 */
                if (!canPullDown() && !canPullUp()) {
                    lastY = y;
                    if (getScrollY() != 0) {//子View到了中间位置,父View还有移动的距离,父View恢复原位
                        int scrollY = getScrollY();
                        mScroller.startScroll(0, scrollY, 0, -scrollY, 0);
                        invalidate();
                    }
                    break;
                }

                if (canPullDown() && mScrollY < 0) {//顶部往下拉
                    mScrollY = (int) (mScrollY * scan());
                } else if (canPullUp() && mScrollY > 0) {//底部往上拉
                    mScrollY = (int) (mScrollY * scan());
                } else {
                    if (Math.abs(mScrollY) > Math.abs(getScrollY())) {//边界问题,移动的距离大于当前的滑动的距离
                        mScrollY = -getScrollY();
                    }
                }
                scrollBy(0, mScrollY);//滑动
                if (getScrollY() == 0) {
                    break;
                }

                lastY = y;
                return true;//事件自己消费
            case MotionEvent.ACTION_UP:
                int scrollY = getScrollY();
                mScroller.startScroll(0, scrollY, 0, -scrollY);
                invalidate();
                break;
        }
        lastY = y;
        return super.dispatchTouchEvent(event);
    }

    /**
     * 滑动的速度
     *
     * @return
     */
    private float scan() {
        return 0.5f;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //不能用这个来测量子View的大小,不准确
//        measureChildren(widthMeasureSpec, heightMeasureSpec);

        measureChildWithMargins(getChildAt(0), widthMeasureSpec, 0, heightMeasureSpec, 0);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getChildTotalWidth(), getChildTotalHeight());
        } else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getChildTotalWidth(), heightSize);
        } else if (heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSize, getChildTotalHeight());
        } else {
            setMeasuredDimension(widthSize, heightSize);
        }
    }

    /**
     * 得到子View的宽度
     *
     * @return
     */
    private int getChildTotalWidth() {
        int childCount = getChildCount();
        int width = 0;
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);
            MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();
            width += childAt.getMeasuredWidth() + layoutParams.leftMargin;
        }
        return width;
    }

    /**
     * 得到子View的高度
     *
     * @return
     */
    private int getChildTotalHeight() {
        int childCount = getChildCount();
        int height = 0;
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);
            MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();
            height += childAt.getMeasuredHeight() + layoutParams.topMargin;
        }
        return height;
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        Log.e(TAG, "onLayout: r==" + r + " b==" + b + " l==" + l + " t==" + t);
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);
            MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams();

            int left = layoutParams.leftMargin + getPaddingLeft();
            int top = layoutParams.topMargin + getPaddingTop();
            int right = left + childAt.getMeasuredWidth();
            int bottom = top + childAt.getMeasuredHeight();

            childAt.layout(left, top, right, bottom);
        }
    }

    //到底顶部,可以下拉
    private boolean canPullDown() {
        if (mChildView instanceof ScrollView) {
            ScrollView scrollView = (ScrollView) mChildView;
            if (scrollView.getScrollY() == 0) {
                return true;
            }
        } else if (mChildView instanceof RecyclerView) {
            RecyclerView recyclerView = (RecyclerView) mChildView;
            if (!recyclerView.canScrollVertically(-1)) {
                return true;
            }
        } else if (mChildView instanceof ListView) {
            ListView listView = (ListView) mChildView;
            if (!listView.canScrollVertically(-1)) {
                return true;
            }
        } else {
            return true;
        }
        return false;
    }

    //到达底部,可以上拉
    private boolean canPullUp() {
        if (mChildView instanceof ScrollView) {
            ScrollView scrollView = (ScrollView) mChildView;
            boolean b = scrollView.canScrollVertically(1);
            if (!b) {
                return true;
            }
        } else if (mChildView instanceof RecyclerView) {
            RecyclerView recyclerView = (RecyclerView) mChildView;
            boolean b = recyclerView.canScrollVertically(1);
            if (!b) {
                return true;
            }
        } else if (mChildView instanceof ListView) {
            ListView listView = (ListView) mChildView;
            boolean b = listView.canScrollVertically(1);
            if (!b) {
                return true;
            }
        } else {
            return true;
        }
        return false;
    }

    @Override
    public void computeScroll() {
        // 重写computeScroll()方法,完成回弹
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }
}

3.使用

    

        
    


你可能感兴趣的:(android,View)