fondo
View's Animation y Gone ya son muy familiares para todos. La animación es responsable de agregar animación a la Vista y Gone puede ocultar la Vista.
Entonces, cuando la animación de una Vista no finaliza, ¿establecer Gone finalizará la animación? ¿Se ocultará la vista?
Este es un fenómeno que encontré durante el proceso de desarrollo, simplemente restaure la escena:
Primero personalice LoadingView, la implementación es muy simple. Después de configurar el fondo, cuando esté visible, inicie una animación que gire sobre sí misma:
public class LoadingView extends View {
private RotateAnimation animation;
private void init(){
animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
animation.setRepeatMode(Animation.RESTART);
animation.setInterpolator(new LinearInterpolator());
animation.setRepeatCount(-1);
animation.setDuration(1250);
setBackgroundResource(R.drawable.loading_frame);
}
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if(visibility == View.VISIBLE){
if (!animation.hasStarted()||animation.hasEnded()) {
startAnimation(animation);
}
}
}
}
Luego use LoadingView en el archivo de diseño y use FrameLayout como la capa más externa:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LoadingView
android:id="@+id/progress"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center"
/>
</FrameLayout>
Finalmente llame a Actividad activada:
mProgressView.setVisibility(GONE)
Como resultado, la carga sigue dando vueltas por ahí.
Verifique las propiedades de LoadingView, la visibilidad desapareció:
El ancho y el alto también tienen valores.
Parece ser un problema, pero se esconden al menos dos detalles detrás:
1. Ver animación y dibujo
2. Procesamiento finalizado en el diseño principal
Ver animación y dibujo.
En los comentarios oficiales de View, el dibujo se divide en los siguientes pasos:
- dibujar fondo
- Guarde las capas del lienzo como preparación para los degradados, si es necesario
- dibujar el contenido de la vista
- dibujar subvistas
- Dibuje bordes degradados y restaure capas si es necesario
- Dibujar decoraciones (por ejemplo, barras de desplazamiento)
El cuarto paso es dibujar la subvista. Existe un fragmento de código en ViewGroup:
protected void dispatchDraw(Canvas canvas) {
for (int i = 0; i < childrenCount; i++) {
...
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
more |= drawChild(canvas, child, drawingTime);
}
}
}
El código muestra que si la subvista es visible o si hay animación, se llamará a la lógica de dibujo de la subvista .
Por lo tanto, bajo la premisa de la animación, es imposible ocultar la Vista usando gone .
Manejo de desaparecidos en el diseño principal
La vista está oculta, generalmente pensamos que el ancho y el alto de esta Vista son ambos 0.
De hecho, durante el proceso de medición del diseño, se omite la subvista cuya propiedad de visibilidad ha desaparecido.
# FrameLayout
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (mMeasureAllChildren || child.getVisibility() != GONE) {
if (measureMatchParentChildren) {
if (lp.width == LayoutParams.MATCH_PARENT ||
lp.height == LayoutParams.MATCH_PARENT) {
mMatchParentChildren.add(child);
}
}
}
}
}
# LinearLayout
void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
...
for (int i = 0; i < count; ++i) {
...
if (child.getVisibility() == GONE) {
i += getChildrenSkipCount(child, i);
continue;
}
...
}
}
Por lo tanto, las subvistas cuya propiedad desapareció no se han vuelto a medir y sus tamaños siguen siendo los últimos medidos.
evento táctil
Una vez identificados los problemas anteriores, surgió otra pregunta:
La vista secundaria que está configurada para realizar una animación al mismo tiempo es visible, entonces, ¿puede recibir eventos táctiles?
Después de reproducir el registro, se descubre que es posible.
La razón de esto se puede encontrar en el código fuente.
El evento Touch de la Vista secundaria lo pasa el control principal. En el método de distribución de eventos de ViewGroup, existe el siguiente código:
#ViewGroup
public boolean dispatchTouchEvent(MotionEvent ev) {
...
if (!child.canReceivePointerEvents()
|| !isTransformedTouchPointInView(x, y, child, null)) {
ev.setTargetAccessibilityFocus(false);
continue;
}
...
}
Si child.canReceivePointerEvents()
se devuelve false
, se omite la distribución.
canReceivePointerEvents
El código es el siguiente:
#View
protected boolean canReceivePointerEvents() {
return (mViewFlags & VISIBILITY_MASK) == VISIBLE || getAnimation() != null;
}
Aunque está configurado "Desaparecido", se puede recibir el evento Touch porque la animación no está vacía.
otro
Incluso si la Vista está configurada para que desaparezca al principio y el usuario no puede verla, la Vista continuará realizando animaciones y consumiendo el rendimiento del sistema.
Así que tenga cuidado al utilizar animaciones y cancele clearAnimation
las animaciones a tiempo.
Resumir
clearAnimation
Cuando encontré este problema al principio, lo resolvió llamándolo . Pero no puedo entender el motivo y no podré hacerlo la próxima vez que me encuentre con un problema similar. Para comprender el principio, el problema que se puede resolver en un minuto tomó menos de un día y personalmente creo que vale la pena.- Domine el conocimiento de la distribución de eventos de antemano y sea objetivo al analizar los eventos táctiles.
- Familiarizado con Choreographer y el proceso de actualización de la interfaz, podrá comprender rápidamente el proceso de ejecución de la animación.
- La atención se centra en la acumulación, algunos conocimientos pueden no ser útiles en este momento, pero sabrás lo cómodo que es cuando los uses.
Materiales de referencia:
cómo se actualiza la interfaz
Ver el principio de funcionamiento de la animación