studio personalizado example custom blocker android popup

android - personalizado - llamar a ShowAtLocation de popupwindow está bloqueando la aplicación



pop up android studio (3)

Tengo una clase que se extiende desde una View y estoy tratando de mostrar una popupWindow usando este código

public class dbView extends View implements View.OnTouchListener { private void showDialog(String msg) { LayoutInflater layoutInflater; View dialogContent; final PopupWindow popupWindow; layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); dialogContent = layoutInflater.inflate(R.layout.pop_up_dialog, null); popupWindow = new PopupWindow( dialogContent, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.showAtLocation(this, Gravity.CENTER, 10, 10); } }

Mi aplicación se bloquea al intentar ejecutar esa última línea. El mensaje de la excepción es

No se puede crear el controlador dentro de la secuencia que no ha llamado a Looper.prepare ()

He buscado respuestas relacionadas con ese mensaje y todas ellas implican que la ventana emergente se creó en un hilo separado y que debería usar runOnUIThread pero si estoy dentro de una vista, ¿necesito hacerlo? ¿Cuál puede ser la causa de este problema?


Supongo que puede deberse a que estás tratando de interferir con tu UI a partir de un hilo no original (que creó la UI). Su clase de vista personalizada no tiene acceso para cambiar la interfaz de usuario, así que creo que la mejor manera de hacerlo es llamar a runOnUIThread() . Aunque he oído que usar runOnUIThread puede no ser la mejor opción, pero me parece que esto será exactamente lo que necesita en su caso.

Por lo general, para que esto funcione, hago una clase especial que amplía la Aplicación (en mi caso es ContextGetter) e implemento un método como este:

public class ContextGetter extends Application { private static Context context; public void onCreate(){ super.onCreate(); context = getApplicationContext(); } public static Context getAppContext() { return context; } }

Me ayuda a obtener el contexto de la aplicación desde cualquier lugar. También debería agregarlo a su manifiesto de esta manera:

<application android:name=".ContextGetter" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >

e incluye todas tus actividades dentro de esta etiqueta.

Cuando tienes tu contexto, puedes hacer esto:

((Activity)ContextGetter.getAppContext()).runOnUiThread(new Runnable() { //doSomethingInside });

Puede parecer extraño, pero debe funcionar para usted. Se ve de esta manera porque Activity se deriva de Context . Siempre que lo intentes me gustaría saber si funcionó. Espero que haya ayudado con la pregunta


Depende de dónde llame al showDialog(String msg) , sé que lo estaba llamando desde su clase View, pero eso no significa que esté en el subproceso UI, las llamadas View se procesen en el subproceso UI, pero si hace una Vista llamar en un hilo que tendrá ese error. Sé que el mismo código se resolvió solo, pero si está ejecutando TimerTask o Threads en su clase View, debe verificarlos dos veces. Y también en lugar de runOnUithread puede llamar a la post(runnable); (el mismo Handler mecanismo) en su clase de vista, que se asegurará de que la llamada ejecutable se envíe al hilo principal.

En resumen, ¿dónde lo llamaste en tu clase View


en manifiesto

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

puedes arreglarlo haciendo tu propio a través del administrador de ventanas.

private void showCustomPopupMenu() { windowManager2 = (WindowManager)getSystemService(WINDOW_SERVICE); LayoutInflater layoutInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view=layoutInflater.inflate(R.layout.xxact_copy_popupmenu, null); params=new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); params.gravity=Gravity.CENTER|Gravity.CENTER; params.x=10; params.y=10; windowManager2.addView(view, params); }