How do I position an element at the bottom of an Absolute layout in NativeScript?

I want to position an element at the bottom of the screen in an 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 the bottom attribute is missing for AbsoluteLayout ... Here is a picture of what I want to create:

enter image description here

So how do you arrange the elements like in the picture, especially the bottom one?

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

+5


source to share


4 answers


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

If you don't want to use a GridLayout, you can try to get the height of your bottom element and screen, then position your element on top with a simple calculation: screen height - bottom element height (- more if you need a little padding). You can use two types of values: DIP and Pixels. If you are using pixels, you need to convert your values ​​to DIP using the screen scale.

Something like this (I have not tested the code I am giving you, this is 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 the position of the element in 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 on screen values: https://docs.nativescript.org/api-reference/interfaces/platform.screenmetrics.html

Alternative way

Instead of using an AbsoluteLayout, you can use a GridLayout to set up a bottom bar with two rows, one with a wildcard font and one with an auto size so that every time it changes it can fit your bottom bar height. I did this in a mobile app to get the 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>

      

+8


source


Another option is to use FlexboxLayout in your AbsoluteLayout container like this:



<FlexboxLayout flexDirection="column" justifyContent="space-between" height="100%">
    <ScrollView
        width="100%"
        orientation="horizontal">
        <!-- More XML -->
    </ScrollView>

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

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

    </StackLayout>
</FlexboxLayout>

      

+1


source


Here's a better solution - wrap all the elements in absolute decomposition with width and height up to 100% and possibly add grid markup to hold the main content.

        <AbsoluteLayout width='100%' height='100%'>
           <StackLayout width='100%' hieght='100%' left='0' top='0'>
                 //add you structure here

           </StackLayout>
           add your fixed element here

           <image src='add the float item'/>
       </AbsoluteLayout>

      

0


source


This is absolutely the best solution I got from one of the developers: https://github.com/NativeScript/NativeScript/issues/5591#issuecomment-482640921

<GridLayout rows="*,auto">
   <ItemTakingFullScreen rowSpan="2"/>
   <ItemShownUnder row="1"/>
   <ItemShownAbove row="1">
</GridLayout>

      

Basically, you can use a grid and force an element to take up multiple grid spaces by sharing them with another element.

0


source







All Articles