How to position element at the bottom of Absolute Layout in NativeScript?

clzola picture clzola · Jul 19, 2017 · Viewed 11.7k times · Source

I want to position an element at the bottom of the screen in Absolute Layout in NativeScript.

I have this code:

<AbsoluteLayout>
    <maps:mapView 
        left="0"
        top="0"
        width="100%"
        height="100%"
        latitude="{{ map.latitude }}" 
        longitude="{{ map.longitude }}" 
        zoom="{{ map.zoom }}"
        padding="{{ map.padding }}"  
        mapReady="onMapReady"
        coordinateTapped="onCoordinateTapped"
        markerSelect="onMarkerSelect"
        shapeSelect="onShapeSelect"
        cameraChanged="onMapCameraChanged"/>

    <ScrollView
        left="0"
        top="0"
        width="100%"
        orientation="horizontal">
        <!-- More XML -->
    </ScrollView>

    <StackLayout
        left="0"
        bottom="0"
        width="100%"
        visibility="visible"
        orientation="horizontal"
        style="background-color: red;">

        <Label text="TITLE"></Label>

    </StackLayout>
</AbsoluteLayout>

I figured out that there is no bottom attribute for AbsoluteLayout... Here is the picture of what I want to create:

enter image description here

So how to arange items like in the picture, especially the bottom one?

EDIT: I should note that dimensions of this bottom rectangle may not be always same....

Answer

micster picture micster · Jul 19, 2017

I did something similar one day, programmatically & with Angular, maybe this can help.

If you don't want to use a GridLayout you can try to get height of your bottom element and of the screen, then place your element from the top with a simple calcul : screen's height - bottom element's height (- more if you want some padding). You can use two types of values : DIPs and pixels. If you're using pixels, you need to convert your values into DIPs by using the screen scale.

Something like this (I didn't test the code I'm giving you, it's just an example) :

1] add an id to your bottom element so you can access it inside your component :

<StackLayout #bottomElt></StackLayout>

2] update your component to set element position inside your absolute layout

// you need ElementRef, OnInit and ViewChild
import { Component, ElementRef, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { AbsoluteLayout } from "ui/layouts/absolute-layout";
import { StackLayout } from "ui/layouts/stack-layout";
// you need access to screen properties
import { screen } from "tns-core-modules/platform";
[...]

export class YourComponent implements OnInit {
    // add access to element inside your component
    @ViewChild("bottomElt") bottomElt: ElementRef;

    // create variable to access bottom element properties
    bottomContainer: StackLayout;

    // set bottom element position after view init
    // example : inside ngOnInit function (for Angular version)
    ngOnInit(): void {
        this.bottomContainer = <StackLayout>this.bottomElt.nativeElement;

        // using DIPs values only
        AbsoluteLayout.setTop(this.bottomContainer, (screen.mainScreen.heightDIPs - Number(this.bottomContainer.height)));

        // using pixels and screen scale
        // this way you can get height without knowing it
        AbsoluteLayout.setTop(this.bottomContainer, (screen.mainScreen.heightDIPs - (Number(this.bottomContainer.getMeasuredHeight()) / screen.mainScreen.scale)));

    }

More information about screen values : https://docs.nativescript.org/api-reference/interfaces/platform.screenmetrics.html

Alternative way

Instead of using AbsoluteLayout, you can use a GridLayout to set a bottom bar, with two rows : one with a wildcard size and the other with auto size so it can fit your bottom bar height everytime it changes. I did it this way in a mobile application to get a menu at the bottom in Android and IOS :

<GridLayout rows="*, auto" width="100%">
    <AbsoluteLayout row="0" orientation="vertical">
        <!-- YOUR CONTENT (maps & ScrollView) -->
    </AbsoluteLayout>

    <!-- YOUR BOTTOM BAR (StackLayout). Don't forget to add row="1" -->
    <StackLayout #bottomElt row="1">[...]</StackLayout>
</GridLayout>