【UGUI】优化ScrollView,方便的内容展示与无限下拉

本文介绍如何使用Unity的UGUI实现自动布局,包括根据文字数量调整Text控件尺寸及ScrollView内容区域大小。通过实例代码展示了如何创建自适应的Text和Image控件,以及如何动态调整ScrollView的content尺寸。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UGUI自动布局(根据文字数量自适应Text控件尺寸,根据内容自适应ScrollView的content尺寸)

首先设置一下固定的UI部分内容

 

将内置ScrollView设置成如上这个样子

 

我们来看content

挂载如下组件,可使content下内容自动垂直布局,这里我们设置不让组件控制子物体的尺寸,对于Force Expand也取消勾选Heigh

这样我们可以自定义控制content下子物体的尺寸,不至于被控件强制缩放,

首先我们创建脚本,挂在上图的ZYKPanel上,我们创建一个List来存储当前需要显示的内容(这个List的作用很重要),然后使脚本持有content的Recttransform组件

 

//store all item in content for calcuate the size of content(just height)

public List<RectTransform> allContentItem = new List<RectTransform> { };

//just content

private RectTransform _content;

public RectTransform content {

get {

if (_content == null) {

_content = transform.Find("Scroll View/Viewport/Content").GetComponent<RectTransform>();

}

return _content;

}

}

 

下面就来用代码创建一些text和image控件

对于文字控件,

它的宽度我们要自己计算,这里我们设置它的宽度为content宽度的90%,在下方代码中可以找到这句

接下来提供设置控件文字内容的参数即可

*对于文本控件,经过ContentSizeFitter规范后,无法从sizeDelta中获取真正的控件高度,虽然在Inspector中显示的是正确值,但程序获取的【sizeDelta.y】会始终是100,这回导致当文字数量较多时,content的高度不够,解决办法是使用text控件提供的preferredHeight来获取正确的控件高度,

相关博客:http://blog.youkuaiyun.com/qq_28768929/article/details/51799828

 

Text CreateFitterText(string str) {

//set parent just -.-

//GameObject go = Instantiate(new GameObject("ZYKtext"), content);

GameObject go = new GameObject("ZYKtext");

go.transform.SetParent(content);

Text text = go.AddComponent<Text>();

//add fitter on text

ContentSizeFitter fitter = go.AddComponent<ContentSizeFitter>();

fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;

text.font = AllSprite.instance.WebglFont;

text.fontSize = 25;

//set text

text.text = str;

//获取顺序

RectTransform textRect = go.GetComponent<RectTransform>();

textRect.sizeDelta = new Vector2(content.sizeDelta.x * 0.9f, textRect.sizeDelta.y);

//add self 2 contorllist

textRect.sizeDelta = new Vector2(textRect.sizeDelta.x, text.preferredHeight);

allContentItem.Add(textRect);

textRect.localScale = Vector3.one;

return text;

}

 

对于图片Image控件,我们不需要其他多余组件,只需要计算一下它的尺寸,并保证它不会大过content即可(太大的就按比例缩放下)

同样使用参数,获得需要显示的sprite

获取sprite并赋值给image,设置Image为NativeSize,这时我们计算content的宽度,并和我们content的宽度(或宽度某比例)做对比,若大于这个值,我们就把Image缩放为适合的尺寸

 

Image CreateFitterImage(Sprite sprite) {

//then set parent must...

GameObject go = new GameObject("FitterImage");

go.transform.SetParent(content);

Image image = go.AddComponent<Image>();

//

image.sprite = sprite;

image.SetNativeSize();

//get Recttransform for calculate Maxsize of Image

RectTransform imgRect = go.GetComponent<RectTransform>();

float imageX = imgRect.sizeDelta.x;//got the length of native image

float contentX = content.sizeDelta.x * 0.8f;//got the length of content

if (imageX>contentX) {//if thg image is too big

float K = contentX / imageX;//got zoom parameter

imgRect.sizeDelta = imgRect.sizeDelta * K;//then reset to our MAX size

}

//add the right size of image 2 controlList

allContentItem.Add(imgRect);

 

return GetComponent<Image>();

}

 

当我们使用上面两个方法,创建了一堆控件出来后,我们就需要重新计算下content的Height,来适应子物体的内容

遍历allContentItem来获取每个控件的height并计算加和,(因为我们设置每个控件之间的Spacing为20,忘了的可以翻翻上面的图,因此在最后要加上这个spacing的高度)

最后在我们真的把这个值设置给content前,先判断下它是不是小于content的高度(或者说它父控件的高度),如果它过小(即内容很少,一个屏幕可以显示,没必要下拉),就将content设置为与父控件等高即可

 

void ResizeContentHeight() {

//

float height = 0;

float parentHeight = content.parent.parent.GetComponent<RectTransform>().sizeDelta.y;

foreach (RectTransform rect in allContentItem) {

Vector2 tempVec2 = rect.sizeDelta;

height += tempVec2.y;

//Debug.Log("current Height=" + height + " currentRect=" + rect.name + " currentRectDelta=" + rect.sizeDelta);

}

//Debug.Log("======height=" + height);

//just multiply all the count of space , although more one, it seems better i thought.

height += allContentItem.Count * 20;

//Debug.Log("======height+spcaing=" + height);

//if the size of childs is not bigger than content'parent .That means the childs is not beyong the screen,

if (height < parentHeight) {

content.sizeDelta = new Vector2(content.sizeDelta.x, parentHeight);

}

else {

content.sizeDelta = new Vector2(content.sizeDelta.x, height);

}

}

 

同时我们要提供一个清空content子控件的方法,

void ClearContentChild() {

int count = content.childCount;

int temp = count;

for(int i = 0; i < count; i++) {

Destroy(content.GetChild(temp-1).gameObject);

temp--;

}

}

 

最后就是调用这些方法,把内容显示在屏幕上了

我们这里传入的参数是一个object类型,这里是一个使用小技巧,在其他位置,专门用来做存储,创建object数组来存储不同页面,在这个数组内,封装进文字和sprite,在使用时,通过如下方法调用

也就是,我们在某个位置想要刷新内容时,调用这个方法,并将预先编好的数组,穿进去即可

 

public void RefreshZYKPanel(List<object> zykItem) {

//first clear our contentItemList

allContentItem.Clear();

//clear old childs under content

ClearContentChild();

//create

foreach (var item in zykItem) {

//是否是文字

if (item.GetType() == typeof(string)) {

CreateFitterText(item as string);

}

else {

CreateFitterImage(item as Sprite);

}

}

//

ResizeContentHeight();

}

 

最后看下效果

 

 

Super ScrollView for UGUI提供基于UGUI ScrollRect的可轻松定制的ScrollView。它是一组C#脚本,可帮助您创建所需的ScrollView。这是非常强大的和高度优化的性能。 文件 Android演示应用程序 演示: - 聊天消息列表演示 - 水平画廊演示 - 垂直画廊演示 - GridView演示 - PageVew演示 - TreeVew演示 - 稠粘头演示的TreeView - 旋转日期选择器 - 更改项目高度演示 - 下拉刷新演示 - 拉起来加载更多的演示 - 点击加载更多演示 - 选择并删除演示 - GridView删除项目演示 - 顶部到底部的演示 - 自下而上的演示 - 从左到右的演示 - 右侧演示 - 响应GridView演示 - TreeViewWithChildrenIndent演示 特征: - ListView和GridView和TreeView - 无限的项目 - 项目在不同的大小(高度/宽度) - 具有不同预制的物品 - 在初始时间大小未知的项目 - 垂直滚动视图(从上到下,从下到上) - 水平滚动视图(从左到右,从右到左) - 项目填充 - 滚动到指定的项目 - 滚动到具有偏移量的项目 - 项目计数在运行时更改 - 项目大小(高度/宽度)在运行时更改 - 物品捕捉到视口中的任何位置 - 项目循环,如微调 - 添加/删除项目 - 全部删除/删除所有项目 - 刷新并重新加载项目 - 使用池缓存项目,不要在运行时销毁项目 - 有效回收物品 - 平台无关 - UGUI支持 - 支持Unity平台(IOS / Android / Mac / PC / Console / Winphone / WebGL ...)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值