20

When my layout loads any view inside of it has a width and height of NaN, it also has a getMeasuredHeight() and getMeasuredWidth() of 0.

At some point getMeasuredHeight() and getMeasuredWidth() (after the layout is laid out I guess) receive useful values.

How can I get the dimensions of anything? How can I watch them change?? When will .width and .height ever not be NaN??? Why can't I make a view hover over the entire screen????

So far I've been polling every 100ms and I feel pretty dumb. Please help.

Michael Eden
  • 948
  • 1
  • 7
  • 18
  • A view has the `width` and `height` property (see [documentation](https://docs.nativescript.org/ApiReference/ui/core/view/View.html),but what's your end goal here, what are you trying to achieve? – Emil Oberg Feb 18 '16 at 07:48
  • @EmilOberg To clarify my `width` and `height` are always `NaN` until I set them. I'm trying to watch the dimensions of an `AbsoluteLayout` so I can reorganize its children accordingly. But this is a general question of how in the world can you get the dimensions of a View in NativeScript (and watch it change). – Michael Eden Feb 18 '16 at 18:14
  • I upvoted this question, because the two mentioned methods were the solution to the problem that every dimension-property on a page is "auto", 0 or negative numbers. I was lucky not getting NaNs. – JackLeEmmerdeur Nov 13 '19 at 05:55

8 Answers8

16

Use the correct import:

const platform = require("platform")

or if you are using

import {screen} from "platform"
//or import {screen} from "tns-core-modules/platform/platform"

then you can use it depending on your language like this :

Typescript:

screen.mainScreen.widthDIPs //for example : 640
screen.mainScreen.widthPixels
screen.mainScreen.heightDIPs
screen.mainScreen.heightPixels

mainScreen implements the ScreenMetrics interface allowing access to the different screen sizes.

JS:

platform.screen.mainScreen.widthDIPs //for example : 640
platform.screen.mainScreen.widthPixels
platform.screen.mainScreen.heightDIPs
platform.screen.mainScreen.heightPixels

NOTE: this properties are the dimensions of the mobile device screen.

Nicu Surdu
  • 8,172
  • 9
  • 68
  • 108
odiaz
  • 241
  • 2
  • 3
  • 6
    Does not answer the question at all. – Gabriel Cséfalvay Jul 08 '18 at 14:53
  • @Tyg While it doesn't specifically answer the question, its the first hit on Google if you search for `get screen height in nativescript` and in that context, the answer is pretty relevant. – Muhammad bin Yusrat Aug 07 '19 at 09:50
  • Well at least the above import doesn't work - `import {screen} from "platform" //or import {screen} from "tns-core-modules/platform/platform"` Use this: `import { Screen } from '@nativescript/core';` Screen.mainScreen.heightDIPs – Kamil Kafoor Jun 22 '23 at 15:07
9

you can try view.getActualSize().width/height on navigatedTo event. only on this event you can get the actual height/width of a layout/view

you can refer here

Giorgos Myrianthous
  • 36,235
  • 20
  • 134
  • 156
Sagar1911
  • 113
  • 1
  • 5
6

It is possible to watch for the layoutChanged event of View. It is fired every time the layout process is done incl. view resize

myView.on("layoutChanged", function(){
    console.log("layout change");
});
4

When NS fires loaded event for a view, it has not been rendered at this point yet. That's why all your views inside have 0 height and width. You can workaround by waiting for sometime and than try to get the view dimensions. Add this to your loaded function:

var height = 0

function checkIfViewRendered() {
    setTimeout(function() {
        height = view.getMeasuredHeight()
    }, 100)
    if (height === 0) checkIfViewRendered()
    else console.log('rendered height is', height)
}

checkIfViewRendered()

Hope this helps.

terreb
  • 1,417
  • 2
  • 23
  • 40
2

How can I watch them change??

You can configure some variables when the device rotates, too:

in Angular2:

import { Component, OnInit, OnDestroy, NgZone } from "@angular/core";
import * as application from "application";

@Component({
    ...
})
export class MyComponent implements OnInit, OnDestroy {

    ngOnInit() {
        this.setIsScreenWide();
        application.on(application.orientationChangedEvent, this.onOrientationChanged, this);
    }

    isScreenWide: boolean;

    setIsScreenWide() {
        let widthDIPs = screen.mainScreen.widthDIPs;
        this.isScreenWide = widthDIPs >= 480;
    }

    onOrientationChanged = (args: application.OrientationChangedEventData) => {
        this.zone.run(() => {
            setTimeout(() => {
                this.setIsScreenWide();
            }, 17 /* one frame @ 60 frames/s, no flicker */);
        });
    };

    ngOnDestroy() {
        application.off(application.orientationChangedEvent, this.onOrientationChanged, this);
    }

    ...
}
EricRobertBrewer
  • 1,750
  • 1
  • 22
  • 25
2

You can use layoutChangedEvent to respond to the view being resized. If your view is called view, something like the following should do the trick:

import { View } from "ui/core/view";
import { EventData } from 'data/observable';

// ...

view.on(View.layoutChangedEvent, (e:EventData) => {
  const size = view.getActualSize();
  // ... do something with the size
});
Jesse Crossen
  • 6,945
  • 2
  • 31
  • 32
1

you can subscribe to the navigatedTo event of the page, that seems to occur after the view has been laid out. There the getMeasuredHeight() and getMeasuredWidth() methods should return a value.

In the xml file add:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded" navigatedTo="{{ navigated }}">
<DockLayout id="mainLayout">
...
</DockLayout>

In the ts file add the matching method:

public navigated(args:EventData){
        alert ("My view height is " + this.myView.getMeasuredHeight());
    }

and in the pageLoaded event link myViewto your view:

public pageLoaded(args: EventData) {
    this.page = <Page>args.object;
    this.page.bindingContext = this;
    this.myView = <DockLayout>this.page.getViewById("mainLayout");        
}

Hope this helps.

Stefano

talpaz
  • 1,956
  • 2
  • 13
  • 14
  • the `navigatedTo` event does not have a `this` reference or any attribute that I can find that let's me access my view. – Michael Eden Mar 08 '16 at 18:22
  • @Michael You can get a reference to the view in the loaded event, then access the stored reference in the navigated event. ```js public pageLoaded(args: EventData) { this.page = args.object; this.layout = this.page.getViewById("mainLayout"); } ``` – talpaz Mar 09 '16 at 21:22
  • oh OK! I had no idea `this` persisted across these functions. Thank you! I will try it out. – Michael Eden Mar 09 '16 at 21:42
  • sorry but this method doesn't seem to work on my NativeScript version (1.6.1). – Michael Eden Mar 15 '16 at 00:42
  • I've just tested it in 1.6.1 with the iOS emulator and it seems to work... are you using Android? Have you got some code to show? maybe some linking is missing... we could take a look... – talpaz Mar 16 '16 at 22:04
0

This code works for me

this.webView.on(WebView.loadedEvent, () => {
  this.webView.on(WebView.layoutChangedEvent, () => {
    this.size = this.webView.getActualSize();
    console.log("size: ", this.size);
  });
});