Есть ли способ сделать NativeScript GridLayout с фиксированным соотношением сторон?

Прежде всего, я хотел бы извиниться, если я не соблюдаю какие-либо правила SO, так как это мой первый вопрос.

То, что я пытаюсь сделать, это наличие квадратной сетки на моей странице. Поведение должно быть эквивалентно наличию элемента с stretch="aspectFit".

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

Решение может быть настолько хакерским, насколько это необходимо, и GridLayout может быть вложен любым способом, который вам необходим для достижения этой цели.

Я уже пытался взломать это так:

 <GridLayout rows="*,auto,*" columns="*,auto,*" backgroundColor="green">
  <Image row="1" col="1" src="~/Images/1px-black.png" stretch="aspectFit" width="100%"></Image>
  <StackLayout row="1" col="1" orientation="vertical" backgroundColor="lightgray">
    <Label text="Label 1" width="100%" height="25%" backgroundColor="red"></Label>
    <Label text="Label 2" width="100%" height="25%" backgroundColor="green"></Label>
    <Label text="Label 3" width="100%" height="25%" backgroundColor="blue"></Label>
    <Label text="Label 4" width="100%" height="25%" backgroundColor="yellow"></Label>
  </StackLayout>
</GridLayout>

Визуально это сработало, но содержимое GridLayout не заполнило его надлежащим образом

PS: я только что заметил в примере, который я выбрал, элемент макета, который я пытаюсь сделать квадратным, является вложенным StackLayout, но это та же идея. Мне нужен способ сделать вложенный элемент макета в квадрате.

2 ответа

Решение

Спасибо @Nathanael за то, что дали мне понимание того, что я мог бы сделать.

Я нашел решение, и вот оно для всех, кому это может понадобиться.

Прежде всего, я буду использовать следующий шаблон:

<GridLayout rows="2*,3*,*,3*,*,3*,*,3*,2*" columns="2*,3*,*,3*,*,3*,*,3*,2*" backgroundColor="green" #refGrid>
    <Label text="A1" col="1" row="1" backgroundColor="#899bfe"></Label>
    <Label text="A2" col="1" row="3" backgroundColor="#899bfe"></Label>
    <Label text="A3" col="1" row="5" backgroundColor="#899bfe"></Label>
    <Label text="A4" col="1" row="7" backgroundColor="#899bfe"></Label>

    <Label text="B1" col="3" row="1" backgroundColor="#899bfe"></Label>
    <Label text="B2" col="3" row="3" backgroundColor="#899bfe"></Label>
    <Label text="B3" col="3" row="5" backgroundColor="#899bfe"></Label>
    <Label text="B4" col="3" row="7" backgroundColor="#899bfe"></Label>

    <Label text="C1" col="5" row="1" backgroundColor="#899bfe"></Label>
    <Label text="C2" col="5" row="3" backgroundColor="#899bfe"></Label>
    <Label text="C3" col="5" row="5" backgroundColor="#899bfe"></Label>
    <Label text="C4" col="5" row="7" backgroundColor="#899bfe"></Label>

    <Label text="D1" col="7" row="1" backgroundColor="#899bfe"></Label>
    <Label text="D2" col="7" row="3" backgroundColor="#899bfe"></Label>
    <Label text="D3" col="7" row="5" backgroundColor="#899bfe"></Label>
    <Label text="D4" col="7" row="7" backgroundColor="#899bfe"></Label>
</GridLayout>

Моя цель - сделать так, чтобы GridLayout выглядел квадратным и центрированным на экране, независимо от соотношения сторон устройства или экрана. Для этого я сделал следующее в JavaScript (или в нашем случае в TypeScript, так как работаю с Angular2 + Nativescript) внутри определения компонента

ngAfterViewInit() {
    let grid: GridLayout = <GridLayout>this.refGrid.nativeElement;
    var x = grid.getActualSize();

    function wait() {
        if (x.width <= 0) {
            x = grid.getActualSize();
            setTimeout(wait, 10);
        } else {
            grid.width=Math.min(x.width, x.height);
            grid.height=Math.min(x.width, x.height);          
        }
    }
    wait();
}

И это был результат:

Square GridLayout в нескольких разрешениях экрана и пропорциях

Вы можете использовать собственные свойства макета сетки. Вам нужно будет убедиться, что ваша сетка заполняет весь экран (это можно сделать, нацелив ее на класс css). Затем вы можете создать необходимое разрешение в строках и столбцах, обратите внимание на использование x* чтобы определить относительную ширину, моя выбранная демонстрация имеет 10, так * представляет 10%.

Затем вы можете вкладывать другие макеты в ячейки сетки, если хотите.

<GridLayout rows="*,*,*,*" columns="*,2*,3*,4*">
  <Label row="0" col="0" [colSpan]="4" backgroundColor="lightgray"> // Will be 100% width, height will be 10%
  </Label>
  <Label row="1" col="0" [colSpan]="4" backgroundColor="blue"> // Will be 100% width, height will be 20%
  </Label>
  <Label row="2" col="0" [colSpan]="4" backgroundColor="green"> // Will be 100% width, height will be 30%
  </Label>
  <Label row="3" col="0" [colSpan]="4" backgroundColor="red"> // Will be 100% width, height will be 40%
  </Label>
</GridLayout>

Надеюсь, это поможет.

Приведенный ниже код сработал для меня - он занимает все пространство экрана. Однако для больших экранов вам может понадобиться что-то другое.

<FlexboxLayout flexDirection="row" flexWrap="wrap">
    <GridLayout flexGrow="1" row="*" columns="*" *ngFor="let tile of tiles" [width]="len" [height]="len">
        <StackLayout horizontalAlignment="center" verticalAlignment="center">
            <Label [text]="tile.line"></Label>
        </StackLayout>
    </GridLayout>
</FlexboxLayout>

Значение len вычисляется следующим образом:

import {isAndroid, isIOS, screen} from "tns-core-modules/platform";
...
ngAfterViewInit() { 
    this.len = screen.mainScreen.widthDIPs / 2;
}
Другие вопросы по тегам