Kyl*_*ney 5 c# layout scroll scrollbar unity-game-engine
我有一个垂直滚动视图,我想动态添加内容。为此,我已将Content Size Fitter组件和Vertical Layout Group组件附加到Content游戏对象,以便每当我实例化新的游戏对象作为其子对象时,其Rect变换都会自动增长。如果滚动条已经在底部,那么在底部添加新对象后,我想将滚动条保持在底部。所以我这样做是这样的:
if ( scrollRect.verticalNormalizedPosition == 0 )
{
isAtBottom = true ;
}
ScrollViewItem item = Instantiate( scrollViewItem, scrollRect.content ) ;
if ( isAtBottom )
{
scrollRect.verticalNormalizedPosition = 0 ;
}
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为新实例化的滚动视图项在我设置verticalNormalizedPosition为零时尚未增加Rect变换的大小。因此,当Rect Transform最终更新时,滚动到底部为时已晚。
举例来说,假设我的内容高度为400像素,滚动条一直位于底部。现在,我向其添加一个100像素高的对象。然后,我将滚动条发送到底部,但它仍然认为内容为400像素高。然后,内容大小将更新为500像素,但是滚动条向下缩小了400像素,因此它仅下降了80%,而不是100%。
有两种方法可以解决此问题。我想要一种方法来立即强制更新Content Size Fitter,或者作为一种事件来响应Content Size Fitter更新。
通过研究和实验,我将这些行按确切的顺序排列几乎成功了:
Canvas.ForceUpdateCanvases();
scrollRect.content.GetComponent<VerticalLayoutGroup>().CalculateLayoutInputVertical() ;
scrollRect.content.GetComponent<ContentSizeFitter>().SetLayoutVertical() ;
scrollRect.verticalNormalizedPosition = 0 ;
Run Code Online (Sandbox Code Playgroud)
但是,它并没有完全滚动到底部。始终相距约20像素。所以我想知道是否还有一些我不希望发生的布局操作。也许是填充之类的东西。
没有Canvas.ForceUpdateCanvases 和疯狂迭代的正确方法。已确认在 Unity 中工作 2018.3.12
// Assumes
ScrollRect m_ScrollRect;
Run Code Online (Sandbox Code Playgroud)
在您更新 ScrollRect 内容并想要备份滚动条位置的地方
float backup = m_ScrollRect.verticalNormalizedPosition;
/* Content changed here */
StartCoroutine( ApplyScrollPosition( m_ScrollRect, backup ) );
Run Code Online (Sandbox Code Playgroud)
要应用新的滚动位置而不抖动,它需要在帧结束时,我们使用 Coroutine 等待该时间,然后使用LayoutRebuilder.ForceRebuildLayoutImmediate仅在该部分触发布局重建。
IEnumerator ApplyScrollPosition( ScrollRect sr, float verticalPos )
{
yield return new WaitForEndOfFrame( );
sr.verticalNormalizedPosition = verticalPos;
LayoutRebuilder.ForceRebuildLayoutImmediate( (RectTransform)sr.transform );
}
Run Code Online (Sandbox Code Playgroud)
归功于:
小智 8
注册只是为了回答这个问题;我找到了一个更快的方法:
只需设置内容对象的锚点和枢轴(也可以有内容调整器组件),它就会从底部开始,然后向上滚动。
我的设置是:
希望这对那些不想做自定义事情并且需要代码的人有所帮助,干杯
好吧,我相信我已经解决了。在大多数情况下,这Canvas.ForceUpdateCanvases();是设置verticalNormalizedPosition为零之前需要做的所有事情。但就我而言,我要添加到内容本身的项目还具有“垂直布局组”组件和“内容大小适合者”组件。所以我必须按以下顺序执行这些步骤:
Canvas.ForceUpdateCanvases();
item.GetComponent<VerticalLayoutGroup>().CalculateLayoutInputVertical() ;
item.GetComponent<ContentSizeFitter>().SetLayoutVertical() ;
scrollRect.content.GetComponent<VerticalLayoutGroup>().CalculateLayoutInputVertical() ;
scrollRect.content.GetComponent<ContentSizeFitter>().SetLayoutVertical() ;
scrollRect.verticalNormalizedPosition = 0 ;
Run Code Online (Sandbox Code Playgroud)
遗憾的是,关于这些方法的文档很少。