可移动悬浮球的实现
近期看到魅族的悬浮球功能,初步研究了下,实现了基本的功能。
一、Window 和WindowManger 的概念
Window:一个抽象类,具体实现在PhoneWindow。表示一个窗口的概念,Android中所有的View都是通过Window来显示的,Actvity/Dialog/Toast中的View都是附加在Window上的——Window是View的直接管理者。View的事件是由Window传递给DecorView,然后DecorView传递给View;setContentView的底层也是通过Window来完成
WindowManger:Window的管理者。有三大接口 Window添加——addView,Window删除——removeView,Window更新——updateViewLayout
二、使用WindowManger添加一个Window来实现悬浮效果
private void setFloatingButton() {
mFloatingBtn = new Button(this);
mFloatingBtn.setText("Suspend");
mLayoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
0,
0,
PixelFormat.TRANSPARENT);
mLayoutParams.flags =
//本区域内的事件自己处理,本区域外的事件底层Window处理
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
//不获取焦点,也不接收输入事件
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//可以显示锁屏界面
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;
//选用系统层级的Type,这样Window会显示在最顶层
mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
//利用WindowManger添加一个Window
getWindowManager().addView(mFloatingBtn, mLayoutParams);
}
三、悬浮球随手指滑动的效果
首先,要先给悬浮球设置onTouchListener
mFloatingBtn.setOnTouchListener(this);
然后,在onTouch方法中,不断更新View的位置即可,更新View位置使用了WindowManger的Window更新(updateViewLayout)方法
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
mLayoutParams.x = mLayoutParams.x + deltaX;
mLayoutParams.y = mLayoutParams.y + deltaY;
mWM.updateViewLayout(v, mLayoutParams);
mLastX = x;
mLastY = y;
break;
default:
break;
}
return false;
}
这样,一个具备基本功能的悬浮球效果就实现了。
扩展:
1.给这个悬浮球赋予更丰富的功能
2.在悬浮球随手指滑动的效果上做些动画,提升滑动体验
参考资料:《Android开发艺术探索》
https://github.com/xerrard/SuspendedBall