使用ViewDragHelper 实现吸边效果

来源:互联网 发布:凡科建站域名绑定 编辑:程序博客网 时间:2024/04/27 20:38

由于项目需求需要按钮吸边,就自己动手写了下。对于通过手势拖拽我立马就想到了ViewDragHelper这个系统工具类。有了这个类的存在 我们只需要处理松开手指的逻辑处理和边界控制就行了。
下面是实现代码

public class SuctionSideView extends RelativeLayout {    private final String TAG = "SuctionSideView";    private ViewDragHelper mDragHelper; // 拖拽控制    private View mSuctionView; // 要吸边的view    private Point mAutoBackOriginPos = new Point(); // 记录子view现在的位置    private boolean isInit = false;    /**     * 1 | 2     * -----     * 3 | 4     */    private int centerX;// 屏幕中心的x值    private int centerY;// 屏幕中心的y值 根据这两个属性建立直角坐标系    public SuctionSideView(@NonNull Context context) {        super(context,null);    }    public SuctionSideView(@NonNull Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        init();        addListener();    }    /**     * 初始化布局     * @throws Exception     */    private void init() {    }    /**     * 监听事件注册     */    private void addListener() {        mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {            @Override            public boolean tryCaptureView(View child, int pointerId) {                return child == mSuctionView;            }            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                final int leftBound = getPaddingLeft() + UIUtil.dp2px(10);                final int rightBound = getWidth() - child.getWidth() - leftBound  - UIUtil.dp2px(10);                final int newLeft = Math.min(Math.max(left, leftBound), rightBound);                return newLeft;            }            @Override            public int getViewHorizontalDragRange(View child) {                return getMeasuredWidth() - child.getMeasuredWidth();            }            @Override            public int clampViewPositionVertical(View child, int top, int dy) {                final int topBound = getPaddingTop()  + UIUtil.dp2px(10);                final int bottomBound = getHeight() - child.getHeight() - getPaddingBottom() - UIUtil.dp2px(10);                final int newTop = Math.min(Math.max(top,topBound),bottomBound);                return newTop;            }            @Override            public int getViewVerticalDragRange(View child) {                return getMeasuredHeight() - child.getMeasuredHeight();            }            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                if (releasedChild == mSuctionView) {                    if (releasedChild.getLeft() < centerX) { // 往左移动                        moveTo(UIUtil.dp2px(10) + getPaddingLeft(), releasedChild.getTop());                    } else { // 往右                        moveTo(getWidth() - UIUtil.dp2px(59) - getPaddingRight(), releasedChild.getTop());                    }//                    if (releasedChild.getLeft() < centerX && releasedChild.getTop() < centerY) { // 1象限//                        if (releasedChild.getLeft() < releasedChild.getTop()) { // 往左//                            moveTo(0, releasedChild.getTop());//                        } else { // 网上//                            moveTo(releasedChild.getLeft(), 0);//                        }//                    } else if (releasedChild.getLeft() > centerX && releasedChild.getTop() < centerY) { // 2象限//                        if (getWidth() - releasedChild.getLeft() - getWidth() < getTop() - releasedChild.getHeight()) { // 往右//                            moveTo(getWidth() - releasedChild.getWidth() - getPaddingRight(), releasedChild.getTop());//                        } else { // 往上//                            moveTo(releasedChild.getLeft(), 0);//                        }//                    } else if (releasedChild.getLeft() < centerX && releasedChild.getTop() > centerY) { // 3 象限//                        if (releasedChild.getLeft() < getHeight() - releasedChild.getTop() - releasedChild.getHeight()) { // 往左//                            moveTo(0, releasedChild.getTop());//                        } else { // 往下//                            moveTo(releasedChild.getLeft(), getHeight() - releasedChild.getHeight() - getPaddingBottom());//                        }//                    } else if (releasedChild.getLeft() > centerX && releasedChild.getTop() > centerY) { // 4象限//                        if (getWidth() - releasedChild.getLeft() - releasedChild.getWidth() < getHeight() - releasedChild.getTop() - releasedChild.getHeight()) { // 向右//                            moveTo(getWidth() - releasedChild.getWidth() - getPaddingRight(), releasedChild.getTop());//                        } else { // 往下//                            moveTo(releasedChild.getLeft(), getHeight() - releasedChild.getHeight() - getPaddingBottom());//                        }////                    }                    ViewCompat.postInvalidateOnAnimation(SuctionSideView.this);                }            }        });    }    private void moveTo(int xvel, int yvel) {        mAutoBackOriginPos.x = xvel;        mAutoBackOriginPos.y = yvel;        mDragHelper.smoothSlideViewTo(mSuctionView,xvel,yvel);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mSuctionView = getChildAt(0);        LogUtil.i(TAG,"onFinishInflate");    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        centerX = getWidth() / 2;        centerY = getHeight() / 2;        if (!isInit) {            mAutoBackOriginPos.x = getWidth() - UIUtil.dp2px(59);            mAutoBackOriginPos.y = getHeight() - UIUtil.dp2px(75);            isInit = true;            mSuctionView.layout(mAutoBackOriginPos.x,mAutoBackOriginPos.y,mAutoBackOriginPos.x + UIUtil.dp2px(49),mAutoBackOriginPos.y + UIUtil.dp2px(65));            LogUtil.i(TAG,"mAutoBackOriginPos.x:" + mAutoBackOriginPos.x + "mAutoBackOriginPos.y" + mAutoBackOriginPos.y);        }    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return mDragHelper.shouldInterceptTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        mDragHelper.processTouchEvent(event);        return false;    }    @Override    public void computeScroll() {        if (mDragHelper.continueSettling(true)) {            invalidate();        }    }}

这里面记录下吸边控件的初始位置。

clampViewPositionHorizontal与clampViewPositionVertical这是控制吸边控件的上下左右能够活动位置

由于我的项目中值需要左右吸边所以我在

onViewReleased 里只需要判断当前控件的left超过中心线了没

其中涉及到的数字为吸边控件距左距右和控件本身的尺寸,整个代码差不多100行是不是很简单吧。
使用也非常简单 用自定义好的控件包裹住需要被吸边的控件

<cn.missfresh.home.widget.SuctionSideView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_below="@+id/title_bar">        <ImageView            android:id="@+id/view"            android:layout_width="49dp"            android:layout_height="65dp"            android:layout_gravity="right|bottom"            android:layout_marginBottom="10dp"            android:layout_marginRight="10dp"            android:scaleType="fitXY"            android:visibility="gone" />    </cn.missfresh.home.widget.SuctionSideView>
0 0
原创粉丝点击