最近做了手机虚拟按钮开发,和华为荣耀的虚拟按钮类似,效果如下(屏幕底下部分):
功能描述:手机开机,“虚拟按钮”自动隐藏,当从手机下边沿往上滑动时候,就自动出现! 没有操作的话,3秒就自动消失。
要实现这个功能需要解决这几个问题:(1)如何让其在手机开机的时候启动;(2)如何能在任何界面都能够响应手机使用者需要“虚拟按钮”的意图,并且弹出“虚拟按钮”;(3)如何检测使用者从手机下边沿往上滑动的事件;(4)如何模拟真实的home_key, menu_key和return_key事件。
下面一个一个的来解决这几个问题:
(1)如何让其在手机开机的时候启动:
这简单,定义一个receiver,其action为:android.intent.action.BOOT_COMPLETED这样就可以了。不过,你会发现手机开机完成后起码有一个较长的延时我们定义的action来能接收到!
(2)要在任何界面都能出现“虚拟按钮”,并且能做一些事情,很显然我们需要一个Service,这里我的Service是:NavBarService。在所有界面都能出现“虚拟按钮”,我们就只能用WindowManager,我们都知道可以用WindowManager来实现悬浮窗口,其实我们“虚拟按钮”就是一个悬浮view.
首先通过以下代码获取WindowManager的实列:WindowManager wm;
wm = (WindowManager)mContext.getSystemService("window");后面把我们布局好的view(LinearLayout holder;)添加上去就可以了:
wm.addView(holder, layoutparams);这里的LinearLayout holder;就是采用了一个LinearLayout来布局的!里面已经布局好了三个按钮:return按钮; home按钮;menu按钮。
这里我们要注意的是第二个参数:layoutparams
WindowManager.LayoutParams layoutparams = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); layoutparams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; layoutparams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; layoutparams.format = PixelFormat.TRANSLUCENT;(3)如何检测使用者从手机下边沿往上滑动的事件;
这个简单!就是用wm.addView添加一个简单view, 其view设置为全部透明的!并且高度只需要15dip,将这个view放置于屏幕的底部。用该view来检测使用者往上滑动的意图。
所以最后就形成了该全部透明的view和上面提到的三个按钮的view(holder) 相互切换,切换时候用WindowManager的renove来移除暂时不需要的view就可以了,如这样: wm.removeView(holder);
(4)如何模拟真实的home_key, menu_key和return_key事件。
首先通过三个按钮view的setOnLongClickListenerset和setOnClickListener来监听长按和短按事件!接下来就是如何模拟真实按键的方法,这里采用的是Instrumentation
public static void home_LongDown() { // Log.i(TAG, "home home_LongDown SystemClock.uptimeMillis()="+SystemClock.uptimeMillis()); new Thread() { public void run() { try { KeyEvent ev = new KeyEvent(SystemClock.uptimeMillis()-100, SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HOME, 1, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); new Instrumentation().sendKeySync(ev); // Log.i(TAG, "home_LongDown"); return; } catch (Exception e) { Log.d(TAG, e.toString()); } } }.start(); //playSoundEffect(android.view.SoundEffectConstants.CLICK); } public static void home_click() { //Log.i(TAG, "home click"); //playSoundEffect(android.view.SoundEffectConstants.CLICK); new Thread() { public void run() { try { new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_HOME); // Log.i(TAG, "Home"); return; } catch (Exception e) { Log.d(TAG, e.toString()); } } }.start(); }