iOS buttons become unclickable after making a floating layout - nativescript

I'm creating a custom action bar and my idea is that the actionbar must be transparent (thats why I can't/don't want to use the native one) and behind the action bar there must be content (an image in this case).
I tried multiple ways and all of them with the same result, the iOS button become unclickable for no reason.
Ok, so I have an AbsoluteLayout inside I have GridLayout fixed on top as the custom actionbar and then a ScrollView with 100% width and height, inside the scrollview there's some content. The problem is as soon as I put a button inside the GridLayout this become unclickable only on iOS because in Android works just fine.
Let me show you my example with some code:
<Page actionBarHidden="true">
<AbsoluteLayout>
<GridLayout rows="50, *" backgroundColor="red" top="0" left="0" height="50" id="bar">
<Button text="click" #tap="goToDetailPage" id="buttondelsous"></Button>
</GridLayout>
<ScrollView backgroundColor="blue" width="100%" height="100%" top="0" id="content">
<WrapLayout>
<StackLayout>
<Label text="this is behind"></Label>
</StackLayout>
</WrapLayout>
</ScrollView>
</AbsoluteLayout>
</Page>
As for the styles forcing the custom actionbar being in front of the scrollview I have:
#bar {
z-index: 5;
width: 100%;
}
#content {
z-index: 2;
}
This looks like this on Android:
Same way on iOS but the button "Click" is not working, like if it was behind something..
Any idea on how to fix this or any other approach to get what I need? Remember behind the action I must be able to place content (like a background image that I don't want to place in the Page tag itself but in another layout)
Thanks!

A wise man once told me that Nativescript stacks elements in the order you list them. Try flipping around the order so the button is listed last in the template. I believe you won't even need the z-index line if you flip the order around.
should look like
<Page actionBarHidden="true">
<AbsoluteLayout>
<ScrollView backgroundColor="blue" width="100%" height="100%" top="0" id="content">
<WrapLayout>
<StackLayout>
<Label text="this is behind"></Label>
</StackLayout>
</WrapLayout>
</ScrollView>
<!-- I'm listed second so I will be on top even though I have row="0" -->
<GridLayout rows="50, *" backgroundColor="red" top="0" left="0" height="50" id="bar">
<Button text="click" #tap="goToDetailPage" id="buttondelsous"/>
</GridLayout>
</AbsoluteLayout>
</Page>

Related

How to create bottom navigation bar

I am trying to create a simple fixed bottom navigation bar in my app using the nativescript-bottom-navigation plugin - and keep getting errors. It will not build, and of the many errors displayed in that horrid EXCEPTION black screen, is "AHBottomNavigation is not a constructor".
I simply want 3 icons in the fixed nav: Home, Account, Programs
I am using pure Javascript, and the demo tutorial is in TypeScript. This may be the issue.
Steps I Followed
I installed the plugin using the command line.
I added my icons manually to the resources folder
My Search Page [ where the nav will be located ]
<Page
navigatingTo="onNavigatingTo"
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:bottomNav="nativescript-bottom-navigation"
class="page">
<ActionBar class="action-bar">
<!--
Use the NavigationButton as a side-drawer button in Android
because ActionItems are shown on the right side of the ActionBar
-->
<NavigationButton ios:visibility="collapsed" icon="res://menu" tap="onDrawerButtonTap"></NavigationButton>
<!--
Use the ActionItem for IOS with position set to left. Using the
NavigationButton as a side-drawer button in iOS is not possible,
because its function is to always navigate back in the application.
-->
<ActionItem icon="res://navigation/menu"
android:visibility="collapsed"
tap="onDrawerButtonTap"
ios.position="left">
</ActionItem>
<Label class="action-bar-title" text="Search"></Label>
</ActionBar>
<GridLayout columns="*"
rows="*, auto">
<StackLayout row="0">
<Label text="content"></Label>
</StackLayout>
<bottomNav:BottomNavigation tabs="{{ tabs }}"
activeColor="green"
inactiveColor="red"
backgroundColor="black"
keyLineColor="black"
row="1"></bottomNav:BottomNavigation>
</GridLayout>
</Page>
and here is...
search-view-model.js
const observableModule = require("tns-core-modules/data/observable");
const SelectedPageService = require("../shared/selected-page-service");
const BottomNavigation = require("nativescript-bottom-navigation").BottomNavigation;
const BottomNavigationTab = require("nativescript-bottom-navigation").BottomNavigationTab;
const OnTabSelectedEventData = require("nativescript-bottom-navigation").OnTabSelectedEventData;
function SearchViewModel() {
SelectedPageService.getInstance().updateSelectedPage("Search");
const viewModel = observableModule.fromObject({
/* Add your view model properties here */
tabs: [
new BottomNavigationTab('First', 'ic_home'),
new BottomNavigationTab('Second', 'ic_view_list'),
new BottomNavigationTab('Third', 'ic_menu')
]
});
return viewModel;
}
module.exports = SearchViewModel;
I cannot understand the error screen displayed to me on my device ( I am testing on an Android device ).
Does anyone see where I am going wrong? Any pointers would be greatly appreciated.
Thank you.
You can use <DockLayout> to achieve the same without using any plugin.
<DockLayout height="100%">
<!-- bottom navigation buttons -->
<StackLayout dock="bottom" height="50" class="bottom-navigation" orientation="horizontal">
<Button text="Home"/>
<Button text="Accounts"/>
<Button text="Programs"/>
</StackLayout>
<!-- other top content -->
<Button dock="top" text="Other Content"/>
</DockLayout>
then use CSS to normalize the layout:
.bottom-navigation {
background-color:#54d4aa;
}
.bottom-navigation button {
width: 33.33%;
background-color:#54d4aa;
border-color: transparent;
border-width: 1;
color:white;
}
You can replace <Button> with <StackLayout> to add icon and text.
Playground Demo

How to build a fixed footer in NativeScript-Vue?

I would like to have a fixed footer in a page, but I tried with
<StackLayout>
and a
position: absolute;
bottom: 0;
and in the container parent
position: relative
but nothing happened.
I tried with
<AbsoluteLayout bottom="0">
and nothing happened again.
Someone knows how to do this? Thank you!
The <AbsoluteLayout> places elements absolutely inside it. With NativeScript, we have to use Layout Containers to place elements inside them.
The best layouts to achieve what you want zare:
1) <DockLayout>, e.g.
<DockLayout>
<Label dock="bottom" height="60" backgroundColor="yellow" text="footer"/>
<Label text="rest of the content"/>
</DockLayout>
2) <GridLayout>, e.g.
<GridLayout columns="*, 60">
<Label col="0" text="rest of the content"/>
<Label col="1" text="footer"/>
</GridLayout>
Please study the layout containers documentation.

Text wont show inside a label nested in an AbsoluteLayout

Im building a component to show users profile pictures stacked horizontally.
in a case where user doesn't have a profile photo, his 1st name letter will show in a bubble inside the stack.
Im having difficulty showing the text inside the bubble.
the container for the bubble is a layout with circle class and inside of it a Label containing the text.
Would highly appreciate any help in this regards since it has exhausted me :XXX
code:
<AbsoluteLayout orientation="horizontal" style="background-color: #00fdd6">
<ng-template ngFor let-user [ngForOf]="users|limit:lengthLimit" let-i="index">
<Image *ngIf="user.profile_photo" [src]="getImageUrl(user)" class="img-circle" height="50" width="50"
left="{{stackProfilePhotos(i)}}"></Image>
<RelativeLayout *ngIf="!user.profile_photo" style="border: #0000fe 5px solid; background-color: green;"
class="img-circle" height="100" width="100" top="-25" left="{{stackProfileLetterBubble(i)}}">
<Label text="M" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" TextColor="White" FontSize="24"></Label>
</RelativeLayout>
</ng-template>
Attached a view of the ui

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>

Native Script ScrollView and AbsoluteLayout

Im new to NS and I have a project. I want a Button floating inside a ScrollView.
<ScrollView>
<StackLayout orientation="vertical">
<AbsoluteLayout >
<Button top="0" left="0" right="0" text="Test" style="font-size: 10; margin:5; " />
</AbsoluteLayout>
<Label text="Trending Now: " cssClass="trending-label" />
<Repeater items="{{ categories }}">
<Repeater.itemTemplate>
.
.
.
</Repeater.itemTemplate>
</Repeater>
</StackLayout>
</ScrollView>
But its not working. The Button is also scrolling. I want the Button to be floating on ScrollView. Thank you.
The reason why the button is scrolling together with the other items is that everything is situated in a ScrollView. In order to have only the Label and the Repeater scrolling, the Button should be placed outside of it.
Another thing I have noticed is that on the Button, simultaneously are applied left and right alignment, which might cause a problem.
I made a possible implementation of the float button, which you can check here.

Resources