Solución:
De acuerdo, creo que lo he descubierto. En la mayoría de los casos, Canvas.ForceUpdateCanvases();
es todo lo que necesita hacer antes de configurar verticalNormalizedPosition
a cero. Pero en mi caso, el elemento que estoy agregando al contenido en sí también tiene un componente de grupo de diseño vertical y un componente de ajuste de tamaño de contenido. Así que debo realizar estos pasos en este orden:
Canvas.ForceUpdateCanvases();
item.GetComponent<VerticalLayoutGroup>().CalculateLayoutInputVertical() ;
item.GetComponent<ContentSizeFitter>().SetLayoutVertical() ;
scrollRect.content.GetComponent<VerticalLayoutGroup>().CalculateLayoutInputVertical() ;
scrollRect.content.GetComponent<ContentSizeFitter>().SetLayoutVertical() ;
scrollRect.verticalNormalizedPosition = 0 ;
Es una pena que haya tan poca documentación sobre estos métodos.
Método adecuado sin Canvas.ForceUpdateCanvases y una iteración loca. Trabajo confirmado en Unity 2018.3.12
// Assumes
ScrollRect m_ScrollRect;
Y en algún lugar donde actualice el contenido de ScrollRect y desee hacer una copia de seguridad de la posición de la barra de desplazamiento
float backup = m_ScrollRect.verticalNormalizedPosition;
/* Content changed here */
StartCoroutine( ApplyScrollPosition( m_ScrollRect, backup ) );
Y para aplicar una nueva posición de desplazamiento sin fluctuación, debe estar al final del cuadro, usamos Coroutine para esperar ese tiempo y luego usamos LayoutRebuilder.ForceRebuildLayoutImmediate para activar la reconstrucción del diseño solo en esa parte.
IEnumerator ApplyScrollPosition( ScrollRect sr, float verticalPos )
{
yield return new WaitForEndOfFrame( );
sr.verticalNormalizedPosition = verticalPos;
LayoutRebuilder.ForceRebuildLayoutImmediate( (RectTransform)sr.transform );
}
Crédito a:
- https://ancientcoder.blog/2019/01/23/force-unity-to-scroll-to-the-bottom-of-a-scroll-rect/
- https://forum.unity.com/threads/scroll-rect-with-dynamic-content-reset-position-properly.518386/