Estoy tratando de crear un botón / imagen de clic siempre superior que permanezca en la parte superior de todas las ventanas todo el tiempo.
La prueba de concepto es
- aquí - Smart Taskbar (en AppBrain)
- y aquí V1.4.0 Barra lateral estilo SWKey - Salvador de botón (en xda-developers)
He tenido éxito y tengo un servicio en ejecución ahora. El servicio muestra algo de texto en la esquina superior izquierda de la pantalla todo el tiempo, mientras que el usuario puede interactuar libremente con el resto de aplicaciones de manera normal.
Lo que estoy haciendo es una subclase ViewGroup
y la agrego al administrador de la ventana raíz con una marca TYPE_SYSTEM_OVERLAY
. Ahora quiero agregar un botón / imagen en la que se pueda hacer clic en lugar de este texto que pueda recibir eventos táctiles en sí mismo. Intenté anular "onTouchEvent" para todo ViewGroup
pero no recibe ningún evento.
¿Cómo puedo recibir eventos solo en ciertas partes de mi grupo de vista siempre arriba? Amablemente sugiera.
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()
llamen. ¿No deberíadispatchDraw()
ser anulado en su lugar? Ver groups.google.com/forum/?fromgroups#!topic/android-developers/…Respuestas:
Esta podría ser una solución estúpida. Pero funciona. Si puede mejorarlo, hágamelo saber.
OnCreate de su servicio: he usado
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
flag. Este es el único cambio en el servicio.Ahora, comenzará a obtener cada evento de clic. Por lo tanto, debe rectificar en su controlador de eventos.
En su evento táctil ViewGroup
También es posible que deba agregar este permiso a su manifiesto:
fuente
Siguiendo la respuesta de @Sam Lu, Indeed 4.x bloquea ciertos tipos para que no escuchen eventos táctiles externos, pero algunos tipos, como
TYPE_SYSTEM_ALERT
, todavía hacen el trabajo.Ejemplo
Permisos
fuente
Comenzando con Android 4.x, equipo de Android fija un problema potencial de seguridad mediante la adición de una nueva función
adjustWindowParamsLw()
en la que se va a añadirFLAG_NOT_FOCUSABLE
,FLAG_NOT_TOUCHABLE
y quitarFLAG_WATCH_OUTSIDE_TOUCH
banderas deTYPE_SYSTEM_OVERLAY
ventanas.Es decir, una
TYPE_SYSTEM_OVERLAY
ventana no recibirá ningún evento táctil en la plataforma ICS y, por supuesto, su usoTYPE_SYSTEM_OVERLAY
no es una solución viable para ICS y dispositivos futuros.fuente
Soy uno de los desarrolladores del SDK de Tooleap . También proporcionamos una forma para que los desarrolladores muestren siempre en las ventanas y botones superiores, y hemos lidiado con una situación similar.
Un problema que las respuestas aquí no han abordado es el de los "botones seguros" de Android.
Los botones asegurados tienen la
filterTouchesWhenObscured
propiedad que significa que no pueden interactuar con ellos, si se colocan debajo de una ventana, incluso si esa ventana no recibe ningún toque. Citando la documentación de Android:Un ejemplo de dicho botón es el botón de instalación cuando intenta instalar aplicaciones de terceros. Cualquier aplicación puede mostrar dicho botón si agrega al diseño de vista la siguiente línea:
Si muestra una ventana siempre arriba sobre un "Botón asegurado", todas las partes del botón aseguradas que están cubiertas por una superposición no manejarán ningún toque, incluso si no se puede hacer clic en esa superposición. Por lo tanto, si planea mostrar dicha ventana, debe proporcionar una forma para que el usuario la mueva o la descarte. Y si una parte de su superposición es transparente, tenga en cuenta que su usuario podría estar confundido por qué un botón determinado en la aplicación subyacente no funciona para él de repente.
fuente
TRABAJAR SIEMPRE EN EL BOTÓN DE IMAGEN SUPERIOR
en primer lugar lo siento por mi inglés
Edito sus códigos y hago que el botón de imagen de trabajo que escucha su evento táctil no le dé control táctil a sus elementos de fondo.
También le da a los oyentes toques de otros elementos
alineaciones de botones son inferior e izquierda
puede cambiar las alineaciones pero necesita cambiar los cordinats en el evento táctil en el elemento if
fuente
En realidad, puede probar WindowManager.LayoutParams.TYPE_SYSTEM_ERROR en lugar de TYPE_SYSTEM_OVERLAY. Puede sonar como un truco, pero le permite mostrar la vista encima de todo y aún así obtener eventos táctiles.
fuente
TYPE_SYSTEM_OVERLAY Esta constante ha quedado en desuso desde el nivel 26 de API. Utilice TYPE_APPLICATION_OVERLAY en su lugar. o ** para usuarios de Android 8 y superiores
fuente
Prueba esto. Funciona bien en ICS. Si desea detener el servicio, simplemente haga clic en la notificación generada en la barra de estado.
ACTUALIZAR
Muestra aquí
Para crear una vista de superposición, al configurar los LayoutParams NO configure el tipo en TYPE_SYSTEM_OVERLAY.
fuente
Aquí hay una solución simple, todo lo que necesita es inflar el diseño XML al igual que lo hace en los adaptadores de lista, solo haga un diseño XML para inflarlo. Aquí hay un código que todo lo que necesitas.
fuente
Encontré una biblioteca que hace exactamente eso: https://github.com/recruit-lifestyle/FloatingView
Hay un proyecto de muestra en la carpeta raíz. Lo ejecuté y funciona según sea necesario. Se puede hacer clic en el fondo, incluso si se trata de otra aplicación.
fuente
Utiliza el permiso "android.permission.SYSTEM_ALERT_WINDOW" tutorial completo en este enlace: http://androidsrc.net/facebook-chat-like-floating-chat-heads/
fuente
Bueno, prueba mi código, al menos te da una cadena como superposición, puedes reemplazarlo con un botón o una imagen. No creerás que esta es mi primera aplicación para Android LOL. De todos modos, si tiene más experiencia con las aplicaciones de Android que yo, intente
fuente
Si alguien sigue leyendo este hilo y no puede hacerlo funcionar, lamento decirle que esta forma de interceptar el evento de movimiento se considera un error y una corrección en Android> = 4.2.
El evento de movimiento que interceptó, aunque tiene acción como ACTION_OUTSIDE, devuelve 0 en getX y getY. Esto significa que no puede ver toda la posición de movimiento en la pantalla, ni puede hacer nada. Sé que el documento dijo que obtendrá x e y, pero la verdad es que NO. Parece que esto es para bloquear el registrador de claves.
Si alguien tiene una solución, deje su comentario.
ref: ¿Por qué ACTION_OUTSIDE devuelve 0 cada vez en KitKat 4.4.2?
https://code.google.com/p/android/issues/detail?id=72746
fuente
Al utilizar el servicio puede lograr esto:
fuente
La respuesta de @Sarwar Erfan ya no funciona ya que Android no permite agregar vistas con WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY a la ventana para que ya no se pueda tocar, ni siquiera con WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH.
Encontré solución a este problema. Puedes verlo en la siguiente pregunta
Al agregar la vista a la ventana con WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, no se obtiene un evento táctil
fuente
Esta es una vieja pregunta, pero recientemente Android tiene soporte para Bubbles. Pronto se lanzarán burbujas, pero actualmente los desarrolladores pueden comenzar a usarlas y están diseñadas para ser una alternativa al uso
SYSTEM_ALERT_WINDOW
. Aplicaciones como (Facebook Messenger y MusiXMatch usan el mismo concepto).Las burbujas se crean a través de la API de notificaciones, envía su notificación de forma normal. Si desea que burbujee, debe adjuntarle algunos datos adicionales. Para obtener más información sobre Bubbles, puede ir a la Guía oficial para desarrolladores de Android en Bubbles .
fuente