Unity UGUI中使用scroll rect和content size fitter问题

  • Post author:
  • Post category:其他


最近成为了底层拼图仔,对一些Unity中UGUI遇到的问题进行一下总结。 以下内容均在Unity2017.4中实现



一. 搭建一个xx列表

许多UI中都可能需要实现可上下拖拽的列表功能,比如手机QQ中的聊天列表以及浏览器的上下拖拽显示内容列表。脑中有了大致的实现效果,便可以搭建起来了。

所以我们先初步要实现一个列表的效果就是:

假设列表中每个信息都是一个item,每接收到一个item,则会在原有列表中的item下方生成(竖直排列),并且我们可以通过拖拽(鼠标)来上下翻阅,类似于如下图所示

UGUI中提供了一个很方便的方法可以让我们快速搭建。在场景中右键找到”UI”->”Scroll View”即可,这个时候我们就会在场景中看到这样的结构

主要是三层结构: ScrollView -> Viewport -> Content

我们来具体看一下设置,点击场景中的

Scroll View

,看其属性面板



主要用到的组件就是

Scroll Rect

  • 其中Content和Viewport已经帮我们自动配置好了,相对应的是场景中的

    Viewport



    Content

  • 我们这里要的是竖直列表效果,对其水平方向的拖拽要禁用掉,所以只勾选了

    Vertical

  • Movement Type

    可以设置拖拽时的移动类型

    • 默认为我们设置成Elastic弹性,当我们列表中内容过多超出

      Content

      的大小范围后,拖拽至超出范围的地方将会自动帮我们弹回Content中。 下面的Elasticity是一个弹性系数,可以理解为数值越小弹性越大
    • Unrestricted则表示可以无限制的超出Content去拖拽,这肯定不是我们想要的(翻到空白处)
    • Clamped则表示我们限定在Content中,意思就是无法拖拽了,这也不是我们想要的

  • Inertia

    可以设置 我们拖拽松开时的惯性

  • Viewport

    选择了我们所能在列表中看到的范围,其对应的物体会待会讲解

  • Horizontal Scrollbar



    Vertical Scrollbar

    用来设置滚动条的,需要的话只需要创建一个scrollbar添加至这里即可,我们这里用不到所以设置为空

再看一下其子物体

Viewport

下组件



这个Viewport帮我们限制了列表的具体能看见的范围大小,其中的

Mask

组件帮我们遮罩掉超出Viewport范围的Content,学过PS的应该知道这个和蒙版是差不多的意思

再看一下Viewport下子物体

Content

的组件



这边用到了一个竖直布局组件 我们生成的item都应该为Content的子物体,这个组件会对每个子物体进行竖直排列,里面比较有关的的一个设置就是

Spacing

,表示间距

看到这里是不是以为大功告成了呢…我们试着把新建的Item加入至Content中如下图所示



启动一下,会发现一个问题,也是一开始遇到的第一个坑:

  • 当我们下拉至超出Viewport范围外的地方时,鼠标松开后,并不会停在当前画面,而是弹回至初始的画面

一开始想解决思路的时候,最粗暴的方法就是每次增加一个item,对应的Content中

Rect Transform



Height

属性也相应增大一定比例,当然脚本写起来其实也非常简单的了。

之后去网上查阅了一些方法之后,发现一个比较简答的方法,那就是添加

Content Size Fitter

组件!

我们为Content添加上这个组件,并在Vertical Fit中选择

Preferred Size

,会自动根据子物体的范围为我们规划所需要的大小,如下图

当我们再次运行时,就不会有之前的问题了! 想翻到哪里就翻到哪里,不会拖了一会就弹回起点



二. 动态增加Text长度

我们经常在创建出Text后,会为Text设置一个较长的宽度,保证在输入Text文本时,文字能在宽度范围内显示出来

这个时候

Content Size Fitter

这个组件又出马了! 我们为带有Text组件的物体再添加

Content Size Fitter




这个时候我们添加文本内容时,就无需担心是否超出宽度范围,当然如果你是跟着我一起做到这步,你会发现一个小问题:

当我们修改此文本内容的时候,其动态增加的宽度是从两边同时出发的,这肯定是跟我们的需求是违背的。

我们要的效果应该是文本添加时,只从一个方向(假定往右)进行宽度增加。解决这个方法也非常简单,只需要将我们这个物体的

pivot

坐标设置为0, 0即可



三. Text后跟随一个image

最近做到的项目需求有一个问题是, 聊天时的未读消息数(由一张背景图和一个text构成)要紧跟在玩家名字后面一点的距离。

由于玩家取名的长度不同,我们不能将未读消息数放置在固定位置(但是说实话如果像手机QQ里面那样的固定的未读消息位置会更舒服点…)大致要呈现的效果如下图



一开始想的思路是在给定玩家名字后,由于我们为其添加了

Content Size Fitter

,所以其扩增的width我们是能求出的,相应的未读消息数这个物体也对应偏移width的距离,思路理清了再去实现其实就不难了,这里稍微说一下代码中用到的属性



我们获取到Text的Rect Transform组件,如果要访问其PosX PosY PosZ 则只需要用

var nameRect = GetComponent<RectTransform>();
var posX = nameRect.anchoredPostion.x;
var posY = nameRect.anchoredPostion.y;
var posZ = nameRect.anchoredPostion.z;

如果要访问Width和Height 则使用

var width = nameRect.sizeDelta.x;
var height = nameRect.sizeDelta.y;

当然这里的sizeDelta是保证四个锚点anchors都在一点上时可以代表宽高,否则表示为到锚点的距离。也可以使用

nameRect.rect.size来获取宽高,不受锚点影响

代码编程的思路应该是没问题的,但是有没有更简单的方法呢? 经过我查询了网上的资料,学到了这个技巧

首先将name的RectTransform的锚点设置成如下图 左中对齐



再将未读消息数这个物体的RectTransform的锚点设置成如下图 右中对齐



最后将未读消息数(icon)作为其子物体即可,结构如下图



这样子我们的Text长度不同时 icon会跟随我们text的宽度变化而变化



四. 总结

如何搭好一个UI也是一门技术活…



版权声明:本文为wangjianxin97原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。