This is the 30th day of my participation in the August Text Challenge.More challenges in August

An overview of the

When we use the untiy UGUI SCrollView, often have this problem, is when the SCrollView long, want to find one of these Item is very difficult, often need to find a long time, very trouble, today is mainly explain the SCrollView positioning function, According to the index of the Item, let the slider directly display the corresponding position of the Item.

Thought analysis

If you want to position the slider, the first thing you need to know is what parameter ScrollView is controlled by, and if you look at the API, you can see, He is controlled by VerticalNormalizedPosition and HorizontalNormalizedPosition its longitudinal and lateral sliding, so we and they range between 0 and 1, what we need through the location of the item, VerticalNormalizedPosition indirectly calculated and HorizontalNormalizedPosition value, thus to control the ScrollView positioning

Function implementation

Scenario building

1. Create a ScrollView and create multiple items within the Content. Then add groups VerticalLayoutGroup (auto-arrange components, added according to arrangement requirements) and ContentSizeFitter (auto-set width) to the Content. The final interface is as follows:

2. Add the button corresponding to the number of items, so that it can be clicked for positioning. Here we use GridLayoutGroup (also automatic patting column), faster automatic patting column, no need to place one by one

Code implementation

Let’s take a look at the code, first to rule out a few unlocatable cases, and then we’ll move on.

1, ScrollView has no Content or Viewport, which indicates that the ScrollView is empty. In this case, we can only exit the ScrollView

If (scrollRect. Viewport = = null | | scrollRect. The content = = null) {Debug. LogError (" ScrollView content or viewport is empty "); return inverse ? 1:0; }Copy the code

If there is no object under Content or if it is not a RectTransform, this will check if there is an object under ScrollView, and if the ScrollView is valid in canvas. If there is no object under Content, this will not work

var childTrans = scrollRect.content.GetChild(0) as RectTransform; If (childTrans == null) {debug. LogError(" No object under Content or not RectTransform"); return inverse ? 1:0; }Copy the code

3. Only one vertical and horizontal can be checked. There are some problems with the calculation of the two checked at the same time, which may be supplemented after modification

Horizontal && ScrollRect. horizontal) {debug. LogError(" Horizontal and vertical can only be checked "); return inverse ? 1:0; }Copy the code

4. Failed to obtain VerticalLayoutGroup or HorizontalLayoutGroup. This is mainly because I used the beat column combination

VerticalLayoutGroup group = scrollRect.content.GetComponent<VerticalLayoutGroup>(); If (group == null) {debug. LogError(" Failed to get VerticalLayoutGroup "); return inverse ? 1:0; }Copy the code
HorizontalLayoutGroup group = scrollRect.content.gameObject.GetComponent<HorizontalLayoutGroup>(); If (group == null) {debug. LogError(" Get HorizontalLayoutGroup failed "); return inverse ? 1:0; }Copy the code

5. The next step is to calculate the position and obtain the corresponding value. Horizontal or Vertical: Horizontal: rect.Width: Vertical: rect.Hight There is another distinguishing problem here, which is the inverse problem of the slider, that is, from top to bottom, from right to left to reverse, need to consider whether to use 1- to calculate the value. Second, get a couple of values the width or height of each item, plus the value is the interval set by the component, which is to be added

float elementLength = childrenRect.height + group.spacing;
Copy the code

The difference between Content. rect and viewPort. rect

var diff = contentRect.height - viewportRect.height;
Copy the code

After calculating all the values, we start to calculate the values, where pixelOffset is the pixelOffset, downward to the right is positive, optional, as required

if (inverse)
	return Mathf.Clamp01(1 - (currentChildIndex * elementLength + pixelOffset) / diff);
else
	return Mathf.Clamp01((currentChildIndex * elementLength - pixelOffset) / diff);
Copy the code

Results show

You can also imagine, for example, adding highlighting to the positioned Item, which may be supplemented later

Source code sharing

This is the project project file GitHub download address: click here to jump to download

Write in the last

All the shared content is the author used in the daily development process of a variety of small function points, sharing is also a way to review, if there is a bad place to write, please give more advice. Welcome to learn from each other and make progress. This piece article is written here first, hope to be able to help you