Создание наложения системы, где домашние кнопки все еще работают?
Я пытаюсь создать кнопку, которая всегда находится на экране.
- Кнопка должна быть интерактивной и
ничего прямо под кнопкой
не следует активировать при нажатии.
- Работа или домашний экран
за кнопкой все равно работать,
что пользователь должен по-прежнему
способность взаимодействовать с домом
экрана или приложения.
- Программная клавиша
кнопки должны по-прежнему работать: дома,
назад, меню и т.д.
Следующий код содержит # 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.
UPDATE: я обнаружил, что следующее позволяет использовать кнопку дома, но все же не остальные кнопки:
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
Ответы
Ответ 1
-
Вы не можете использовать типы окон OR. Вы создадите некоторый случайный другой тип. И, честно говоря, типы окон, которые вы используете, действительно не предназначены для использования приложениями (поэтому у них есть слово "система" ).
-
Что вы подразумеваете под словом "мягкие клавиши больше не работают"? Нельзя прекращать работу дома, если это большая проблема (я хотел бы знать код для этого). Другие клавиши доставляются в текущий ключевой фокус; если вы не хотите сфокусироваться, используйте FLAG_NOT_FOCUSABLE
.
-
Документация для каждого из этих флагов должна быть довольно четкой, что она делает, поэтому выберите флаги, которые делают то, что вы хотите. FLAG_NOT_FOCUSABLE
, потому что вы не хотите принимать ключевые события. FLAG_NOT_TOUCH_MODAL
, потому что вы не хотите блокировать события касания, которые находятся за пределами вашего окна. Вы не говорите, что хотите узнать о прессах за окном, поэтому нет причин использовать FLAG_WATCH_OUTSIDE_TOUCH
.
Ответ 2
Я вижу, что pcm2a не опубликовал рабочего решения, поэтому я мог бы сделать это для него.
Примечание. Хотя я представляю рабочее решение, использование таких методов не на 100% прав в отношении дизайна архитектуры Android. Я рекомендую просить кого-то из команды разработчиков Android для получения дополнительной информации (и, пожалуйста, напишите свой ответ здесь, чтобы все мы могли видеть).
Разрешения
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Сервис
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"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView
android:id="@+id/video_player"
android:layout_width="120dp"
android:layout_height="120dp"/>
</LinearLayout>
Счастливое кодирование!
<я > Amir