Я пытаюсь создать постоянно активируемую кнопку / кликабельное изображение, которое постоянно остается поверх всех окон.
Доказательство концепции
- здесь - Smart Taskbar (на AppBrain)
- а вот V1.4.0 в стиле боковой панели SWKey - кнопка спасителя (на xda-developers)
Я добился успеха и теперь у меня есть работающий сервис. Сервис все время отображает текст в левом верхнем углу экрана, в то время как пользователь может свободно взаимодействовать с остальными приложениями в обычном режиме.
Я делаю подкласс ViewGroup
и добавляю его в корневой оконный менеджер с флагом TYPE_SYSTEM_OVERLAY
. Теперь я хочу добавить кнопку / clickable-изображение вместо этого текста, который может получать сенсорные события сам по себе. Я попытался переопределить «onTouchEvent» для всего, ViewGroup
но он не получает никакого события.
Как я могу получать события только в определенных частях моей группы с постоянным просмотром? Пожалуйста, предложите.
public class HUD extends Service {
HUDView mView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
// | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(),"onDestroy", Toast.LENGTH_LONG).show();
if(mView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(mView);
mView = null;
}
}
}
class HUDView extends ViewGroup {
private Paint mLoadPaint;
public HUDView(Context context) {
super(context);
Toast.makeText(getContext(),"HUDView", Toast.LENGTH_LONG).show();
mLoadPaint = new Paint();
mLoadPaint.setAntiAlias(true);
mLoadPaint.setTextSize(10);
mLoadPaint.setARGB(255, 255, 0, 0);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText("Hello World", 5, 15, mLoadPaint);
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//return super.onTouchEvent(event);
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
}
onDraw()
зовут. Не должноdispatchDraw()
быть отменено вместо этого? См. Groups.google.com/forum/?fromgroups#!topic/android-developers/…Ответы:
Это может быть глупым решением. Но это работает. Если вы можете улучшить его, пожалуйста, дайте мне знать.
На создание вашего сервиса: я использовал
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
флаг. Это единственное изменение в обслуживании.Теперь вы начнете получать каждое событие клика. Итак, вам нужно исправить в вашем обработчике событий.
В вашем сенсорном событии ViewGroup
Также вам может понадобиться добавить это разрешение в ваш манифест:
источник
После ответа @Sam Lu, действительно, Android 4.x блокирует определенные типы от прослушивания внешних событий касания, но некоторые типы, такие как
TYPE_SYSTEM_ALERT
, все еще делают работу.пример
права доступа
источник
Начиная с Android 4.x, Android команда исправлена потенциальная проблема безопасности, добавив новую функцию ,
adjustWindowParamsLw()
в которой он будет добавлятьFLAG_NOT_FOCUSABLE
,FLAG_NOT_TOUCHABLE
и удалятьFLAG_WATCH_OUTSIDE_TOUCH
флаги дляTYPE_SYSTEM_OVERLAY
окон.То есть
TYPE_SYSTEM_OVERLAY
окно не получит никакого сенсорного события на платформе ICS и, конечно, его использованиеTYPE_SYSTEM_OVERLAY
не является работоспособным решением для ICS и будущих устройств.источник
Я один из разработчиков Tooleap SDK . Мы также предоставляем разработчикам возможность всегда отображать верхние окна и кнопки, и мы столкнулись с подобной ситуацией.
Одной из проблем, на которые не были даны ответы, является проблема защищенных кнопок Android.
Защищенные кнопки имеют
filterTouchesWhenObscured
свойство, которое означает, что они не могут взаимодействовать, если находятся под окном, даже если это окно не получает никаких прикосновений. Цитирование документации Android:Примером такой кнопки является кнопка установки , когда вы пытаетесь установить сторонние apks. Любое приложение может отобразить такую кнопку, если добавить к макету вида следующую строку:
Если вы отображаете всегда поверх окна поверх «Защищенной кнопки», то все защищенные части кнопок, которые покрыты наложением, не будут обрабатывать никаких касаний, даже если это наложение не активировано. Поэтому, если вы планируете отображать такое окно, вы должны предоставить пользователю возможность его переместить или закрыть. И если часть вашего оверлея прозрачна, учтите, что ваш пользователь может быть сбит с толку, почему определенная кнопка в базовом приложении неожиданно для него не работает.
источник
РАБОТАЙТЕ ВСЕГДА НА КНОПКАХ TOP IMAGE
прежде всего извините за мой английский
я редактирую ваши коды и заставляю рабочую кнопку изображения, которая слушает его сенсорное событие, не давать сенсорное управление его фоновым элементам.
также это дает слушателям прикосновение к другим элементам
кнопки внизу и слева
Вы можете изменить настройки, но вам нужно изменить кординацию в событии touch в элементе if
источник
На самом деле вы можете попробовать WindowManager.LayoutParams.TYPE_SYSTEM_ERROR вместо TYPE_SYSTEM_OVERLAY. Это может звучать как хак, но оно позволяет отображать представление поверх всего и по-прежнему получать сенсорные события.
источник
TYPE_SYSTEM_OVERLAY Эта константа устарела начиная с уровня API 26. Вместо этого используйте TYPE_APPLICATION_OVERLAY. или ** для пользователей ниже и выше Android 8
источник
Попробуй это. Прекрасно работает в ICS. Если вы хотите остановить службу, просто нажмите на уведомление, созданное в строке состояния.
ОБНОВИТЬ
Образец здесь
Чтобы создать вид наложения, при настройке LayoutParams НЕ устанавливайте тип TYPE_SYSTEM_OVERLAY.
источник
Вот простое решение. Все, что вам нужно, это накачать XML-макет точно так же, как вы делаете это для адаптеров списков, просто создайте XML-макет, чтобы его накачать. Вот код, который вам нужен.
источник
Нашел библиотеку, которая делает именно это: https://github.com/recruit-lifestyle/FloatingView
В корневой папке есть пример проекта. Я запустил его, и он работает как требуется. Фон кликабелен - даже если это другое приложение.
источник
Он использует полное руководство "android.permission.SYSTEM_ALERT_WINDOW" по этой ссылке: http://androidsrc.net/facebook-chat-like-floating-chat-heads/
источник
Хорошо, попробуйте мой код, по крайней мере, он дает вам строку в качестве наложения, вы можете очень хорошо заменить его кнопкой или изображением. Вы не поверите, что это мое первое приложение для Android LOL. В любом случае, если вы более опытны с приложениями для Android, чем я, пожалуйста, попробуйте
источник
Если кто-то еще читает эту ветку и не может заставить ее работать, мне очень жаль сообщать вам, что этот способ перехвата события движения считается ошибкой и исправлением в Android> = 4.2.
Событие движения, которое вы перехватили, хотя и имеет действие ACTION_OUTSIDE, возвращает 0 в getX и getY. Это означает, что вы не можете видеть все позиции движения на экране, и вы ничего не можете сделать. Я знаю, что док сказал, что получит х и у, но правда в том, что НЕ БУДЕТ. Кажется, что это заблокировать регистратор ключей.
Если у кого-то есть обходной путь, пожалуйста, оставьте свой комментарий.
ref: Почему ACTION_OUTSIDE каждый раз возвращает 0 на KitKat 4.4.2?
https://code.google.com/p/android/issues/detail?id=72746
источник
с помощью сервиса вы можете добиться этого:
источник
Ответ @Sarwar Erfan больше не работает, так как Android не позволяет добавлять представление с WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY к окну, чтобы оно больше не было доступно даже с WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH.
Я нашел решение этой проблемы. Вы можете проверить это в следующем вопросе
При добавлении представления в окно с помощью WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY событие касания не отображается
источник
Это старый вопрос, но недавно в Android появилась поддержка Bubbles. Вскоре будут запущены пузыри, но в настоящее время разработчики могут начать использовать их. Они предназначены для альтернативы их использованию
SYSTEM_ALERT_WINDOW
. Такие приложения, как (Facebook Messenger и MusiXMatch используют одну и ту же концепцию).Пузыри создаются с помощью API уведомлений, вы отправляете уведомление как обычно. Если вы хотите, чтобы он пузырился, вам нужно приложить к нему дополнительные данные. Для получения дополнительной информации о Bubbles вы можете обратиться к официальному руководству Android для разработчиков по Bubbles .
источник