Is there any way to customize progress bar in Nativescript? - nativescript

I'm looking a way to do this progress bar step, let's say for a registration process.
I tried putting 4 Images and 3 Labels in a row like this
<Page loaded="pageLoaded" xmlns="http://www.nativescript.org/tns.xsd">
<ActionBar title="Register"></ActionBar>
<AbsoluteLayout class="home-panel" width="500" height="65"
borderColor="black" borderWidth="1">
<Image width="50" height="50"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTjuRgmqRR4U-fUyGU1Xf-Y1IEnInqqVtxm9w&usqp=CAU"
left="10" top="5">
</Image>
<Image width="50" height="50"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTjuRgmqRR4U-fUyGU1Xf-Y1IEnInqqVtxm9w&usqp=CAU"
left="100" top="5">
</Image>
<Image width="50" height="50"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTjuRgmqRR4U-fUyGU1Xf-Y1IEnInqqVtxm9w&usqp=CAU"
left="200" top="5">
</Image>
<Image width="50" height="50"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTjuRgmqRR4U-fUyGU1Xf-Y1IEnInqqVtxm9w&usqp=CAU"
left="300" top="5">
</Image>
<Label
style="background-color: green; height: 20; width: 60; border-radius: 50%;"
left="50" top="20"></Label>
<Label
style="background-color: green; height: 20; width: 70; border-radius: 50%;"
left="140" top="20"></Label>
<Label
style="background-color: green; height: 20; width: 70; border-radius: 50%;"
left="240" top="20"></Label>
</AbsoluteLayout>
</Page>
But I'm not a really fan, firstly because using AbsoluteLayout makes it difficult to adapt it on different screens (what if it is a tablet ?)
And secondly it seems to me as ugly workaround, i've been struggling a lot with shapes in nativescript, guess that it is not really friendly.
I wonder if there is a better way to do this ?
Playground Link

I'm not sure if you are using NativeScript core, but the logic is the same.
https://docs.nativescript.org/ui/components/progress
In the docs it shows that the progress bar has a property called called value in which you can put how much is the progress bar set to.
You can control the progress bar with code behind or on the view and hard code it on every page you need.
Example :
<!-- scaleY makes the bar thicker -->
<Progress value="25" maxValue="100" scaleY="15" />

Related

Xamarin form Label can't display Chinese characters in italic

I'm new to Xamarin and was testing Xamarin features. Below is an excerpt from my toy application. As you can see, I tried in two ways to display some Chinese characters in italic.
<Label HorizontalOptions="Center" Grid.Row="2" Margin="20, 20, 20, 0"
VerticalOptions="CenterAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="操舵室操舵室操舵室" FontSize="Medium" FontAttributes="Italic"
TextColor="#777777" />
</FormattedString>
</Label.FormattedText>
</Label>
<Label HorizontalOptions="Center" Grid.Row="3" Margin="20, 20, 20, 0" TextType="Html"
VerticalOptions="CenterAndExpand">
<![CDATA[
<div style="font-size: 14px; color: #777777; font-style: italic;">操舵室操舵室操舵室<span style="color: #277DCA;">操舵室操舵室操舵室</span></div>
]]>
</Label>
However, both the simulator and the physical device display them as normal text (not italic). Below is a snapshot of the simulator.
Why this happens and how can I make these text italic?
Below is the package versions I use.
I test your code, and the label text display Italic when using the first way, but there are some issue using second way to set Italic.
If you want to display html text in label , and set Italic, please using the following code:
<Label
HorizontalOptions="Center"
TextType="Html"
VerticalOptions="CenterAndExpand">
<![CDATA[
This is <i style="font-size: 14px; color: #777777">操舵室操舵室操舵室</i> text.
]]>
</Label>
And I don't have any issue when using the first way to set Italic , please check my screenshot:
This is my sample you can take a look:
https://github.com/CherryBu/LabelItalic-

iOS buttons become unclickable after making a floating layout

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>

In Nativescript how can I achieve a vertically aligned label text using StackLayout

I need something like this:
But this is what I have at the moment:
.rotate {
transform: rotate(-90deg);
font-size: 16px;
color: #FFFFFF;
}
This is my code:
<StackLayout backgroundColor="#3C414B" width="12%" height="100%" horizontalAlignment="center" verticalAlignment="center" (tap)="openDrawer('Right')">
<StackLayout class="rotate" orientation="horizontal">
<Label class="fa" style="margin-right: 10px" text=""></Label>
<Label width="100%" class="" text="New Category" textwrap="false"></Label>
</StackLayout>
</StackLayout>
You will have to set the height explicitly to the width of the element, transform doesn't take care of that by default.
Or you may even consider using an image, here is a related thread from Forums.
It looks like you rotate inner <StackLayout class="rotate" ...>, but it still get width limit of outer <StackLayout width="12%" ...>
Try so:
<StackLayout class="rotate" backgroundColor="#3C414B" width="100%" height="12%" horizontalAlignment="center" verticalAlignment="center">
<StackLayout orientation="horizontal">
<Label class="fa" style="margin-right: 10px" text=""></Label>
<Label text="New Category" textwrap="false" backgroundColor="yellow"></Label>
</StackLayout>
</StackLayout>
Or try to find solution with other layout type. For example, AbsoluteLayout

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>

Binding to child object

I have the following code(wp7-silverlight). I try to bind a slider to those 2 controls' Angle property, but for some reason the inner control doesn't seems to receive the data, only the parent control. When I put them side by side(not nested), those work properly. Any idea why only the outer control can get the data from the slider?
<rotate:RotatableUserControl Width="400"
Height="400"
x:Name="RotatableUserControl"
Angle="{Binding ElementName=SliderObject, Path=Value}">
<Canvas Background="Red">
<rotate:RotatableUserControl Width="50"
Height="50"
x:Name="childeRotate3"
Angle="{Binding ElementName=SliderObject, Path=Value}">
<Grid Background="Yellow" />
</rotate:RotatableUserControl>
</Canvas>
</rotate:RotatableUserControl>
I am not sure why you can't bind it nested, but you could try to set the canvas Datacontext to the SliderObject and the bind the Value to the nested rotate:RotatableUserControl, that may work!
<rotate:RotatableUserControl Width="400"
Height="400"
x:Name="RotatableUserControl"
Angle="{Binding ElementName=SliderObject, Path=Value}">
<Canvas Background="Red" Datacontext={Binding ElementName=SliderObject, Path=Value}">
<rotate:RotatableUserControl Width="50"
Height="50"
x:Name="childeRotate3"
Angle="{Binding}">
<Grid Background="Yellow" />
</rotate:RotatableUserControl>
</Canvas>
</rotate:RotatableUserControl>

Resources