Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 851
Uka Lpts Avatar asked Jul 08 '16 20:07

Uka Lpts


2 Answers

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

like image 151
Uka Lpts Avatar answered Nov 03 '22 11:11

Uka Lpts


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.

like image 2
George Edwards Avatar answered Nov 03 '22 10:11

George Edwards