您好,登錄后才能下訂單哦!
收到這個(gè)需求的時(shí)候第一想法是監(jiān)聽(tīng)手指在屏幕中的操作,來(lái)實(shí)時(shí)獲取手指所在屏幕的坐標(biāo),進(jìn)行實(shí)時(shí)更新被拖動(dòng)圖的位置,但這種做法就會(huì)影響到頁(yè)面中其它按鈕的點(diǎn)擊事件了。如果處理點(diǎn)擊沖突事件,就記錄被拖動(dòng)圖的區(qū)域再處理ontouch方法,這樣就需要計(jì)算的成本很大了。
另外一種想法是,直接監(jiān)聽(tīng)被拖動(dòng)圖的觸摸事件,手指不停的移動(dòng),控件不停的改變位置,這種想法似乎更合理,只是要記錄下最初位置,最后用平移動(dòng)畫(huà)要回去。思路整理清楚了,剩下就是代碼的編寫(xiě)。
先處理的是onTouch方法:這里就是對(duì)被拖動(dòng)控件的不斷改變位置
@Override public boolean onTouch(View v, MotionEvent event) { //如果長(zhǎng)按拖動(dòng) 加上這句 // if (!isLongClicked) return false; switch (event.getAction()) { case MotionEvent.ACTION_MOVE: { // 1. 添加到 Window 中 if (!dragDeleteView.isAttachedToWindow()) { dragDeleteView.bindAnchorView(anchorView); wm.addView(dragDeleteView, params); v.getParent().requestDisallowInterceptTouchEvent(true); v.setVisibility(View.INVISIBLE); } // 2. 更新坐標(biāo)位置 dragDeleteView.updateFingerPoint(event.getRawX(), event.getRawY()); break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { if (dragDeleteView.isOverThresholdHeight()) { wm.removeView(dragDeleteView); callback.onDelete(); } else { dragDeleteView.recover(); } v.getParent().requestDisallowInterceptTouchEvent(false); isLongClicked = false; break; } } return false; }
再需要的是判斷是否超過(guò)了閾值,需要獲取目標(biāo)控件的區(qū)域,然后需要獲取手指所在的x,y值,判斷手指是否在目標(biāo)區(qū)域。
/** * 判斷是否拖拽超過(guò)了的閾值 * * @return */ public boolean isOverThresholdHeight() { final int[] location = new int[2]; dragDeleteView.getLocationOnScreen(location); //獲得寬度 int width = dragDeleteView.getMeasuredWidth(); //獲得高度 int height = dragDeleteView.getMeasuredHeight(); float imgY = mCurPoint.y + mAnchorBitmap.getHeight() * 0.8f; float imgX = mCurPoint.x + mAnchorBitmap.getWidth() * 0.8f; if (imgX>(location[0])&&(imgX<location[0]+width)&&imgY>(location[1])&&imgY<(location[1]+height)){ return true; }else { return false; } }
最后就一個(gè)屬性動(dòng)畫(huà),如果拖動(dòng)不在目標(biāo)區(qū)域內(nèi),那么就回到原來(lái)位置,需要向前甩一定值后再回到原來(lái)位置。那么就需要用到插值器了,使用OvershootInterpolator就可以了。從手指抬起的位置到被拖動(dòng)控件的初始位置。
/** * 供 DragDeleteTouchPerformerInternal 內(nèi)部調(diào)用 * <p> * 恢復(fù)原先位置 */ private void recover() { final float deltaX = mCurPoint.x - mStartPoint.x; final float deltaY = mCurPoint.y - mStartPoint.y; ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f).setDuration(500); anim.setInterpolator(new OvershootInterpolator()); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mCurPoint.x = mStartPoint.x + deltaX * (float) animation.getAnimatedValue(); mCurPoint.y = mStartPoint.y + deltaY * (float) animation.getAnimatedValue(); invalidate(); } }); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mCallbackInternal.onRecovered(); } }); anim.start(); }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。