Is there a way to make a NativeScript GridLayout with a fixed aspect ratio?
Asked Answered
A

3

5

First of all, I'd like to apologize if I fail to comply with any SO rules, as it's my first question.

What I'm trying to acomplish, is having a square gridLayout in my page. The behavior should be equivalent to having an element with stretch="aspectFit".

If the suggested solution could let me enforce any given aspect ratio instead of just a square one, it would be a nice plus, because it would allow me to solve multiple situations in the future. Or if it could be applied to any Layout element, it would also be nice.

The solution can be as hacky as desired, and the GridLayout can be nested in any way you need to acomplish this.

I have already tried to hack it like this:

 <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>

Visually it seemed to work, but the contents of the GridLayout didn't fill it apropriately

PS: I just noticed in the example I chose, the layout element I am trying to make square is the nested StackLayout, but it's the same idea. I need a way to make a nested layout element squared.

Alina answered 8/7, 2016 at 20:50 Comment(3)
Are you willing to have some JS that runs on the loaded event? If so this is trivial to do. If you want it in pure XML, it is not possible because nothing constrains the Y to X (or X to Y) values built into the grid.Politicize
@Politicize I'm open to any solution. I'm on the early stages of my development so I think I could cope with almost any solutionAlina
@Politicize I should also state I'm working on an Angular2 application. Maybe the events or the lifecycle affect the answerAlina
A
6

Thanks to @Nathanael for giving me insights into what I could possibly do.

I found the solution and here it is for anyone who might need it.

First of all, I'll be using the following Template:

<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>

My goal is to make the GridLayout look square and centered on the screen, no matter the device or screen aspect ratio. To accomplish this I did the following in JavaScript (or TypeScript in this case, as I'm working with Angular2 + Nativescript) inside the Component Definition

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();
}

And this was the result:

Square GridLayout in multiple screen resolutions and aspect ratios

Alina answered 10/7, 2016 at 18:57 Comment(0)
C
2

You can use the native properties of a grid layout. You will need to ensure your grid fills the whole screen (can be done by targeting it with a css class). Then you can create the resolution you need in rows and columns, note the use of x* to define relative widths, my chosen demo has 10, so * represents 10%.

You can then nest other layouts in the grid cells if you wish.

<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>

Hope that helps.

Capriola answered 10/7, 2016 at 17:49 Comment(0)
C
0

The code below worked for me - it uses up all space of the screen. You might want something different for larger screens though.

<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>

The value len is computed as follows:

import {isAndroid, isIOS, screen} from "tns-core-modules/platform";
...
ngAfterViewInit() { 
    this.len = screen.mainScreen.widthDIPs / 2;
}
Carraway answered 6/1, 2020 at 22:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.