可移动悬浮球的实现
可移动悬浮球的实现
近期看到魅族的悬浮球功能,初步研究了下,实现了基本的功能。
一、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