Multiple layouts over google maps - nativescript

i was wondering is it possible to create something like this? https://prnt.sc/o3b62o google map on full screen and 2 buttons. (one top and one at the bottom) I have version with grid layout, but then map is not interactive.
<GridLayout className="map-layout" rows="*, auto">
<StackLayout className="map" rowSpan="2">
<MapView width="100%"height="100%":zoom="7"
:latitude="parseFloat(location.lat)"
:longitude="parseFloat(location.lng)"/>
</StackLayout>
<Button text="bottom button" row="1"></Button>
<Button text="top button" row="0"></Button>
</GridLayout>

If you are looking for a floating space at top and bottom of map, you are not suppose to use two rows, it should be one row with vertical alignment set to top / bottom.
<GridLayout class="map-layout">
<MapView class="map" :zoom="7"
:latitude="parseFloat(location.lat)"
:longitude="parseFloat(location.lng)"/>
<Button text="bottom button" verticalAlignment="bottom"></Button>
<Button text="top button" verticalAlignment="top"></Button>
</GridLayout>
Lear more about layouts at https://www.nslayouts.com/

Related

How to customize reorderHandle in drag mode in angular typescript or how to hide it

<RadListView row="0" [items]="Array" itemReorder="true" (itemReordered)="groupReordered($event)" reorderMode="Drag">
how to hide default drag handle in ios or how to customize it
I have created a sample playgroud for you here.
To customise the recordhandle, you need to set that in item-template for listview like below
<RadListView class="list-group" [items]="countries" (itemReordered)="onItemReordered($event)"
itemReorder="true" reorderMode="Drag" style="height:1250px">
<ng-template let-country="item">
<FlexboxLayout flexDirection="row" class="list-group-item">
<ReorderHandle verticalAlignment="center">
<Image [src]="country.imageSrc" class="thumb img-circle"></Image>
</ReorderHandle>
<Label [text]="country.name" class="list-group-item-heading"
verticalAlignment="center" style="width: 60%"></Label>
</FlexboxLayout>
</ng-template>
</RadListView>
by default in ios, a reorder handle is displayed at the right side of the item. But in the example above you can drag by image. Also if you want to hide that then do not pass anything in ReorderHandle.

How do I get the height of an image or GridLayout after it displays

I'm using angular. I have an image carousel. I have two gridlayouts, one on top of the other. The top grid has the naviagation buttons. I want them to be positioned in the center of the image top to bottom. I'm trying to do that based on the image height, as it will differ depending on the device size. How do I get either the view image height or the containing grid height?
<GridLayout class="template_body" rows="auto,50*,auto" columns="*" #sv>
<GridLayout row="0" #wviWrapper>
<!-- <web-view id="wvi" #wvi></web-view> -->
<template-text *ngIf="lessonDetail.instruction" [data]="lessonDetail.instruction" [version]="version" [screenwidth]="screenWidth"></template-text>
</GridLayout>
<GridLayout row="1">
<player-carousel [data]='lessondata' [itemindex]="lessonindex" (loaded)="onCarouselLoaded($event)" [clength]="carouselLength"></player-carousel>
</GridLayout>
<GridLayout row="1">
<FlexboxLayout backgroundColor="#3c495e" alignItems="center" justifyContent="space-between" verticalAlignment="top" orientation="horizontal" class="button-group" #bg>
<Button text="" appDebounceTap (debounceClick)="getItem(-1)" [debounceTime]="1000" id="backbtn" col="0" alignSelf="flex-end" class="back-btn fas" horizontalAlignment="left"></Button>
<Button text="" appDebounceTap (debounceClick)="getItem(1)" [debounceTime]="1000" id="nextbtn" col="1" alignSelf="flex-end" class="next-btn fas" horizontalAlignment="right"></Button>
</FlexboxLayout>
</GridLayout>
</GridLayout>
I'm using angular:

How to correctly handle nested scroll views in Nativescript/Angular

I'm trying to create in Nativescript(Testing it on Android) a view containing a Donut Chart and an Accordion-like list below it, and enable infinite scrolling, so that when i scroll down the chart will scroll up out of the view, leaving the whole screen available for the list.
The problem is that no matter what i try the accordion-list will either scroll out of the view, leaving the chart on top of it, basically appearing like it's hiding behind the chart, or the elements won't display correctly / at all.
This is how my layout is made so far
Index screen
<ScrollView heiht="100%>
<StackLayout>
<DonutChart [chartDataIterable]="chartData"></DonutChart>
<Accordion [items]="items"></Accordion>
</StackLayout>
</ScrollView>
Donut Chart Component
<GridLayout rows="auto">
<RadPieChart row="0" height="300" allowAnimation="true" (pointSelected)="changeDisplayValue($event)" (pointDeselected)="resetToTotal($event)">
<DonutSeries tkPieSeries seriesName="dataSeries" selectionMode="DataPoint" outerRadiusFactor="0.9" expandRadius="0.4"
outerRadiusFactor="0.7" innerRadiusFactor="0.7" [items]="chartDataObservable" valueProperty="value" legendLabel="type"></DonutSeries>
</RadPieChart>
<StackLayout row="0" horizontalAlignment="center" verticalAlignment="center">
<Label horizontalAlignment="center" [text]="currentType"></Label>
<Label horizontalAlignment="center" [text]="currentTypeAmount"></Label>
</StackLayout>
</GridLayout>
Accordion Component
<ListView [items]="items" height="100%">
<ng-template let-item="item">
<AccordionCell [item]="item"></AccordionCell>
</ng-template>
</ListView>
The GridLayout wrapping the chart is used to add some info at the center of the donut, and the accordion height 100% is set to prevent the list view from taking the height of a single cell.
I suspect that the issue is due to ListView integrating a ScrollView by default, thus prioritizing the scrolling in the ListView and never triggering the scrolling of the outer ScrollView since the content never exceeds the screen size.
Since there hasn't been an answer for a week now i'll share the workaround i came up with.
Instead of using a ScrollView to scroll through my chart and accordion(basically ListView) components, i've moved the Chart and positioned it as the first cell of the ListView, this way both scrolling and cell recycling work well. The only drawback is that a little extra cell management is needed in order to make sure that the chart stays on top, without losing the first entry of the list's data source.
accordion.component.ts
ngOnInit(): void {
this.observableItems = new ObservableArray(this.items);
this.observableItems.unshift({});
}
public templateSelector (item: any, index: number, items: ObservableArray<any>){
if(index === 0)
return "chart";
else if(item.date != items.getItem(index-1).date)
return "date";
else
return "default";
}
accordion.component.html
<RadListView [items]="observableItems" [itemTemplateSelector]="templateSelector" (itemLoading)="itemLoading($event)">
<ng-template tkListItemTemplate let-item="item" let-index="index">
<AccordionCell [item]="item" [index]="index" [itemLoadedEvent]="itemLoadedEvent.asObservable()"></AccordionCell>
</ng-template>
<ng-template tkTemplateKey="date" let-item="item" let-index="index">
<StackLayout>
<Label [text]="item?.date | date: 'dd/MM/yyyy'"></Label>
<AccordionCell [item]="item" [index]="index" [itemLoadedEvent]="itemLoadedEvent.asObservable()"></AccordionCell>
</StackLayout>
</ng-template>
<ng-template tkTemplateKey="chart">
<DonutChart [chartDataIterable]="chartDataIterable (chartSectionSelected)="chartSectionSelectedHandler($event)" (chartSectionDeselected)="chartSectionDeselectedHandler()"></DonutChart>
</ng-template>

How to enable swipe gesture when tabView is positioned bottom

I am using nativescript-vue and I wanted to play around with tab-view. The problem is, when I set my tabs to be positioned at the bottom of the screen, the swipe gesture no longer works and is somewhat disabled. I want to enable swipe gesture.
Because I'm new to native-script or android, I'm not really sure how to enable it.
<Page actionBarHidden="true">
<TabView androidTabsPosition="bottom">
<TabViewItem title="Tab 1">
<GridLayout columns="*" rows="*">
<Label class="message" :text="msg" col="0" row="0"/>
</GridLayout>
</TabViewItem>
<TabViewItem title="Tab 2">
<GridLayout columns="*" rows="*">
<Label class="message" text="Tab 2 Content"/>
</GridLayout>
</TabViewItem>
<TabViewItem title="Tab 3">
<GridLayout columns="*" rows="*">
<Label class="message" text="Tab 3 Content"/>
</GridLayout>
</TabViewItem>
</TabView>
</Page>
The above script creates tabview with 3 tabs, but the problem is, now you can't swipe between the tabs. If I set androidTabsPosition="top", then swipe gesture works.
Can someone please enlighten me how to enable swipe gestures.
Here's the documentary for tabView in nativescript-vue
Enable swipe on the view pager from the TabView's loaded event. I didn't notice any side effect with this behaviour, incase if you hit anything let me know.
Template
...
<TabView androidTabsPosition="bottom" #loaded="onTabViewLoaded">
...
JS
onTabViewLoaded: function(args) {
if (args.object.android) {
args.object.android.viewPager.setSwipePageEnabled(true);
}
}

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

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:
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....
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>
Another option is using 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>
This is the absolute best solution, got it from one of the devs: 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 grid layout and have a item take up multiple grid spaces, sharing them with some other item.
here is the best solution
wrapper all the elements in an absolutelayout with width and hieght to 100% and maybe add a gridlayout 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>
It can be done also with GridLayout:
<GridLayout rows="16,*,16" columns="16,*,16" width="100%" backgroundColor="red">
<GridLayout row="1" col="1" rows="auto, auto, auto" columns="auto" horizontalAlignment="right" verticalAlignment="bottom" backgroundColor="blue">
<!-- Your content at bottom right corner -->
<Label row="0" text="Your content" textAlignment="center" textWrap="true"></Label>
<Label row="1" text="at" textAlignment="center" textWrap="true"></Label>
<Label row="2" text="bottom right corner" textAlignment="center"></Label>
</GridLayout>
</GridLayout>
This is the easy way
<DockLayout backgroundColor="lightgray" stretchLastChild="true">
<Label text="top" dock="top" height="60" backgroundColor="green">
</Label>
<Label text="bottom" dock="bottom" height="60" backgroundColor="yellow"></Label>
<Label text="center" backgroundColor="red"></Label>
</DockLayout>
This is what you want!
<DockLayout backgroundColor="lightgray" stretchLastChild="false">
<Label text="top" dock="top" height="60" backgroundColor="green">
</Label>
<Label text="bottom" dock="bottom" height="60" backgroundColor="yellow"></Label>
</DockLayout>

Resources