在布局文件添加控件时可使用如下方式:
<android.support.design.widget.FloatingActionButton
.......
/>
也可使用自定义的包名:
com.example.notepad2.DragFloatActionButton
因为接下来要实现自定义的悬浮按钮,可根据实际情况自定。这里建议使用第二种方法,使用第一种时可能会出现闪退情况
<com.example.notepad2.DragFloatActionButton
android:id="@+id/fb"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:borderWidth="0dp"
app:backgroundTint="#FFFFFF"
app:rippleColor="#008577"
android:src="@drawable/hao"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
/>
实现自定义悬浮按钮
创建一个DragFloatActionButton类继承FloatingActionButton
在类中覆写 onTouchEvent 函数,捕捉触摸事件,然后利用setX(),setY() 方法将其移动。
而吸附效果,则是利用ObjectAnimator.ofFloat 实现动画。
//左吸附
ObjectAnimator oa=ObjectAnimator.ofFloat(this,"x",getX(),0);
oa.setInterpolator(new DecelerateInterpolator());
oa.setDuration(500);
oa.start();
使用的构造方法为
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
第一个参数为添加动画的对象
第二个参数为动画属性名称,这里我们使用alpha透明度动画
第三个参数为要改变的值,是可变的,这里我们从1变为0再变为1,也就是从不透明变成透明,然后变回来。
以下是 DragFloatActionButton 类的实现代码:
public class DragFloatActionButton extends FloatingActionButton {
private int parentHeight;
private int parentWidth;
public DragFloatActionButton(Context context) {
super(context);
}
public DragFloatActionButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
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:
setPressed(true);
isDrag=false;
getParent().requestDisallowInterceptTouchEvent(true);
lastX=rawX;
lastY=rawY;
ViewGroup parent;
if(getParent()!=null){
parent= (ViewGroup) getParent();
parentHeight=parent.getHeight();
parentWidth=parent.getWidth();
}
break;
case MotionEvent.ACTION_MOVE:
if(parentHeight<=0||parentWidth==0){
isDrag=false;
break;
}else {
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>parentWidth-getWidth()?parentWidth-getWidth():x;
y=getY()<0?0:getY()+getHeight()>parentHeight?parentHeight-getHeight():y;
setX(x);
setY(y);
lastX=rawX;
lastY=rawY;
Log.i("aa","isDrag="+isDrag+"getX="+getX()+";getY="+getY()+";parentWidth="+parentWidth);
break;
case MotionEvent.ACTION_UP:
if(!isNotDrag()){
//恢复按压效果
setPressed(false);
//Log.i("getX="+getX()+";screenWidthHalf="+screenWidthHalf);
/* animate().setInterpolator(new DecelerateInterpolator())
.setDuration(500)
.start();*/
if(rawX>=parentWidth/2){
//靠右吸附
animate().setInterpolator(new DecelerateInterpolator())
.setDuration(500)
.xBy(parentWidth-getWidth()-getX())
.start();
}else {
//靠左吸附
ObjectAnimator oa=ObjectAnimator.ofFloat(this,"x",getX(),0);
oa.setInterpolator(new DecelerateInterpolator());
oa.setDuration(500);
oa.start();
}
}
break;
}
//如果是拖拽则消s耗事件,否则正常传递即可。
return !isNotDrag() || super.onTouchEvent(event);
return ev.getAction() != MotionEvent.ACTION_UP && (mIsDrag || super.onTouchEvent(ev));
}
private boolean isNotDrag(){
return !isDrag&&(getX()==0
||(getX()==parentWidth-getWidth()));
}
}
DragFloatActionButton的使用
在布局文件中添加响应控件后在MainActivity中为其进行绑定
FloatingActionButton imageButton;
imageButton= (DragFloatActionButton)findViewById(R.id.fb);
同时必须 添加按钮点击事件,触发 onTouchEvent 函数
使按钮能被拖拽移动
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//添加要响应的内容
...........
}
});