在最近的项目开发过程中,产品提出了一个需求,就是要求在屏幕上面有一个悬浮按钮,然后手势可以拖动,在手抬起的时候会回到屏幕边缘,类似于苹果的虚拟home键。
不多说了,直接上代码了,代码里面会有注释,可以解释清楚:整个Demo只有一个类,继承FloatingActionButton:
import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import com.rhzt.xgj.util.DisplayUtil;
/**
* Created by lixuce on 2017/5/8.
*/
public class DragFloatActionButton extends FloatingActionButton {
private int screenWidth;
private int screenHeight;
private int screenWidthHalf;
private int statusHeight;
public DragFloatActionButton(Context context) {
super(context);
init();
}
public DragFloatActionButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
//获取屏幕宽
screenWidth= DisplayUtil.getScreenWidth(getContext());
screenWidthHalf=screenWidth/2;
//屏幕的高
screenHeight=DisplayUtil.getScreenHight(getContext());
//状态栏的高度
// 如果状态栏可以拖动 就获取状态栏的高度 目前设置成0
statusHeight=0;
}
private int lastX;
private int lastY;
private boolean isDrag;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
isDrag=false;
getParent().requestDisallowInterceptTouchEvent(true);
lastX=rawX;
lastY=rawY;
break;
case MotionEvent.ACTION_MOVE:
isDrag=true;
//计算手指移动了多少
int dx=rawX-lastX;
int dy=rawY-lastY;
//这里修复一些华为手机无法触发点击事件的问题
int distance= (int) Math.sqrt(dx*dx+dy*dy);
if(distance==0){
isDrag=false;
break;
}
float x=getX()+dx;
float y=getY()+dy;
//检测是否到达边缘 左上右下
x=x<0?0:x>screenWidth-getWidth()?screenWidth-getWidth():x;
y=y<statusHeight?statusHeight:y+getHeight()>screenHeight?screenHeight-getHeight():y;
setX(x);
setY(y);
lastX=rawX;
lastY=rawY;
//Log.i("getX="+getX()+";getY="+getY()+";screenHeight="+screenHeight);
break;
case MotionEvent.ACTION_UP:
if(isDrag){
//恢复按压效果
setPressed(false);
// Log.i("getX="+getX()+";screenWidthHalf="+screenWidthHalf);
if(rawX>=screenWidthHalf){
animate().setInterpolator(new DecelerateInterpolator())
.setDuration(500)
.xBy(screenWidth-getWidth()-getX())
.start();
}else {
ObjectAnimator oa=ObjectAnimator.ofFloat(this,"x",getX(),0);
oa.setInterpolator(new DecelerateInterpolator());
oa.setDuration(500);
oa.start();
}
}
break;
}
//如果是拖拽则消耗事件,否则正常传递即可。你
return isDrag || super.onTouchEvent(event);
}
}
很简单就可以实现效果了,代码是应对我的需求来写的,你也可以自己来写,只是一个思路,希望可以帮到你。