收到这个需求的时候第一想法是监听手指在屏幕中的操作,来实时获取手指所在屏幕的坐标,进行实时更新被拖动图的位置,但这种做法就会影响到页面中其它按钮的点击事件了。如果处理点击冲突事件,就记录被拖动图的区域再处理ontouch方法,这样就需要计算的成本很大了。
另外一种想法是,直接监听被拖动图的触摸事件,手指不停的移动,控件不停的改变位置,这种想法似乎更合理,只是要记录下最初位置,最后用平移动画要回去。思路整理清楚了,剩下就是代码的编写。
先处理的是onTouch方法:这里就是对被拖动控件的不断改变位置
@Override
public boolean onTouch(View v, MotionEvent event) {
//如果长按拖动 加上这句
// 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. 更新坐标位置
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;
}
再需要的是判断是否超过了阈值,需要获取目标控件的区域,然后需要获取手指所在的x,y值,判断手指是否在目标区域。
/**
* 判断是否拖拽超过了的阈值
*
* @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;
}
}
最后就一个属性动画,如果拖动不在目标区域内,那么就回到原来位置,需要向前甩一定值后再回到原来位置。那么就需要用到插值器了,使用OvershootInterpolator就可以了。从手指抬起的位置到被拖动控件的初始位置。
/**
* 供 DragDeleteTouchPerformerInternal 内部调用
* <p>
* 恢复原先位置
*/
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();
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:http://blog.itpub.net/69978258/viewspace-2708037/