Что такое Xamarin.Forms эквивалент layoutSubviews?

Я переношу большую базу кода iOS в приложение Xamarin.Forms. У нас есть много пользовательских представлений, которые выполняют свою логику макета, выполняя вычисления в -layoutSubviews. Кодовая база слишком велика, чтобы я мог ее вовремя портировать, если мне нужно будет переинтерпретировать эти расчеты с точки зрения макетов стека или сетки. Что мне действительно нужно, так это прямой эквивалент, где я могу добавлять эквивалентные подпредставления в наши представления, не беспокоясь о том, куда они идут, а затем метод, который вызывается при изменении границ представления, внутри которого я могу установить новые границы подпредставлений. Затем я могу напрямую портировать наш существующий код iOS.

Есть ли эквивалент в Xamarin.Forms для -layoutSubviews?


person Simon    schedule 08.08.2016    source источник


Ответы (2)


Вы можете создать свой собственный макет, производный от класса Xamarin.Forms.Layout.

public class CustomLayout : Layout<View>
{
    public CustomLayout ()
    {

    }
}

Макет должен переопределить метод LayoutChildren. Этот метод отвечает за позиционирование детей на экране.

Дети могут быть измерены с помощью метода GetSizeRequest, который вернет как желаемый размер, так и минимальный размер, который желает ребенок.

protected override void LayoutChildren (double x, double y, double width, double height)
{
    for (int i = 0; i < Children.Count; i++) {
        var child = (View) Children[i];
        // skip invisible children

        if(!child.IsVisible) 
            continue;
        var childSizeRequest = child.GetSizeRequest (double.PositiveInfinity, height);
        var childWidth = childSizeRequest.Request.Width;
        LayoutChildIntoBoundingRegion (child, new Rectangle (x, y, childWidth, height));
        x += childWidth;
    }
}

Этот метод будет автоматически вызываться всякий раз, когда макет необходимо пересчитать. Если ваш макет состоит из жестко закодированных элементов или элементов фиксированного размера, жестко закодируйте их размеры в этом алгоритме вместо измерения. Вызовы GetSizeRequest являются одними из самых дорогих вызовов, которые можно сделать, и их непредсказуемость во время выполнения, поскольку поддерево может быть произвольно сложным. Фиксация их размера — отличный способ повысить производительность, если динамическое изменение размера не требуется.

Реализация OnSizeRequest необходима, чтобы убедиться, что новый макет имеет правильный размер при размещении внутри других макетов. Во время циклов макета этот метод может вызываться много раз в зависимости от макета над ним и от того, сколько исключений макета требуется для разрешения текущей иерархии макета.

protected override SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint)
{
    var height = 0;
    var minHeight = 0;
    var width = 0;
    var minWidth = 0;

    for (int i = 0; i < Children.Count; i++) {
        var child = (View) Children[i];
        // skip invisible children

        if(!child.IsVisible) 
            continue;
        var childSizeRequest = child.GetSizeRequest (double.PositiveInfinity, height);
        height = Math.Max (height, childSizeRequest.Minimum.Height);
        minHeight = Math.Max (minHeight, childSizeRequest.Minimum.Height);
        width += childSizeRequest.Request.Width;
        minWidth += childSizeRequest.Minimum.Width;
    }

    return new SizeRequest (new Size (width, height), new Size (minWidth, minHeight));
}

Вы можете прочитать полное руководство по созданию пользовательского макета здесь.

person Rohit Vipin Mathews    schedule 17.08.2016

Я не уверен, есть ли эквивалент в формах для layoutSubviews, но вычисления, о которых вы говорите, могут быть выполнены внутри метода, называемого:

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height);
}

Вам нужно наследоваться от ContentPage или Any Page, чтобы переопределить этот метод.

person Mario Galván    schedule 08.08.2016