废话不多说,开门见山,实现的效果如下图所示,手指能拖拽悬浮球移动,并会根据距离判断自动吸附于屏幕边缘,其半边隐藏于屏幕外。
方式一:自定义View重写onTouchEvent
onTouchEvent(MotionEvent event)是手机屏幕事件的处理方法,参数event为手机屏幕触摸事件封装类的对象,其中封装了该事件的所有信息;例如触摸的位置、触摸的类型以及触摸的时间等;该对象会在用户触摸手机屏幕时被创建。
开发中经常要用到的状态有以下三种,可以通过event.getAction()获得。
- 手指按下:MotionEvent.ACTION_DOWN
- 手指在屏幕上移动:MotionEvent.ACTION_MOVE
- 手指抬起:MotionEvent.ACTION_UP
现在通过一个示例来实现可拖拽、自动吸附的控件。自定义一个MovedImageButton继承自ImageButton,然后重写onTouchEvent方法,在该方法中,event.getX()、event.getY() 是用来获取触摸点在控件上的实时位置,然后用 lastX、lastY 来记录按下的瞬间触摸点在控件上的位置。
ACTION_MOVE 状态触发后,计算出手指在x轴和y轴的偏移量,再调用 layout(int l,int t,int r,int b) 方法,此方法用来重新绘制控件位置,4个参数分别表示控件左上角(l、t)和右下角(r,b)相对于 屏幕 的坐标,当然也可以用offsetLeftAndRight(int offsetX)、offsetTopAndBottom(int offsetY) 方法实现同样效果;最后手指离开屏幕的瞬间。
触发ACTION_UP状态后,此时控件需要移动到屏幕边缘,实现吸附效果,这里使用了ObjectAnimator或是控件自带的animate() 方法来实现自动移动的动画,另外添加了对距离的判断,以此选择停靠在屏幕哪个边缘。
public class MovedImageButton extends android.support.v7.widget.AppCompatImageButton {
private int lastX;
private int lastY;
private float screenWidth;
public MovedImageButton(Context context) {
super(context);
}
public MovedImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MovedImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-lastY;
//第一种方法
layout(getLeft()+offsetX,
getTop()+offsetY,
getRight()+offsetX,
getBottom()+offsetY);
//第二种方法
//offsetLeftAndRight(offsetX);
//offsetTopAndBottom(offsetY);
break;
case MotionEvent.ACTION_UP:
adsorbAnim(event.getRawX(), event.getRawY())