创建主页按钮仍然有效的系统覆盖?

我正在尝试创建一个始终在屏幕上的按钮。

  1. 按钮应该是可点击的,按下按钮下面的任何内容都不应该被激活。
  2. 在按钮后面运行的活动或主屏幕应该仍然有效,这意味着用户仍然可以与主屏幕或应用程序进行交互。
  3. 软键按钮仍然可以工作:家庭,后面,菜单等

以下代码执行#1和#2,但软键按钮不再起作用:

WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); 

将其更改为此选项会禁用叠加层,但#2和#3会起作用:

 WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 

最后在这个例子中,叠加以及它背后的内容被点击:

 WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, 

如何更改此设置以使叠加层可以点击,直接在其下面是不可点击的,并且叠加层之外的所有内容都可以使用,包括主页按钮?

执行所有这些的示例应用程序是Super Manager。

更新:我发现以下内容允许使用主页按钮,但仍然不能使用其他按钮:

  WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 

  1. 你不能将OR窗口types放在一起。 您将创建一些随机的其他types。 说实话,您使用的窗口types实际上并不打算供应用程序使用(这就是为什么它们中包含“系统”一词)。

  2. “软键按钮不再起作用”是什么意思? 如果这是一个大问题(我想知道执行此操作的代码),就不应该停止工作。 其他键被传递到当前的关键焦点; 如果您不想聚焦,请使用FLAG_NOT_FOCUSABLE

  3. 每个标志的文档应该非常清楚它的作用,所以选择做你想做的标志。 FLAG_NOT_FOCUSABLE因为您不想接受关键事件。 FLAG_NOT_TOUCH_MODAL因为您不想阻止窗口外的触摸事件。 您并不是说您想了解窗外的印刷机,因此没有理由使用FLAG_WATCH_OUTSIDE_TOUCH

我看到pcm2a没有发布一个有效的解决方案,所以我不妨为他做。

注意 :虽然我提出了一种可行的解决方案,但就Android架构设计而言,使用这些方法并非100%正确。 我建议向Android开发团队的某些人询问更多信息(请在此发布他们的答案供我们所有人查看)。

权限

  

服务

 package com.vidmind.test.service.video; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.VideoView; public class TestVideoService extends Service { /** Command to the service to display a message */ public static final int MSG_PLAY_VIDEO = 1; public static final int MSG_VIDEO_LOOP_MODE = 2; /** Bundle Strings */ public static final String KEY_VIDEO_URL = "KEY_VIDEO_URL"; public static final String KEY_VIDEO_LOOP_MODE = "KEY_VIDEO_LOOP_MODE"; // Binder given to clients private static final String TAG = "TestVideoService"; final Messenger mMessenger = new Messenger(new IncomingHandler()); private LinearLayout mOverlay; private VideoView mVideoView; private boolean mVideoLoop = true; /** ****************** Handler implementation class ****************** **/ /** * Handler of incoming messages from clients. */ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { Bundle bundle; switch (msg.what) { case MSG_PLAY_VIDEO: bundle = msg.getData(); String url = bundle.getString(KEY_VIDEO_URL); play(url); break; case MSG_VIDEO_LOOP_MODE: bundle = msg.getData(); boolean looping = bundle.getBoolean(KEY_VIDEO_LOOP_MODE); setVideoLoop(looping); break; default: super.handleMessage(msg); } } } /** ****************************************************************** **/ @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "Service has started"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "Serice destroyed"); // Remove view from WindowManager WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.removeView(mOverlay); mOverlay = null; mVideoView = null; } /** ****************** Private Functions ****************** **/ /** * Set video loop mode * @param value */ private void setVideoLoop(boolean value) { mVideoLoop = value; } /** * Start playing the movie * @param url * @returns success/failure */ private boolean play(String url) { boolean isSuccess = false; if (mOverlay != null && mVideoView.isPlaying()) { Log.w(TAG, "Cannot recreate video overlay"); return isSuccess; } // Create overlay video createOverlay(mOverlay != null); if (!mVideoView.isPlaying()) { mVideoView.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setLooping(mVideoLoop); } }); mVideoView.setVideoURI(Uri.parse(url)); mVideoView.requestFocus(); mVideoView.start(); isSuccess = true; } return isSuccess; } /** * Create video overlay * * @param isCreated */ private void createOverlay(boolean isCreated) { if (isCreated) return; // Create System overlay video WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.FILL_PARENT, 150, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, PixelFormat.TRANSLUCENT); params.gravity = Gravity.BOTTOM; LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); mOverlay = (LinearLayout) inflater.inflate(R.layout.main, null); mVideoView = (VideoView) mOverlay.findViewById(R.id.video_player); WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.addView(mOverlay, params); } } 

layout.main

 < ?xml version="1.0" encoding="utf-8"?>    

快乐的编码!
阿米尔