Android 在所有應用的上層彈出可拖動的View
阿新 • • 發佈:2019-01-08
最近facebook Messenger添加了一個新的特性chatHead,這個圖示可以脫離所有的介面,顯示在android手機的所有應用的最上面。研究了下。記錄如下。
首先想到的是用一個透明的Activity來搞這個事情,想來facebook不會這麼愚蠢,試了下果然猜對了:
adb shell dumpsys activity,沒有發現相關activity。
其實facebook用的是service。
adb shell dumpsys activity services下發現果然找到了其service。
解釋下實現原理。
很簡單,就是將一個View新增到Window裡。我們知道,一個Activity有一個Window例項,Dialog也有他們自己的專用例項,Service也可以有一個Window。比如說InputMethodService可以用一個Window去接收Touch事件然後在任意一個Window的上面繪製一個鍵盤。DreamService用來建立屏保。
為了顯示一個新的Window,需要加入如下許可權:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
方法setChatHeadTouchListener可以使這個view可以在Window上隨意拖動。public class ChatHeadService extends Service { private WindowManager windowManager; private ImageView chatHead; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); chatHead = new ImageView(this); chatHead.setImageResource(R.drawable.ic_launcher); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); params.gravity = Gravity.TOP | Gravity.LEFT; params.x = 0; params.y = 100; windowManager.addView(chatHead, params); setChatHeadTouchListener(params); } private void setChatHeadTouchListener(final WindowManager.LayoutParams params) { chatHead.setOnTouchListener(new View.OnTouchListener() { private int initialX; private int initialY; private float initialTouchX; private float initialTouchY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: initialX = params.x; initialY = params.y; initialTouchX = event.getRawX(); initialTouchY = event.getRawY(); return true; case MotionEvent.ACTION_UP: return true; case MotionEvent.ACTION_MOVE: params.x = initialX + (int) (event.getRawX() - initialTouchX); params.y = initialY + (int) (event.getRawY() - initialTouchY); windowManager.updateViewLayout(chatHead, params); return true; } return false; } }); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if (chatHead != null) { windowManager.removeView(chatHead); } } }
別忘了在想顯示Window的時候開啟服務。
startService(new Intent(this, ChatHeadService.class));
這樣你就能看到一個可愛的Window顯示在所有的應用程式上面了。
程式碼地址:http://download.csdn.net/detail/liuhanhan512/7208705
有問題交流。