Red de conocimiento informático - Problemas con los teléfonos móviles - Serie Window: la vida pasada y presente de PopupWindow

Serie Window: la vida pasada y presente de PopupWindow

El blog anterior analizó el código fuente de Toast, y la ventana mencionada en él era inevitablemente menor que la PopupWindow analizada en este blog. Pensé que era el mismo proceso: crear la ventana y configurar la Vista. DecorView y agregue Ventana, listo.... Sin embargo, descubrí que PopupWindow no está implementado de esta manera.

Este blog analizará varios puntos:

La PopupWindow que utilizamos habitualmente implica los siguientes tres métodos principales:

Por lo tanto, primero mire el constructor

Si ContentView está configurado en el constructor, obtendrá directamente el objeto Context y WindowManager, llamará al método setContentView, establecerá el ancho y el alto y prestará atención a la variable Focusable. variable en el efecto PopupWindow más tarde.

Si llamamos al constructor más básico, normalmente llamamos al método setContentView para configurar el diseño, así que veamos ese método aquí.

Como puedes ver, es básicamente el mismo constructor que acabamos de ver, guardando la variable ContentView y obteniendo los objetos Context y WindowManger.

Puedes ver que los dos pasos anteriores son básicamente trabajo de preparación y luego observar el método de visualización principal showAsDropDown.

Puedes ver que este método en realidad aprovecha la sobrecarga e implementa muchos métodos, que terminan en el último método.

El contenido anterior está dividido en cuatro partes y he escrito notas en cada parte, por lo que las veremos por separado a continuación.

Como puede ver, este método establece principalmente los parámetros que pasamos, pero lo que debe tenerse en cuenta aquí es que Google utiliza referencias débiles aquí. Creo que esto es relativamente raro. Código fuente de la capa FrameWork que conozco, es raro ver a Google usando referencias débiles aquí, aquí se usan referencias débiles y aquí se usan referencias débiles. , donde se utilizan referencias débiles para guardar el diseño entrante y el diseño principal de nivel superior.

createPopupLayoutParams se utiliza para crear un LayoutParam. Preste atención a la variable token aquí. Los lectores que hayan leído la publicación anterior del blog deben recordar que el componente Toast también necesita una variable token. .getApplicationWindowToken() Mire el token, es el token del diseño principal. Dedicaremos una publicación de blog a discutir esta bandera y cómo afecta los tipos de ventanas.

Se puede decir que este método es el método principal de la ventana emergente. Primero, podemos ver que la variable mBackgroud está vacía y, si se establece el fondo, se ejecutará el método createBackgroundView.

Aquí podemos ver que se construye un parámetro de diseño con el mismo ancho y alto y se crea un PopupBackgroundView usando el método addView que envuelve nuestro ContentView.

El PopupBackgroundView aquí es en realidad un FrameLayout, que solo se usa para configurar el fondo.

A continuación, ejecute el método createDecorView.

Como puedes ver, este es básicamente el mismo método que ahora, entonces, ¿por qué necesitamos encapsularlo nuevamente esta vez? Echemos un vistazo a PopupDecorView

Hay mucho aquí.

En primer lugar, este sigue siendo un diseño heredado de FrameLayout. La única diferencia es que sobrecarga dos métodos clave: despachoKeyEvent y onTouchEvent, por lo que debemos saber que los eventos de teclado y táctiles se manejan especialmente aquí.

Esta es la razón por la que la ventana emergente desaparece cuando haces clic fuera de la Vista, que es como se manejan los eventos táctiles.

También debemos prestar atención a una cosa aquí.

Puedes ver que el método de despachoTouchEvent se anula aquí. Las personas que están familiarizadas con el proceso de distribución de eventos de Android deben saber que es así. en la parte superior de la jerarquía de distribución de eventos. El concepto mTouchInterceptor es en realidad un interceptor, lo que significa que para PopupWindow podemos personalizar el manejo de eventos.

Una vez completados todos estos preparativos, queda un último método.

Finalmente, veremos el método de visualización principal y podemos ver que la ventana emergente se agrega a través del método addView de WindowManger. Puede ver que PopupWindow en realidad no recrea una nueva ventana, sino que la agrega a la ventana actual usando WindowManger.addView. Así es como funciona PopupWindow.

Cuando aprendemos por primera vez a utilizar PopupWindow, a menudo vemos comentarios como este.

A través del análisis del código fuente anterior, no encontramos que BackgroundDrawable tenga un impacto tan grande. Simplemente envuelve la impresión de Ver fondo. Aquí tenemos que hablar sobre la diferencia de versión de PopupWindow. está basado en Android -28, podemos saber por el código fuente que este blog está basado en Android-28, podemos saber por el código fuente que backgrounddrawable no tendrá tal impacto. Pero echemos un vistazo al código fuente de Android 4.2.2.

Puedes ver que hay una diferencia en el método preparePopup. Si configuras mBackground aquí, se guardará usando PopupViewContainer.

Como puedes ver, esto manejará los eventos de teclado y táctiles directamente, lo que significa que si no configuramos el fondo, no podremos hacer clic fuera de la ventana emergente para hacerla desaparecer. versiones inferiores, aunque luego solucionamos el problema, Google aún dejó un gran vacío. Google también dejó un gran vacío, para ajustar el fondo en una visualización consistente, no tienes más remedio que ajustarlo dos veces en versiones superiores, y eso es mucho trabajo.

Este blog analiza principalmente el principio de implementación de PopupWindow. En general, PopupWindow tiene principalmente los siguientes pasos: