Сегментированные отображение растровых карт SkiaSharp

Объект SkiaSharp SKCanvas определяет метод с именем DrawBitmapNinePatch и двумя методами, которые DrawBitmapLattice очень похожи. Оба этих метода отрисовывают растровое изображение до размера прямоугольника назначения, но вместо равномерного растяжения растрового изображения отображают части растрового изображения в его измерениях пикселей и растягивают другие части растрового изображения, чтобы он соответствовал прямоугольнику:

Сегментированные примеры

Эти методы обычно используются для отрисовки растровых изображений, которые образуют часть объектов пользовательского интерфейса, таких как кнопки. При проектировании кнопки обычно требуется, чтобы размер кнопки был основан на содержимом кнопки, но вы, вероятно, хотите, чтобы граница кнопки была одинаковой шириной независимо от содержимого кнопки. Это идеальное применение DrawBitmapNinePatch.

DrawBitmapNinePatch это особый случай DrawBitmapLattice , но это проще двух методов для использования и понимания.

Отображение девяти исправлений

Концептуально делит DrawBitmapNinePatch растровое изображение на девять прямоугольников:

Девять исправлений

Прямоугольники в четырех углах отображаются в их размерах пикселей. Как указывают стрелки, другие области на краях растрового изображения растягиваются по горизонтали или по вертикали к области целевого прямоугольника. Прямоугольник в центре растянут как по горизонтали, так и по вертикали.

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

Чтобы разделить растровое изображение на эти девять прямоугольников, необходимо указать прямоугольник в центре. Это синтаксис DrawBitmapNinePatch метода:

canvas.DrawBitmapNinePatch(bitmap, centerRectangle, destRectangle, paint);

Прямоугольник центра относительно растрового изображения. Это значение (целочисленная SKRectI версия SKRect) и все координаты и размеры находятся в единицах пикселей. Прямоугольник назначения относится к поверхности отображения. Аргумент paint не обязателен.

На странице "Девять исправлений" в примере сначала используется статический конструктор для создания общедоступного статического свойства типа SKBitmap:

public partial class NinePatchDisplayPage : ContentPage
{
    static NinePatchDisplayPage()
    {
        using (SKCanvas canvas = new SKCanvas(FiveByFiveBitmap))
        using (SKPaint paint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.Red,
            StrokeWidth = 10
        })
        {
            for (int x = 50; x < 500; x += 100)
                for (int y = 50; y < 500; y += 100)
                {
                    canvas.DrawCircle(x, y, 40, paint);
                }
        }
    }

    public static SKBitmap FiveByFiveBitmap { get; } = new SKBitmap(500, 500);
    ···
}

Две другие страницы в этой статье используют ту же растровую карту. Растровое изображение составляет 500 пикселей квадрата, и состоит из массива из 25 кругов, каждый из которых занимает 100 пикселей квадратной площади:

Круговая сетка

Конструктор экземпляра программы создает SKCanvasView обработчик, который используется DrawBitmapNinePatch для отображения растрового PaintSurface изображения, растянутого на всю область отображения:

public class NinePatchDisplayPage : ContentPage
{
    ···
    public NinePatchDisplayPage()
    {
        Title = "Nine-Patch Display";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKRectI centerRect = new SKRectI(100, 100, 400, 400);
        canvas.DrawBitmapNinePatch(FiveByFiveBitmap, centerRect, info.Rect);
    }
}

Прямоугольник centerRect охватывает центральный массив из 16 кругов. Круги в углах отображаются в их измерениях пикселей, и все остальное растягивается соответствующим образом:

Девять исправлений

Страница UWP имеет ширину 500 пикселей и, следовательно, отображает верхние и нижние строки в виде ряда кругов того же размера. В противном случае все круги, которые не находятся в углах, растягиваются, чтобы сформировать многоточие.

Для странного отображения объектов, состоящих из сочетания кругов и многоточий, попробуйте определить центр прямоугольника, чтобы он перекрывал строки и столбцы кругов:

SKRectI centerRect = new SKRectI(150, 150, 350, 350);

Отображение решеток

Два DrawBitmapLattice метода аналогичны DrawBitmapNinePatch, но они обобщены для любого количества горизонтальных или вертикальных разделов. Эти деления определяются массивами целых чисел, соответствующих пикселям.

Метод DrawBitmapLattice с параметрами для этих массивов целых чисел не работает. Метод DrawBitmapLattice с параметром типа SKLattice работает, и это тот, который используется в примерах, показанных ниже.

Структура SKLattice определяет четыре свойства:

  • XDivs, массив целых чисел
  • YDivs, массив целых чисел
  • Flags, массив SKLatticeFlags, тип перечисления
  • Bounds тип Nullable<SKRectI> , указывающий необязательный прямоугольник источника в растровом рисунке

Массив XDivs делит ширину растрового изображения на вертикальные полосы. Первая полоса расширяется от пикселя 0 слева до XDivs[0]. Эта полоса отображается в ширине пикселя. Вторая полоса простирается от XDivs[0] XDivs[1], и растянута. Третья полоса расширяется от XDivs[1] XDivs[2] и отображается в ширину пикселя. Последняя полоса расширяется от последнего элемента массива к правому краю растрового изображения. Если массив имеет четное количество элементов, он отображается в ширине пикселя. В противном случае это растянуто. Общее число вертикальных полос — это несколько элементов в массиве.

Массив YDivs аналогичен. Он делит высоту массива на горизонтальные полосы.

Вместе массив XDivs YDivs делит растровое изображение на прямоугольники. Число прямоугольников равно продукту числа горизонтальных полос и количеству вертикальных полос.

Согласно документации Skia, Flags массив содержит один элемент для каждого прямоугольника, сначала верхнюю строку прямоугольников, а затем вторую строку и т. д. Массив Flags имеет тип SKLatticeFlags, перечисление со следующими элементами:

  • Default со значением 0
  • Transparent со значением 1

Тем не менее, эти флаги, кажется, не работают, как они должны, и лучше всего игнорировать их. Но не устанавливайте Flags для свойства значение null. Задайте для него достаточно большой массив значений SKLatticeFlags , чтобы охватывать общее количество прямоугольников.

Страница Lattice Nine Patch используется DrawBitmapLattice для имитации DrawBitmapNinePatch. Он использует ту же растровую карту, созданную в NinePatchDisplayPage:

public class LatticeNinePatchPage : ContentPage
{
    SKBitmap bitmap = NinePatchDisplayPage.FiveByFiveBitmap;

    public LatticeNinePatchPage ()
    {
        Title = "Lattice Nine-Patch";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }
    `
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        SKLattice lattice = new SKLattice();
        lattice.XDivs = new int[] { 100, 400 };
        lattice.YDivs = new int[] { 100, 400 };
        lattice.Flags = new SKLatticeFlags[9];

        canvas.DrawBitmapLattice(bitmap, lattice, info.Rect);
    }
}

XDivs YDivs Оба свойства задаются массивами всего двух целых чисел, разделяя растровое изображение на три полосы как по горизонтали, так и по вертикали: от пикселя 0 до пикселя 100 (отрисовывается в размере пикселя), от пикселя 100 до пикселя 400 (растянутый) и от пикселя 400 до пикселя 500 (размер пикселя). XDivs Вместе и YDivs определите в общей сложности 9 прямоугольников, что является размером массиваFlags. Простое создание массива достаточно для создания массива значений SKLatticeFlags.Default .

Отображение идентично предыдущей программе:

Латтис Девять исправлений

Страница отображения lattice делит растровое изображение на 16 прямоугольников:

public class LatticeDisplayPage : ContentPage
{
    SKBitmap bitmap = NinePatchDisplayPage.FiveByFiveBitmap;

    public LatticeDisplayPage()
    {
        Title = "Lattice Display";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKLattice lattice = new SKLattice();
        lattice.XDivs = new int[] { 100, 200, 400 };
        lattice.YDivs = new int[] { 100, 300, 400 };

        int count = (lattice.XDivs.Length + 1) * (lattice.YDivs.Length + 1);
        lattice.Flags = new SKLatticeFlags[count];

        canvas.DrawBitmapLattice(bitmap, lattice, info.Rect);
    }
}

YDivs И XDivs массивы несколько отличаются, что приводит к тому, что отображение не совсем так симметрично, как в предыдущих примерах:

Лартис-дисплей

В изображениях iOS и Android слева только меньшие круги отображаются в размерах пикселей. Все остальное растянуто.

Страница отображения lattice обобщает создание массива Flags , что позволяет экспериментировать с XDivs и YDivs более легко. В частности, вы хотите увидеть, что происходит при установке первого элемента XDivs элемента или YDivs массива в значение 0.