Android實(shí)現(xiàn)炫酷的拖拽浮動(dòng)按鈕
IOS的Assistive Touch效果很炫酷,可以任意拖拽,同時(shí)點(diǎn)擊后會(huì)展開(kāi)菜單欄。然而,這不只是IOS的特權(quán),Android也可以實(shí)現(xiàn)。但是由于懸浮窗需要申請(qǐng)權(quán)限,所以本文僅在app內(nèi)實(shí)現(xiàn),可以任意拖拽,并可以響應(yīng)點(diǎn)擊事件。
一、效果圖

二、實(shí)現(xiàn)原理
1、拖拽實(shí)現(xiàn)
下面具體介紹重寫(xiě)onTouch方法的具體實(shí)現(xiàn)
case MotionEvent.ACTION_DOWN:{mDownPointerId = MotionEventCompat.getPointerId(event, 0);mPreviousX = event.getRawX();mPreviousY = event.getRawY();break;}
case MotionEvent.ACTION_MOVE:{if (mDownPointerId >= 0) {int index = MotionEventCompat.getActionIndex(event);int id = MotionEventCompat.getPointerId(event, index);if (id == mDownPointerId) {boolean update = adjustMarginParams(view, event);if (!update) {break;}mFloatView.requestLayout();mHasMoved = true;result = true;}}break;}
private boolean adjustMarginParams(View v, MotionEvent event) {float x = event.getRawX();float y = event.getRawY();float deltaX = x - mPreviousX;float deltaY = y - mPreviousY;if (!mHasMoved) {if (Math.abs(deltaX) < mTouchSlop && Math.abs(deltaY) < mTouchSlop) {return false;}}//左上角位置int newX = (int)x - mFloatView.getWidth() / 2;int newY = (int)y - mFloatView.getHeight() / 2;newX = Math.max(newX, mBoundsInScreen.left + mEdgePaddingLeft);newX = Math.min(newX, mBoundsInScreen.right - mEdgePaddingRight - mFloatView.getWidth());newY = Math.max(newY, mBoundsInScreen.top + mEdgePaddingTop);newY = Math.min(newY, mBoundsInScreen.bottom - mEdgePaddingBottom - mFloatView.getHeight());mFloatViewWindowParam.x = newX;mFloatViewWindowParam.y = newY - mParentMarginTop;return true;}
case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:{if (mDownPointerId >= 0 && mHasMoved) {event.setAction(MotionEvent.ACTION_CANCEL);adjustMarginParams(view, event);mFloatView.requestLayout();int center = (mBoundsInScreen.width() - mFloatView.getWidth()) / 2;int x = mFloatViewWindowParam.x;int destX = 0;int posX = Gravity.LEFT;//抬起時(shí) 根據(jù)位置強(qiáng)制把浮動(dòng)按鈕歸于左邊或右邊if (x < center) { // 左邊destX = mBoundsInScreen.left + mEdgePaddingLeft;} else {posX = Gravity.RIGHT;destX = mBoundsInScreen.right - mEdgePaddingRight - mFloatView.getWidth();}if (mFloatButtonCallback != null) {float posY = 0;if (mBoundsInScreen.height() - mFloatView.getHeight() != 0) {posY = 1f * (mFloatViewWindowParam.y - mBoundsInScreen.top) / (mBoundsInScreen.height() - mFloatView.getHeight());}mFloatButtonCallback.onPositionChanged(destX, mFloatViewWindowParam.y, posX, posY);}int deltaHorizon = destX - x;//小于100直接移動(dòng) 否則開(kāi)啟動(dòng)畫(huà)if (Math.abs(deltaHorizon) < 100) {mFloatViewWindowParam.x = destX;mFloatView.requestLayout();} else {ValueAnimator animator = ValueAnimator.ofInt(x, destX);animator.setInterpolator(mInterpolator);if (mUpdateListener == null) {mUpdateListener = new FloatAnimatorUpdateListener();mUpdateListener.setUpdateView(FloatTouchListener.this);}animator.addUpdateListener(mUpdateListener);animator.setDuration(200);animator.start();}}resetStatus();break;}}
2、點(diǎn)擊實(shí)現(xiàn)
public boolean onTouch(View view, MotionEvent event) {int action = MotionEventCompat.getActionMasked(event);if (mFloatButtonCallback != null) {mFloatButtonCallback.onTouch();}boolean result = false;switch (action) {case MotionEvent.ACTION_DOWN:{....................................................break;}case MotionEvent.ACTION_MOVE:{....................................................result = true;break;}case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:{................................................break;}}return result;}
原理就是這么簡(jiǎn)單,更加炫酷的效果可自定義實(shí)現(xiàn)
評(píng)論
圖片
表情
