美文网首页
拖动悬浮按钮-继承自FloatingActionButton

拖动悬浮按钮-继承自FloatingActionButton

作者: 旅行者归来 | 来源:发表于2019-11-30 11:41 被阅读0次

    其他控件悬浮拖动的原理类似

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.ViewGroup;
    import android.view.animation.BounceInterpolator;
    
    public class DragFloatBtnT extends FloatingActionButton {
    
        //移动后的xy坐标
        private float mLastRawx;
        private float mLastRawy;
        private boolean isDrug = false;
        private int mRootMeasuredWidth;
        private int padding;
    
        public DragFloatBtnT(Context context) {
            super(context);
            init();
        }
    
        public DragFloatBtnT(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public DragFloatBtnT(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            padding = DensityUtils.dp2px(getContext(), 15);
        }
    
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            //当前手指的坐标
            float mRawx = ev.getRawX();
            float mRawy = ev.getRawY();
            ViewGroup mViewGroup = (ViewGroup) getParent();
    
            switch (ev.getAction()) {
                //手指按下
                case MotionEvent.ACTION_DOWN:
                    setPressed(true);
                    isDrug = false;
                    //记录按下的位置
                    mLastRawx = mRawx;
                    mLastRawy = mRawy;
                    if (mViewGroup != null) {
                        int[] location = new int[2];
                        mViewGroup.getLocationInWindow(location);
                        //获取父布局的宽度
                        mRootMeasuredWidth = mViewGroup.getMeasuredWidth();
                    }
                    break;
                //手指滑动
                case MotionEvent.ACTION_MOVE:
                    if (mViewGroup != null) {
                        int[] location = new int[2];
                        mViewGroup.getLocationInWindow(location);
                        //获取父布局的高度
                        int mRootMeasuredHeight = mViewGroup.getMeasuredHeight();
                        mRootMeasuredWidth = mViewGroup.getMeasuredWidth();
                        //获取父布局顶点的坐标
                        int rootTopy = location[1];
                        if (mRawx >= 0 && mRawx <= mRootMeasuredWidth && mRawy >= rootTopy && mRawy <= (mRootMeasuredHeight + rootTopy)) {
                            //手指X轴滑动距离
                            float differenceValuex = mRawx - mLastRawx;
                            //手指Y轴滑动距离
                            float differenceValuey = mRawy - mLastRawy;
                            //判断是否为拖动操作
                            if (!isDrug) {
                                isDrug = !(Math.sqrt(differenceValuex * differenceValuex + differenceValuey * differenceValuey) < 2);
                            }
                            //获取手指按下的距离与控件本身X轴的距离
                            float ownx = getX();
                            //获取手指按下的距离与控件本身Y轴的距离
                            float owny = getY();
                            //理论中X轴拖动的距离
                            float endx = ownx + differenceValuex;
                            //理论中Y轴拖动的距离
                            float endy = owny + differenceValuey;
                            //X轴可以拖动的最大距离
                            float maxx = mRootMeasuredWidth - getWidth();
                            //Y轴可以拖动的最大距离
                            float maxy = mRootMeasuredHeight - getHeight();
                            //X轴边界限制
                            endx = endx < 0 ? 0 : endx > maxx ? maxx : endx;
                            //Y轴边界限制
                            endy = endy < 0 ? 0 : endy > maxy ? maxy : endy;
                            //开始移动
                            setX(endx);
                            setY(endy);
                            //记录位置
                            mLastRawx = mRawx;
                            mLastRawy = mRawy;
                        }
                    }
                    break;
                //手指离开
                case MotionEvent.ACTION_UP:
                    //恢复按压效果
                    setPressed(false);
                    float center = mRootMeasuredWidth / 2;
                    //自动贴边
                    if (mLastRawx <= center) {
                        //向左贴边
                        DragFloatBtnT.this.animate()
                                .setInterpolator(new BounceInterpolator())
                                .setDuration(500)
                                .x(padding)
                                .start();
                    } else {
                        //向右贴边
                        DragFloatBtnT.this.animate()
                                .setInterpolator(new BounceInterpolator())
                                .setDuration(500)
                                .x(mRootMeasuredWidth - getWidth() - padding)
                                .start();
                    }
                    break;
                default:
            }
            //是否拦截事件
            return isDrug ? isDrug : super.onTouchEvent(ev);
        }
    }
    

    代码中的DensityUtils源码如下:

    public class DensityUtils {
        /**
         * convert px to its equivalent dp
         *
         * 将px转换为与之相等的dp
         */
        public static int px2dp(Context context, float pxValue) {
            final float scale =  context.getResources().getDisplayMetrics().density;
            return (int) (pxValue / scale + 0.5f);
        }
    
    
        /**
         * convert dp to its equivalent px
         *
         * 将dp转换为与之相等的px
         */
        public static int dp2px(Context context, float dipValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dipValue * scale + 0.5f);
        }
    
    
        /**
         * convert px to its equivalent sp
         *
         * 将px转换为sp
         */
        public static int px2sp(Context context, float pxValue) {
            final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
            return (int) (pxValue / fontScale + 0.5f);
        }
    
    
        /**
         * convert sp to its equivalent px
         *
         * 将sp转换为px
         */
        public static int sp2px(Context context, float spValue) {
            final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
            return (int) (spValue * fontScale + 0.5f);
        }
    }
    
    

    相关文章

      网友评论

          本文标题:拖动悬浮按钮-继承自FloatingActionButton

          本文链接:https://www.haomeiwen.com/subject/svcowctx.html