Как сделать так, чтобы пользовательская Unity LayoutGroup расширялась, чтобы соответствовать содержимому

Основываясь на ответе @ zx81, вы получите подходящую идею, я добавил Java 9 results call, который возвращает Stream. Поскольку OP хотел использовать split, я собрал String[], как это делает split.

Осторожно, если у вас есть пробелы после разделителей запятой (a, b, "c,d"). Затем вам нужно изменить шаблон.

Jshell demo

$ jshell
-> String so = "123,test,444,\"don't split, this\",more test,1";
|  Added variable so of type String with initial value "123,test,444,"don't split, this",more test,1"

-> Pattern.compile("\"[^\"]*\"|[^,]+").matcher(so).results();
|  Expression value is: java.util.stream.ReferencePipeline$Head@2038ae61
|    assigned to temporary variable $68 of type java.util.stream.Stream<MatchResult>

-> $68.map(MatchResult::group).toArray(String[]::new);
|  Expression value is: [Ljava.lang.String;@6b09bb57
|    assigned to temporary variable $69 of type String[]

-> Arrays.stream($69).forEach(System.out::println);
123
test
444
"don't split, this"
more test
1

Код

String so = "123,test,444,\"don't split, this\",more test,1";
Pattern.compile("\"[^\"]*\"|[^,]+")
    .matcher(so)
    .results()
    .map(MatchResult::group)
    .toArray(String[]::new);

Объяснение

  1. Regex [^"] соответствует: цитата, ничего, кроме цитаты, цитата.
  2. Regex [^"]* соответствует: цитата, ничего, кроме цитаты 0 (или более) раз, цитата.
  3. Это регулярное выражение должно идти первым, чтобы «выиграть», в противном случае сопоставление ничего, кроме запятой 1 или более раз , то есть: [^,]+ - будет «побеждать».
  4. results() требует Java 9 или выше.
  5. Он возвращает Stream<MatchResult>, который я сопоставляю с помощью вызова group() и собираю в массив строк. Вызов Parameterless toArray() возвратит Object[].
0
задан Stan 16 January 2019 в 23:01
поделиться

1 ответ

Через какое-то время я получил значок, и я решил выделить время, чтобы найти решение. Надеюсь, кому-то еще это пригодится.

Опять же, это модифицированная версия работы, проделанной здесь . Спасибо за это. Этот компонент теперь вычисляет его собственный предпочтительный размер.

Основные изменения:

  1. Я удалил его довольно сильно:
    • Все горизонтальные переопределения очищены, мне нужно только горизонтальное поведение обтекания
    • Удалены некоторые очевидные Переменные похмелья из класса GridLayout
  2. Логика для вычисления дочерних позиций и, в свою очередь, количества строк, предпочтительная высота в своем собственном методе.
  3. Дочерние позиции сохраняются в массиве Vector2, чтобы отделить расчет от дочерних настроек.

Это устраняет проблему с высотой всего компонента, который не корректируется, а также немедленно реагирует с исходным сценарием из-за того, как были установлены дочерние объекты rectTransforms, а затем к сценарию потребовалось два «цикла», чтобы распознать размеры ребенок.

Это соответствует всем моим потребностям, я думаю, что это может быть довольно легко переработано, чтобы справиться и с вертикальной намоткой ...

using UnityEngine;
using UnityEngine.UI;

[AddComponentMenu("Layout/Wrap Layout Group", 153)]
public class WrapLayoutGroup : LayoutGroup
{
    [SerializeField] protected Vector2 m_Spacing = Vector2.zero;
    public Vector2 spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } }

    [SerializeField] protected bool m_Horizontal = true;
    public bool horizontal { get { return m_Horizontal; } set { SetProperty(ref m_Horizontal, value); } }

    private float availableWidth { get { return rectTransform.rect.width - padding.horizontal + spacing.x; } }

    private const float MIN_HEIGHT = 80;

    private int preferredRows = 1;
    private float calculatedHeight = MIN_HEIGHT;

    private Vector2[] childPositions = new Vector2[0];

    protected WrapLayoutGroup()
    { }

#if UNITY_EDITOR
    protected override void OnValidate()
    {
        base.OnValidate();
    }

#endif

    public override void CalculateLayoutInputVertical()
    {
        calculatePositionsAndRequiredSize();
        SetLayoutInputForAxis(calculatedHeight, calculatedHeight, -1, 1);
    }

    public override void SetLayoutHorizontal() { }

    public override void SetLayoutVertical()
    {
        SetChildren();
    }

    private void SetChildren()
    {
        for (int i = 0; i < rectChildren.Count; i++)
        {
            RectTransform child = rectChildren[i];
            SetChildAlongAxis(child, 0, childPositions[i].x, LayoutUtility.GetPreferredWidth(child));
            SetChildAlongAxis(child, 1, childPositions[i].y, LayoutUtility.GetPreferredHeight(child));
        }
    }

    private void calculatePositionsAndRequiredSize()
    {
        childPositions = new Vector2[rectChildren.Count];

        Vector2 startOffset = new Vector2(
            GetStartOffset(0, 0),
            GetStartOffset(1, 0)
        );

        Vector2 currentOffset = new Vector2(
            startOffset.x,
            startOffset.y
        );

        float childHeight = 0;
        float childWidth = 0;
        float maxChildHeightInRow = 0;

        int currentRow = 1;

        for (int i = 0; i < rectChildren.Count; i++)
        {
            childHeight = LayoutUtility.GetPreferredHeight(rectChildren[i]);
            childWidth = LayoutUtility.GetPreferredWidth(rectChildren[i]);

            //check for new row start
            if (currentOffset.x + spacing.x + childWidth > availableWidth && i != 0)
            {
                currentOffset.x = startOffset.x;
                currentOffset.y += maxChildHeightInRow + spacing.y;
                currentRow++;
                maxChildHeightInRow = 0;
            }

            childPositions[i] = new Vector2(
                currentOffset.x,
                currentOffset.y
            );

            //update offset
            maxChildHeightInRow = Mathf.Max(maxChildHeightInRow, childHeight);
            currentOffset.x += childWidth + spacing.x;

        }

        //update groups preferred dimensions
        preferredRows = currentRow;
        calculatedHeight = currentOffset.y + maxChildHeightInRow + padding.vertical - spacing.y;
    }
}

0
ответ дан Stan 16 January 2019 в 23:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: