Android 可拖拽的view,带吸边效果,不影响下层点击,不影响子view点击

转载请注明原创出处,谢谢!
public class DragStickLinearLayout extends LinearLayout {

    // 是否吸边
    private boolean mIsStick = true;
    private float v = 1.f; // 宽比例(适配横竖屏)(保证取值在0-1)
    private float h = 0.8f; // 高比例(适配横竖屏)(保证取值在0-1)
    private int mTop = 0;
    private int mLeft = 0;
    private ViewDragHelper mViewDragHelper;

    public DragStickLinearLayout(@NonNull Context context) {
        super(context);
        init();
    }

    public DragStickLinearLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragStickLinearLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        v = SpUtils.getFloat("v", v);
        h = SpUtils.getFloat("h", h);
        mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(@NonNull View child, int pointerId) {
                return true;
            }

            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                if (top <= 0) {
                    mTop = 0;
                } else {
                    mTop = Math.min(top, getMeasuredHeight() - child.getMeasuredHeight());
                }
                return mTop;
            }

            @Override
            public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
                if (left <= 0) {
                    mLeft = 0;
                } else {
                    mLeft = Math.min(left, getMeasuredWidth() - child.getMeasuredWidth());
                }
                return mLeft;
            }

            @Override
            public int getViewHorizontalDragRange(@NonNull View child) {
                return 1; // 返回1不影响子view的点击事件
            }

            @Override
            public int getViewVerticalDragRange(@NonNull View child) {
                return 1; // 返回1不影响子view的点击事件
            }

//            @Override
//            public void onViewDragStateChanged(int state) {
//                super.onViewDragStateChanged(state);
//                if (state == ViewDragHelper.STATE_IDLE) {
//                    Log.i("TAGaaaaaaaaaaaa", "onViewDragStateChangedtop: " + getChildAt(0).getTop());
//                    Log.i("TAGaaaaaaaaaaaa", "onViewDragStateChangedleft: " + getChildAt(0).getLeft());
//                }
//            }

//            @Override
//            public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
//                super.onViewPositionChanged(changedView, left, top, dx, dy);
//                Log.i("TAGaaaaaaaaaaaa", "onViewPositionChanged: l:" + left + " t:" + top + " " + changedView);
//            }

            @Override
            public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                if (mIsStick) {
                    if (mLeft < (getMeasuredWidth() - getChildAt(0).getMeasuredWidth()) / 2) { // 贴左边
                        mLeft = 0;
                        ((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_start);
                    } else { // 贴右边
                        mLeft = getMeasuredWidth() - releasedChild.getMeasuredWidth();
                        ((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_end);
                    }
                    mViewDragHelper.smoothSlideViewTo(getChildAt(0), mLeft, mTop);
                    ViewCompat.postInvalidateOnAnimation(DragStickLinearLayout.this);
                }
            }
        });
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        // 处理贴边
        if (mViewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            // 保存top和left的比例
            int width = getMeasuredWidth() - getChildAt(0).getMeasuredWidth();
            int height = getMeasuredHeight() - getChildAt(0).getMeasuredHeight();
            h = 1.f * mTop / height;
            if (mIsStick) {
                // 切边
                if (mLeft < width / 2) {
                    v = 0.f;
                } else {
                    v = 1.f;
                }
            } else {
                v = 1.f * mLeft / width;
            }
            // 保存v和h(保证取值在0-1)
            SpUtils.putFloat("v", Math.min(1, Math.max(0, v)));
            SpUtils.putFloat("h", Math.min(1, Math.max(0, h)));
        } else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            ((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_move);
        }
        mViewDragHelper.processTouchEvent(ev);
        // 判断触摸是否在子View的范围内,不影响底部view的时间
        return mViewDragHelper.isViewUnder(getChildAt(0), (int) ev.getX(), (int) ev.getY());
    }

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        int width = getMeasuredWidth() - getChildAt(0).getMeasuredWidth();
        int height = getMeasuredHeight() - getChildAt(0).getMeasuredHeight();
        mTop = (int) (height * h);
        mLeft = (int) (width * v);
        getChildAt(0).layout(mLeft, mTop, mLeft + getChildAt(0).getMeasuredWidth(), mTop + getChildAt(0).getMeasuredHeight());
        if (isFirst) {
            isFirst = false;
            if (mLeft <= 0) {
                ((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_start);
            } else {
                ((ImageView) getChildAt(0)).setImageResource(R.drawable.iv_ai_end);
            }
        }
    }

    private boolean isFirst = true;

    public void initVH(float v, float h) {
        this.v = v;
        this.h = h;
        invalidate();
    }
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容