android仿華為手機懸浮窗設計
本文實例為大家分享了android仿華為手機懸浮窗的具體代碼,供大家參考,具體內(nèi)容如下
最近項目中有個需求就是要在android 系統(tǒng)桌面上寫一個懸浮球,并使其具有返回,進到主頁,打開設置等功能。類似于華為手機的懸浮球。這里主要用到windowManager來實現(xiàn)。
1.先來看看效果圖
主頁的小圓點
點擊小圓點之后展開,然后可以模擬虛擬按鍵,返回等功能。全局有效。
2.一步步來實現(xiàn)
1.首先這個要常住在桌面,故得寫在一個服務里面里面。服務的啟動可以通過開機廣播,或者在Activity 中啟動后直接finish 掉,這里都做一下。方便點擊測試
public class MainActivity extends Activity { ? ? private static final int NOT_NOTICE = 2;//如果勾選了不再詢問 ? ? private AlertDialog alertDialog; ? ? private AlertDialog mDialog; ? ? @Override ? ? protected void onCreate(Bundle savedInstanceState) { ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? setContentView(R.layout.activity_main); ? ? ? ? Intent intent = new Intent(MainActivity.this, FloatWindowService.class); ? ? ? ? startService(intent); ? ? ? ? finish(); ? ? } }
public class FwBroadcastReceiver extends BroadcastReceiver { ? ? public static final String TAG = "FwBroadcastReceiver"; ? ? public static final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED"; ? ? public static final String ACTION_STASRT_FLAOTWINDOW = "android.intent.action.start.FlaotWindow"; ? ? @Override ? ? public void onReceive(Context context, Intent intent) { ? ? ? ? Log.d(TAG, "intent:" + intent.getAction()); ? ? ? ? startFloatWindowService(context); ? ? } ? ? private void startFloatWindowService(Context context) { ? ? ? ? Intent intent = new Intent(context, FloatWindowService.class); ? ? ? ? context.startService(intent); ? ? } }
2.FloatWindowService 中去創(chuàng)建懸浮球
public class FloatWindowService extends Service { ? ? /** ? ? ?* 用于在線程中創(chuàng)建或移除懸浮窗。 ? ? ?*/ ? ? private Handler handler = new Handler(); ? ? /** ? ? ?* 定時器,定時進行檢測當前應該創(chuàng)建還是移除懸浮窗。 ? ? ?*/ ? ? private Timer timer; ? ? @Override ? ? public IBinder onBind(Intent intent) { ? ? ? ? return null; ? ? } ? ? @Override ? ? public int onStartCommand(Intent intent, int flags, int startId) { ? ? ? ? // 開啟定時器,每隔0.5秒刷新一次 ? ? ? ? if (timer == null) { ? ? ? ? ? ? timer = new Timer(); ? ? ? ? ? ? timer.scheduleAtFixedRate(new RefreshTask(), 0, 500); ? ? ? ? } ? ? ? ? return super.onStartCommand(intent, flags, startId); ? ? } ? ? @Override ? ? public void onDestroy() { ? ? ? ? super.onDestroy(); ? ? ? ? // Service被終止的同時也停止定時器繼續(xù)運行 ? ? ? ? if (timer != null) { ? ? ? ? ? ? timer.cancel(); ? ? ? ? ? ? timer = null; ? ? ? ? } ? ? } ? ? class RefreshTask extends TimerTask { ? ? ? ? @Override ? ? ? ? public void run() { ? ? ? ? ? ? // 沒有懸浮窗顯示,則創(chuàng)建懸浮窗。 ? ? ? ? ? ? if ( !MyWindowManager.isWindowShowing()) { ? ? ? ? ? ? ? ? handler.post(new Runnable() { ? ? ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? ? ? ? ? MyWindowManager.createSmallWindow(getApplicationContext()); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? } ? ? }
3. 核心部分,創(chuàng)建大小懸浮窗
public class MyWindowManager { ? ? /** ? ? ?* 小懸浮窗View的實例 ? ? ?*/ ? ? private static FloatWindowSmallView smallWindow; ? ? /** ? ? ?* 大懸浮窗View的實例 ? ? ?*/ ? ? private static FloatWindowBigView bigWindow; ? ? /** ? ? ?* 小懸浮窗View的參數(shù) ? ? ?*/ ? ? private static LayoutParams smallWindowParams; ? ? /** ? ? ?* 大懸浮窗View的參數(shù) ? ? ?*/ ? ? private static LayoutParams bigWindowParams; ? ? /** ? ? ?* 用于控制在屏幕上添加或移除懸浮窗 ? ? ?*/ ? ? private static WindowManager mWindowManager; ? ? /** ? ? ?* 創(chuàng)建一個小懸浮窗。初始位置為屏幕的右部中間位置。 ? ? ?* ? ? ?* @param context 必須為應用程序的Context. ? ? ?*/ ? ? public static void createSmallWindow(Context context) { ? ? ? ? WindowManager windowManager = getWindowManager(context); ? ? ? ? int screenWidth = windowManager.getDefaultDisplay().getWidth(); ? ? ? ? int screenHeight = windowManager.getDefaultDisplay().getHeight(); ? ? ? ? if (smallWindow == null) { ? ? ? ? ? ? smallWindow = new FloatWindowSmallView(context); ? ? ? ? ? ? if (smallWindowParams == null) { ? ? ? ? ? ? ? ? smallWindowParams = new LayoutParams(); ? ? ? ? ? ? ? ? smallWindowParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY; ? ? ? ? ? ? ? ? smallWindowParams.format = PixelFormat.RGBA_8888; ? ? ? ? ? ? ? ? smallWindowParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL ? ? ? ? ? ? ? ? ? ? ? ? | LayoutParams.FLAG_NOT_FOCUSABLE; ? ? // 注意這里的flag和type ? ? ? ? ? ? ? ? smallWindowParams.gravity = Gravity.LEFT | Gravity.TOP; ? ? ? ? ? ? ? ? smallWindowParams.width = FloatWindowSmallView.viewWidth; ? ? ? ? ? ? ? ? smallWindowParams.height = FloatWindowSmallView.viewHeight; ? ? ? ? ? ? ? ? smallWindowParams.x = screenWidth; ? ? ? ? ? ? ? ? smallWindowParams.y = screenHeight / 2; ? ? ? ? ? ? } ? ? ? ? ? ? smallWindow.setParams(smallWindowParams); ? ? ? ? ? ? windowManager.addView(smallWindow, smallWindowParams); ? ? ? ? } ? ? } ? ? /** ? ? ?* 將小懸浮窗從屏幕上移除。 ? ? ?* ? ? ?* @param context 必須為應用程序的Context. ? ? ?*/ ? ? public static void removeSmallWindow(Context context) { ? ? ? ? if (smallWindow != null) { ? ? ? ? ? ? WindowManager windowManager = getWindowManager(context); ? ? ? ? ? ? windowManager.removeView(smallWindow); ? ? ? ? ? ? smallWindow = null; ? ? ? ? } ? ? } ? ? /** ? ? ?* 創(chuàng)建一個大懸浮窗。位置為屏幕正中間。 ? ? ?* ? ? ?* @param context 必須為應用程序的Context. ? ? ?*/ ? ? public static void createBigWindow(Context context) { ? ? ? ? WindowManager windowManager = getWindowManager(context); ? ? ? ? int screenWidth = windowManager.getDefaultDisplay().getWidth(); ? ? ? ? int screenHeight = windowManager.getDefaultDisplay().getHeight(); ? ? ? ? if (bigWindow == null) { ? ? ? ? ? ? bigWindow = new FloatWindowBigView(context); ? ? ? ? ? ? if (bigWindowParams == null) { ? ? ? ? ? ? ? ? bigWindowParams = new LayoutParams(); //?? ??? ??? ??? ?bigWindowParams.x = screenWidth / 2 - FloatWindowBigView.viewWidth / 2; //?? ??? ??? ??? ?bigWindowParams.y = screenHeight / 2 - FloatWindowBigView.viewHeight / 2; ? ? ? ? ? ? ? ? bigWindowParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY; ? ? ? ? ? ? ? ? bigWindowParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE; ?// 這里的flag,如果不加這個,這這個界面的返回鍵(上面實際圖的返回按鈕)則沒有作用,因為這個界面會消耗這個模擬的返回按鍵 ? ? ? ? ? ? ? ? bigWindowParams.format = PixelFormat.RGBA_8888; ? ? ? ? ? ? ? ? bigWindowParams.gravity = Gravity.RIGHT; ? ? ? ? ? ? ? ? bigWindowParams.width = FloatWindowBigView.viewWidth; ? ? ? ? ? ? ? ? bigWindowParams.height = FloatWindowBigView.viewHeight; ? ? ? ? ? ? } ? ? ? ? ? ? windowManager.addView(bigWindow, bigWindowParams); ? ? ? ? } ? ? } ? ? /** ? ? ?* 將大懸浮窗從屏幕上移除。 ? ? ?* ? ? ?* @param context 必須為應用程序的Context. ? ? ?*/ ? ? public static void removeBigWindow(Context context) { ? ? ? ? if (bigWindow != null) { ? ? ? ? ? ? WindowManager windowManager = getWindowManager(context); ? ? ? ? ? ? windowManager.removeView(bigWindow); ? ? ? ? ? ? bigWindow = null; ? ? ? ? } ? ? } ? ? /** ? ? ?* 是否有懸浮窗(包括小懸浮窗和大懸浮窗)顯示在屏幕上。 ? ? ?* ? ? ?* @return 有懸浮窗顯示在桌面上返回true,沒有的話返回false。 ? ? ?*/ ? ? public static boolean isWindowShowing() { ? ? ? ? return smallWindow != null || bigWindow != null; ? ? } ? ? /** ? ? ?* 如果WindowManager還未創(chuàng)建,則創(chuàng)建一個新的WindowManager返回。否則返回當前已創(chuàng)建的WindowManager。 ? ? ?* ? ? ?* @param context 必須為應用程序的Context. ? ? ?* @return WindowManager的實例,用于控制在屏幕上添加或移除懸浮窗。 ? ? ?*/ ? ? private static WindowManager getWindowManager(Context context) { ? ? ? ? if (mWindowManager == null) { ? ? ? ? ? ? mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); ? ? ? ? } ? ? ? ? return mWindowManager; ? ? }
4.小懸浮窗布局
public class FloatWindowSmallView extends LinearLayout { ?? ?/** ?? ? * 記錄小懸浮窗的寬度 ?? ? */ ?? ?public static int viewWidth; ?? ?/** ?? ? * 記錄小懸浮窗的高度 ?? ? */ ?? ?public static int viewHeight; ?? ?/** ?? ? * 記錄系統(tǒng)狀態(tài)欄的高度 ?? ? */ ?? ? private static int statusBarHeight; ?? ?/** ?? ? * 用于更新小懸浮窗的位置 ?? ? */ ?? ?private WindowManager windowManager; ?? ?/** ?? ? * 小懸浮窗的參數(shù) ?? ? */ ?? ?private WindowManager.LayoutParams mParams; ?? ?/** ?? ? * 記錄當前手指位置在屏幕上的橫坐標值 ?? ? */ ?? ?private float xInScreen; ?? ?/** ?? ? * 記錄當前手指位置在屏幕上的縱坐標值 ?? ? */ ?? ?private float yInScreen; ?? ?/** ?? ? * 記錄手指按下時在屏幕上的橫坐標的值 ?? ? */ ?? ?private float xDownInScreen; ?? ?/** ?? ? * 記錄手指按下時在屏幕上的縱坐標的值 ?? ? */ ?? ?private float yDownInScreen; ?? ?/** ?? ? * 記錄手指按下時在小懸浮窗的View上的橫坐標的值 ?? ? */ ?? ?private float xInView; ?? ?/** ?? ? * 記錄手指按下時在小懸浮窗的View上的縱坐標的值 ?? ? */ ?? ?private float yInView; ?? ?public FloatWindowSmallView(Context context) { ?? ??? ?super(context); ?? ??? ?windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); ?? ??? ?LayoutInflater.from(context).inflate(R.layout.float_window_small, this); ?? ??? ?View view = findViewById(R.id.small_window_layout); ?? ??? ?viewWidth = view.getLayoutParams().width; ?? ??? ?viewHeight = view.getLayoutParams().height; ?? ?} ?? ?@Override ?? ?public boolean onTouchEvent(MotionEvent event) { ?? ??? ?switch (event.getAction()) { ?? ??? ?case MotionEvent.ACTION_DOWN: ?? ??? ??? ?// 手指按下時記錄必要數(shù)據(jù),縱坐標的值都需要減去狀態(tài)欄高度 ?? ??? ??? ?xInView = event.getX(); ?? ??? ??? ?yInView = event.getY(); ?? ??? ??? ?xDownInScreen = event.getRawX(); ?? ??? ??? ?yDownInScreen = event.getRawY() - getStatusBarHeight(); ?? ??? ??? ?xInScreen = event.getRawX(); ?? ??? ??? ?yInScreen = event.getRawY() - getStatusBarHeight(); ?? ??? ??? ?Log.d("xct","down"+"xInView:"+xInView+"yInView:"+yInView+"xInScreen:"+xInScreen+"yInScreen:"+yInScreen); ?? ??? ??? ?break; ?? ??? ?case MotionEvent.ACTION_MOVE: ?? ??? ??? ?xInScreen = event.getRawX(); ?? ??? ??? ?yInScreen = event.getRawY() - getStatusBarHeight(); ?? ??? ??? ?// 手指移動的時候更新小懸浮窗的位置 ?? ??? ??? ?Log.d("xct","move"+"xInView:"+xInView+"yInView:"+yInView+"xInScreen:"+xInScreen+"yInScreen:"+yInScreen); ?? ??? ??? ?updateViewPosition(); ?? ??? ??? ?break; ?? ??? ?case MotionEvent.ACTION_UP: ?? ??? ??? ?// 如果手指離開屏幕時,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,則視為觸發(fā)了單擊事件。 ?? ??? ??? ?Log.d("xct","up"+"xInView:"+xInView+"yInView:"+yInView+"xInScreen:"+xInScreen+"yInScreen:"+yInScreen); ?? ??? ??? ?if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { ?? ??? ??? ??? ?openBigWindow(); ?? ??? ??? ?} ?? ??? ??? ?break; ?? ??? ?default: ?? ??? ??? ?break; ?? ??? ?} ?? ??? ?return true; ?? ?} ?? ?/** ?? ? * 將小懸浮窗的參數(shù)傳入,用于更新小懸浮窗的位置。 ?? ? *? ?? ? * @param params ?? ? * ? ? ? ? ? ?小懸浮窗的參數(shù) ?? ? */ ?? ?public void setParams(WindowManager.LayoutParams params) { ?? ??? ?mParams = params; ?? ?} ?? ?/** ?? ? * 更新小懸浮窗在屏幕中的位置。 ?? ? */ ?? ?private void updateViewPosition() { ?? ??? ?mParams.x = (int) (xInScreen - xInView); ?? ??? ?mParams.y = (int) (yInScreen - yInView); ?? ??? ?windowManager.updateViewLayout(this, mParams); ?? ?} ?? ?/** ?? ? * 打開大懸浮窗,同時關閉小懸浮窗。 ?? ? */ ?? ?private void openBigWindow() { ?? ??? ?MyWindowManager.createBigWindow(getContext()); ?? ??? ?MyWindowManager.removeSmallWindow(getContext()); ?? ?} ?? ?/** ?? ? * 用于獲取狀態(tài)欄的高度。 ?? ? *? ?? ? * @return 返回狀態(tài)欄高度的像素值。 ?? ? */ ?? ?private int getStatusBarHeight() { ?? ??? ?if (statusBarHeight == 0) { ?? ??? ??? ?try { ?? ??? ??? ??? ?Class<?> c = Class.forName("com.android.internal.R$dimen"); ?? ??? ??? ??? ?Object o = c.newInstance(); ?? ??? ??? ??? ?Field field = c.getField("status_bar_height"); ?? ??? ??? ??? ?int x = (Integer) field.get(o); ?? ??? ??? ??? ?statusBarHeight = getResources().getDimensionPixelSize(x); ?? ??? ??? ?} catch (Exception e) { ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?} ?? ??? ?} ?? ??? ?return statusBarHeight; ?? ?} }
5.大懸浮窗布局
public class FloatWindowBigView extends LinearLayout{ ? ? /** ? ? ?* 記錄大懸浮窗的寬度 ? ? ?*/ ? ? public static int viewWidth; ? ? /** ? ? ?* 記錄大懸浮窗的高度 ? ? ?*/ ? ? public static int viewHeight; ? ? /** ? ? ?* 記錄當前手指位置在屏幕上的橫坐標值 ? ? ?*/ ? ? private float xInScreen; ? ? /** ? ? ?* 記錄當前手指位置在屏幕上的縱坐標值 ? ? ?*/ ? ? private float yInScreen; ? ? private static int statusBarHeight; ? ? /** ? ? ?* 記錄手指按下時在屏幕上的橫坐標的值 ? ? ?*/ ? ? private float xDownInScreen; ? ? /** ? ? ?* 記錄手指按下時在屏幕上的縱坐標的值 ? ? ?*/ ? ? private float yDownInScreen; ? ? /** ? ? ?* 記錄手指按下時在小懸浮窗的View上的橫坐標的值 ? ? ?*/ ? ? private float xInView; ? ? /** ? ? ?* 記錄手指按下時在小懸浮窗的View上的縱坐標的值 ? ? ?*/ ? ? private float yInView; ? ? @Override ? ? public boolean onTouchEvent(MotionEvent event) { ? ? ? ? Log.d("xct","onTouchEvent"); ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? // 手指按下時記錄必要數(shù)據(jù),縱坐標的值都需要減去狀態(tài)欄高度 ? ? ? ? ? ? ? ? xInView = event.getX(); ? ? ? ? ? ? ? ? yInView = event.getY(); ? ? ? ? ? ? ? ? xDownInScreen = event.getRawX(); ? ? ? ? ? ? ? ? yDownInScreen = event.getRawY() - getStatusBarHeight(); ? ? ? ? ? ? ? ? xInScreen = event.getRawX(); ? ? ? ? ? ? ? ? yInScreen = event.getRawY() - getStatusBarHeight(); ? ? ? ? ? ? ? ? Log.d("xct", "down" + "xInView:" + xInView + "yInView:" + yInView + "xInScreen:" + xInScreen + "yInScreen:" + yInScreen); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? xInScreen = event.getRawX(); ? ? ? ? ? ? ? ? yInScreen = event.getRawY() - getStatusBarHeight(); ? ? ? ? ? ? ? ? // 手指移動的時候更新小懸浮窗的位置 ? ? ? ? ? ? ? ? Log.d("xct", "move" + "xInView:" + xInView + "yInView:" + yInView + "xInScreen:" + xInScreen + "yInScreen:" + yInScreen); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_UP: ? ? ? ? ? ? ? ? // 如果手指離開屏幕時,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,則視為觸發(fā)了單擊事件。 ? ? ? ? ? ? ? ? if (xInView < 0 || yInView < 0 || yInView > 445){ ? ? ? ? ? ? ? ? ? ? ? ? ContronPresent.getInstance().closeBigFlaot(getContext()); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? Log.d("xct", "up" + "xInView:" + xInView + "yInView:" + yInView + "xInScreen:" + xInScreen + "yInScreen:" + yInScreen); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? default: ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? return super.onTouchEvent(event); ? ? } ? ? public FloatWindowBigView(final Context context) { ? ? ? ? super(context); ? ? ? ? LayoutInflater.from(context).inflate(R.layout.float_window_big, this); ? ? ? ? View view = findViewById(R.id.big_window_layout); ? ? ? ? viewWidth = view.getLayoutParams().width; ? ? ? ? viewHeight = view.getLayoutParams().height; ? ? ? ? Button close = findViewById(R.id.close); ? ? ? ? Button back = ?findViewById(R.id.back); ? ? ? ? Button home = findViewById(R.id.home); ? ? ? ? Button rorate = findViewById(R.id.rorate); ? ? ? ? Button control = findViewById(R.id.control); ? ? ? ? close.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? // 點擊返回的時候,移除大懸浮窗,創(chuàng)建小懸浮窗 ? ? ? ? ? ? ? ? MyWindowManager.removeBigWindow(context); ? ? ? ? ? ? ? ? MyWindowManager.createSmallWindow(context); ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? back.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ?new Thread(){ ? ? ? ? ? ? @Override ? ? ? ? ? ? public void run() { ? ? ? ? ? ? ? ? new Instrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); ? ? ? ? ? ? } ? ? ? ? }.start(); ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? home.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? Log.d("xct","去home頁"); ? ? ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? rorate.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? control.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? Log.d("xct","控制中心"); ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? }); ? ? } ? ? private int getStatusBarHeight() { ? ? ? ? if (statusBarHeight == 0) { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? Class<?> c = Class.forName("com.android.internal.R$dimen"); ? ? ? ? ? ? ? ? Object o = c.newInstance(); ? ? ? ? ? ? ? ? Field field = c.getField("status_bar_height"); ? ? ? ? ? ? ? ? int x = (Integer) field.get(o); ? ? ? ? ? ? ? ? statusBarHeight = getResources().getDimensionPixelSize(x); ? ? ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return statusBarHeight; ? ? } ? ? @Override ? ? public boolean dispatchKeyEvent(KeyEvent event) { ? ? ? ? Log.i("xct", "dispatchKeyEvent: "+event.getKeyCode()); ? ? ? ? return true; ? ? } ? ? @Override ? ? public boolean dispatchTouchEvent(MotionEvent ev) { ? ? ? ? Log.d("xct","dispatchTouchEvent"); ? ? ? ? return super.dispatchTouchEvent(ev); ? ? } ? ? @Override ? ? public boolean onKeyDown(int keyCode, KeyEvent event) { ? ? ? ? Log.d("xct","onKeyDown:"+keyCode); ? ? ? ? return super.onKeyDown(keyCode, event); ? ? } }
6.需要注意的
這里需要注意的是,一是權限問題,因為我是系統(tǒng)權限,故不用申請,如果第三方需要使用,則如果動態(tài)申請。
另外就是在這我這個例子中,大懸浮窗中的模擬返回按鍵,是回有按鍵傳遞的,故大懸浮窗的參數(shù)中必須加入 bigWindowParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE; 否則返回事件會傳不下去。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android中Intent傳遞對象的兩種方法Serializable,Parcelable
這篇文章主要介紹了Android中的傳遞有兩個方法,一個是Serializable,另一個是Parcelable,對intent傳遞對象的兩種方法感興趣的朋友一起學習吧2016-01-01Android studio圓形進度條 百分數(shù)跟隨變化
這篇文章主要為大家詳細介紹了Android studio圓形進度條,百分號跟隨變化,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10Android入門之使用RecyclerView完美實現(xiàn)瀑布流界面詳解
網(wǎng)上充滿著不完善的基于RecyclerView的瀑布流實現(xiàn),要么根本是錯的、要么就是只知其一不知其二。本文就來用RecyclerView完美實現(xiàn)瀑布流界面,希望大家有所幫助2023-02-02解析Android開發(fā)優(yōu)化之:從代碼角度進行優(yōu)化的技巧
下面我們就從幾個方面來了解Android開發(fā)過程中的代碼優(yōu)化,需要的朋友參考下2013-05-05