Удобный VerticalScrollView

Лучший способ помочь другим, поделиться своими находками.

Удобный VerticalScrollView

Сообщение Glooger 28 янв 2014, 19:36

Небольшой скрипт, больше для новичков. Просто сам недавно понял, что в GUI.Window элементы ниже или выше отображаемого поля можно не отрисовывать, что достаточно круто!

В скриптах примера окна на 5, 500 и 25000 кнопок. + добавил скролинг мышью как на мобилках, но это просто от балды, не уверен, что его код эффективен :)

Синтаксис:
Используется csharp
using System.Collections.Generic;
using UnityEngine;


public class VerticalScrollView0 : MonoBehaviour
{
    public GUISkin optionsSkin;
    public Texture2D textureNull;


    private List<Item> itemList = new List<Item>();
    private List<Item> itemListTemp = new List<Item>();

    public int rowHeight = 80;
    public int rowSpace = 5;
    public Rect windowRect;

    private Vector2 scrollPosition;

    public bool enableView = true;

    private bool withScroll, clearScrollList;

    private int startPos, correctPos;
    private bool slipWork, mouseDown;

    private int testRowQty = 5;
    private int selectedItem = -1;
    private Vector2 screen;

    private void Start()
    {
        windowRect = new Rect(rowSpace, 20, Screen.width / 3 - rowSpace, Screen.height - rowSpace - 20);
        screen = new Vector2(Screen.width, Screen.height);
        for (int i = 0; i < testRowQty; i++) AddItem("item " + i, null);
    }

    private void Update()
    {
        if (enableView)
        {
            if (screen != new Vector2(Screen.width, Screen.height))
            {
                windowRect = new Rect(rowSpace, 20, Screen.width/3 - rowSpace, Screen.height - rowSpace - 20);
                withScroll = itemList.Count*(rowHeight + rowSpace) - rowSpace > windowRect.height;
            }
        }
        if (withScroll)
        {
            if (Input.GetKeyDown(KeyCode.Mouse0) && (enableView ? new Rect(windowRect) { width = windowRect.width - optionsSkin.verticalScrollbar.fixedWidth - optionsSkin.verticalScrollbar.margin.left } : windowRect).Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)))
            {
                startPos = (int)(Screen.height - Input.mousePosition.y);
                mouseDown = true;
                slipWork = true;
            }
            if (slipWork)
            {
                if (Input.GetKeyUp(KeyCode.Mouse0)) mouseDown = false;
                if (mouseDown) correctPos = startPos - (int)(Screen.height - Input.mousePosition.y);

                if (correctPos > 1 || correctPos < -1)
                {
                    var step = (int)(correctPos * 10 * Time.deltaTime);
                    step = step == 0 ? correctPos > 0 ? 1 : -1 : step;
                    step = System.Math.Abs(correctPos) < System.Math.Abs(step) ? correctPos : step;

                    scrollPosition.y += step;
                    startPos -= step;
                    if (!mouseDown) correctPos -= step > 0 ? step / 4 > 1 ? step / 4 : 1 : step / 4 < -1 ? step / 4 : -1;
                }
                else if (!mouseDown) slipWork = false;
            }
        }
    }

    public void AddItem(string itemName, Texture2D textureIcon)
    {
        if (!clearScrollList)
        {
            itemList.Add(new Item(itemList.Count, itemName, textureIcon ?? textureNull));
            if (!withScroll) withScroll = itemList.Count * (rowHeight + rowSpace) - rowSpace > windowRect.height;
        }
        else itemListTemp.Add(new Item(itemListTemp.Count, itemName, textureIcon ?? textureNull));
    }

    public void Clear()
    {
        clearScrollList = true;
    }

    private void OnGUI()
    {
        if (enableView)
        {
            if (clearScrollList)
            {
                itemList.Clear();
                foreach (var item in itemListTemp) itemList.Add(item);
                itemListTemp.Clear();
                selectedItem = -1;
                scrollPosition = new Vector2();
                clearScrollList = false;
                withScroll = itemList.Count * (rowHeight + rowSpace) - rowSpace > windowRect.height;
            }

            GUI.skin = optionsSkin;

            if (withScroll) GUI.Window(0, windowRect, DoWindow2, "");
            else GUI.Window(0, windowRect, DoWindow1, "");

            GUI.Label(new Rect(windowRect.x, 0, windowRect.width, 20), testRowQty + " items", optionsSkin.FindStyle("StyleForTest"));
        }
    }

    private void DoWindow1(int windowID)
    {
        Rect rBtn = new Rect(0, 0, windowRect.width, rowHeight);

        foreach (var item in itemList)
        {
            DreawItem(item, rBtn);
            rBtn.y += (rowHeight + rowSpace);
        }
    }

    private void DoWindow2(int windowID)
    {
        Rect rScrollFrame = new Rect(0, 0, windowRect.width, windowRect.height);
        Rect rList = new Rect(0, 0, windowRect.width - optionsSkin.verticalScrollbar.fixedWidth - optionsSkin.verticalScrollbar.margin.left, itemList.Count * (rowHeight + rowSpace));
        Rect rBtn = new Rect(0, 0, windowRect.width - optionsSkin.verticalScrollbar.fixedWidth - optionsSkin.verticalScrollbar.margin.left, rowHeight);

        scrollPosition = GUI.BeginScrollView(rScrollFrame, scrollPosition, rList, false, false);

        foreach (var item in itemList)
        {
            if (rBtn.yMax >= scrollPosition.y && rBtn.yMin <= (scrollPosition.y + rScrollFrame.height)) DreawItem(item, rBtn);
            rBtn.y += (rowHeight + rowSpace);
        }
        GUI.EndScrollView();
    }

    private void DreawItem(Item item, Rect itemRect)
    {
        bool bClicked;

        if (item.id == selectedItem)
        {
            bClicked = GUI.Button(itemRect, item.name, optionsSkin.box);
            GUI.DrawTexture(new Rect(itemRect.width - 80, itemRect.yMin + 6, 69, 69), item.icon);
        }
        else
        {
            bClicked = GUI.Button(itemRect, item.name);
            GUI.DrawTexture(new Rect(itemRect.width - 82, itemRect.yMin + 8, 65, 65), item.icon);
        }

        if (bClicked)
        {
            selectedItem = item.id;
        }
    }

    private class Item
    {
        public int id;
        public string name;
        public Texture2D icon;

        public Item(int id, string name, Texture2D icon)
        {
            this.id = id;
            this.name = name;
            this.icon = icon;
        }
    }
}

HTML код для вашего блога :
Код: Выделить всё
<script language='javascript' type="text/javascript"> document.write("<iframe marginheight='0' src='http://unity3d.ru/distribution/player.php?url=http://gloo.clan.su/BuildWeb.unity3d&w=900&h=700&t=true&preview=1' height='"+(700+30)+"' width='900' frameborder='0' scrolling='no'></iframe>"); </script>
Аватара пользователя
Glooger
UNIт
 
Сообщения: 118
Зарегистрирован: 04 апр 2013, 08:40

Re: Удобный VerticalScrollView

Сообщение BornFoRdeatH 28 янв 2014, 21:56

Синтаксис:
Используется csharp
foreach (var item in itemList)
        {
            if (rBtn.yMax >= scrollPosition.y && rBtn.yMin <= (scrollPosition.y + rScrollFrame.height)) DreawItem(item, rBtn);
            rBtn.y += (rowHeight + rowSpace);
        }
 


Это же избыточно. Зачем цыклить весь массив когда вы и без того знаете с какого по какой индекс отрисовывать, у вас высота всех елементов списка одинакова, вот вам scrollPosition.y делим на высоту елемента списка, получаем с какого индекса начинать рисовать, далее высоту видимой области делим на высоту елемента, получаем количество отрисовываемых елементов, добавляем 1-2 для кореектного отображения и вот у вас уже цикл из десятка итераций, а не 25 тыщ как у вас.
Не бойся, если ты один, бойся, если ты ноль.
BornFoRdeatH
Адепт
 
Сообщения: 2377
Зарегистрирован: 22 окт 2011, 23:41
Откуда: Украина
Skype: bornfordeath

Re: Удобный VerticalScrollView

Сообщение Glooger 28 янв 2014, 23:33

Ну сам факт, что в списке 25 000 элементов - это уже не нормально и что-то нужно менять.
А в реальности у меня в среднем 5 - 20 элементов в списке, так что думаю не критично. Но конечно всё равно взять на заметку нужно
Аватара пользователя
Glooger
UNIт
 
Сообщения: 118
Зарегистрирован: 04 апр 2013, 08:40


Вернуться в Исходники (Копилка)

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1