Skip to content

Latest commit

 

History

History
6081 lines (4544 loc) · 235 KB

ui-and-styling.md

File metadata and controls

6081 lines (4544 loc) · 235 KB
title
UI & Styling

Layout Properties

Margins

The four margin properties (marginTop, marginRight, marginBottom and marginLeft) describe the distance between a view and its parent.

When you set margins through XML, you can choose between the following approaches.

  • Set one value: Provide a single value that will be applied on all sides of the view.
  • Set two values: Provide two values. The first value is applied to the top side, the second value is applied to the right side. Next, the first value is applied to the bottom and the second value to the left side (in that order).
  • Set four values: Provide four values for each margin. The first value is applied to the top, the second value is applied to the right, the third value is applied to the bottom and the fourth value is applied to the left side (in that order).

Paddings

The four padding properties (paddingTop, paddingRight, paddingBottom and paddingLeft) describe the distance between the layout container and its children.

When you set paddings through XML, you can choose between the following approaches.

  • Set one value: Provide a single value that will be applied on all sides of the view.
  • Set two values: Provide two values. The first value is applied to the top side, the second value is applied to the right side. Next, the first value is applied to the bottom and the second value to the left side (in that order).
  • Set four values: Provide four values for each padding. The first value is applied to the top, the second value is applied to the right, the third value is applied to the bottom and the fourth value is applied to the left side (in that order).

Alignments

Layout applies horizontal and vertical alignment only when an element is allocated more size than it needs.

The following table shows the valid values of horizontalAlignment.

Member Description
left The view is aligned to the left of the layout slot of the parent element.
center The view is aligned to the center of the layout slot of the parent element.
right The view is aligned to the right of the layout slot of the parent element.
stretch The view is stretched to fill the layout slot of the parent element; width takes precedence, if set.

The following table shows the valid values of verticalAlignment.

Member Description
top The view is aligned to the top of the layout slot of the parent element.
center The view is aligned to the center of the layout slot of the parent element.
bottom The view is aligned to the bottom of the layout slot of the parent element.
stretch The view is stretched to fill the layout slot of the parent element; height takes precedence, if set.

Percentage Support

NativeScript supports percentage values for width, height and margin. When a layout pass begins, first the percent values are calculated based on parent available size. This means that on vertical StackLayout if you place two Buttons with height='50%' they will get all the available height (e.g., they will fill the StackLayout vertically.). The same applies for margin properties. For example, if you set marginLeft='5%', the element will have a margin that corresponds to 5% of the parent's available width.

iOS Safe Area Support

The iOS Safe Area is a term that Apple introduced in iOS 11. It is the area of the screen that is free to use and won’t be obstructed by hardware and software parts of the system. The safe area is not a constant. It is affected by the notch, the rounded corners of the screen, the status bar and the home indicator, but also from parts of your application like the action bar and the tab bar. To get a better understanding refer to the Apple docs.

Since version 5.0 NativeScript provides a default handling mechanism for the iOS Safe Area. The default behavior is that certain container View components (these that can have children) overflow the safe area and are laid out to the edges of the screen. These container components are:

  • Layouts
  • ListView
  • ScrollView
  • WebView
  • Repeater

Internally, the workflow is as follows:

  1. Measure pass - all components are measured in the safe area portion of the screen.
  2. Layout pass - all components are laid out in full screen, but are inset to the safe area boundaries.
  3. Layout pass - if the component borders the safe area, it is adjusted and expanded to the edges of the screen.

::: tip The above workflow can lead to containers being laid out with a bigger size than initially declared in the markup. You can prevent this behavior by setting the iosOverflowSafeArea property below to false. :::

iosOverflowSafeArea Property

The above default behavior should provide good UX out of the box. Additionally, NativeScript 5.0 exposes a property iosOverflowSafeArea that can control how components handle the iOS Safe Area. Set this property value to true if you want the component to expand to the edges of the screen when it borders the safe area. Set it to false to explicitly prevent this behavior. The default value for container components is true. All other components are considered content that should be constrained to the safe area and default to false.

Layout Containers

AbsoluteLayout

The <AbsoluteLayout> container is the simplest layout container in NativeScript.

<AbsoluteLayout> has the following behavior:

  • Uses a pair of absolute left/top coordinates to position its children.
  • Doesn't enforce any layout constraints on its children.
  • Doesn't resize its children at runtime when its size changes.

Example: a grid-like layout

The following example creates a simple grid. For more information about creating grid layouts, see GridLayout.

<AbsoluteLayout backgroundColor="#3c495e">
  <label
    text="10,10"
    left="10"
    top="10"
    width="100"
    height="100"
    backgroundColor="#43b883"
  />
  <label
    text="120,10"
    left="120"
    top="10"
    width="100"
    height="100"
    backgroundColor="#43b883"
  />
  <label
    text="10,120"
    left="10"
    top="120"
    width="100"
    height="100"
    backgroundColor="#43b883"
  />
  <label
    text="120,120"
    left="120"
    top="120"
    width="100"
    height="100"
    backgroundColor="#43b883"
  />
</AbsoluteLayout>

Example: Overlapping elements

The following example creates a group of overlapping items.

<AbsoluteLayout backgroundColor="#3c495e">
  <label
    text="10,10"
    left="10"
    top="10"
    width="100"
    height="100"
    backgroundColor="#289062"
  />
  <label
    text="30,40"
    left="30"
    top="40"
    width="100"
    height="100"
    backgroundColor="#43b883"
  />
</AbsoluteLayout>

Props

Name Type Description
N/A N/A None.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

When an element is a direct child of <AbsoluteLayout>, you can set the following additional properties.

Name Type Description
top Number Gets or sets the distance, in pixels, between the top edge of the child and the top edge of its parent.
left Number Gets or sets the distance, in pixels, between the left edge of the child and the left edge of its parent.

DockLayout

<DockLayout> is a layout container that lets you dock child elements to the sides or the center of the layout.

<DockLayout> has the following behavior:

  • Uses the dock property to dock its children to the left, right, top, bottom or center of the layout.
    To dock a child element to the center, it must be the last child of the container and you must set the stretchLastChild property of the parent to true.
  • Enforces layout constraints to its children.
  • Resizes its children at runtime when its size changes.

Example: Dock to every side without stretching the last child

The following example creates a frame-like layout consisting of 4 elements, position at the 4 edges of the screen.

<DockLayout stretchLastChild="false" backgroundColor="#3c495e">
  <label text="left" dock="left" width="40" backgroundColor="#43b883" />
  <label text="top" dock="top" height="40" backgroundColor="#289062" />
  <label text="right" dock="right" width="40" backgroundColor="#43b883" />
  <label text="bottom" dock="bottom" height="40" backgroundColor="#289062" />
</DockLayout>

Example: Dock to every side and stretch the last child

The following example shows how stretchLastChild affects the positioning of child elements in a DockLayout container. The last child (bottom) is stretched to take up all the remaining space after positioning the first three elements.

<DockLayout stretchLastChild="true" backgroundColor="#3c495e">
  <label text="left" dock="left" width="40" backgroundColor="#43b883" />
  <label text="top" dock="top" height="40" backgroundColor="#289062" />
  <label text="right" dock="right" width="40" backgroundColor="#43b883" />
  <label text="bottom" dock="bottom" backgroundColor="#1c6b48" />
</DockLayout>

Example: Dock to every side and the center

The following example creates a <DockLayout> of 5 elements. The first four wrap the center element in a frame.

<DockLayout stretchLastChild="true" backgroundColor="#3c495e">
  <label text="left" dock="left" width="40" backgroundColor="#43b883" />
  <label text="top" dock="top" height="40" backgroundColor="#289062" />
  <label text="right" dock="right" width="40" backgroundColor="#43b883" />
  <label text="bottom" dock="bottom" height="40" backgroundColor="#289062" />
  <label text="center" backgroundColor="#1c6b48" />
</DockLayout>

Example: Dock multiple children to the same side

The following example creates a single line of 4 elements that stretch across the entire height and width of the screen.

<DockLayout stretchLastChild="true" backgroundColor="#3c495e">
  <label text="left 1" dock="left" width="40" backgroundColor="#43b883" />
  <label text="left 2" dock="left" width="40" backgroundColor="#289062" />
  <label text="left 3" dock="left" width="40" backgroundColor="#1c6b48" />
  <label text="last child" backgroundColor="#43b883" />
</DockLayout>

Props

Name Type Description
stretchLastChild Boolean Enables or disables stretching the last child to fit the remaining space.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

When an element is a direct child of <DockLayout>, you can set the following additional properties.

Name Type Description
dock String Specifies which side to dock the element to.
Valid values: top, right, bottom, or left.

GridLayout

<GridLayout> is a layout container that lets you arrange its child elements in a table-like manner.

The grid consists of rows, columns, and cells. A cell can span one or more rows and one or more columns. It can contain multiple child elements which can span over multiple rows and columns, and even overlap each other.

By default, <GridLayout> has one column and one row. You can add columns and rows by configuring the columns and the rows properties. In these properties, you need to set the number of columns and rows and their width and height. You set the number of columns by listing their widths, separated by a comma. You set the number of rows by listing their heights, separated by a comma.

You can set a fixed size for column width and row height or you can create them in a responsive manner:

  • An absolute number: Indicates a fixed size.
  • auto: Makes the column as wide as its widest child or makes the row as tall as its tallest child.
  • *: Takes as much space as available after filling all auto and fixed size columns or rows.

See Props for more information.

Example: Grid layout with fixed sizing

The following example creates a simple 2-by-2 grid with fixed column widths and row heights.

<GridLayout columns="115, 115" rows="115, 115">
  <label text="0,0" row="0" col="0" backgroundColor="#43b883" />
  <label text="0,1" row="0" col="1" backgroundColor="#1c6b48" />
  <label text="1,0" row="1" col="0" backgroundColor="#289062" />
  <label text="1,1" row="1" col="1" backgroundColor="#43b883" />
</GridLayout>

Example: Grid layout with star sizing

The following example creates a grid with responsive design, where space is allotted proportionally to child elements.

<GridLayout columns="*, 2*" rows="2*, 3*" backgroundColor="#3c495e">
  <label text="0,0" row="0" col="0" backgroundColor="#43b883" />
  <label text="0,1" row="0" col="1" backgroundColor="#1c6b48" />
  <label text="1,0" row="1" col="0" backgroundColor="#289062" />
  <label text="1,1" row="1" col="1" backgroundColor="#43b883" />
</GridLayout>

Example: Grid layout with fixed and auto sizing

The following example create a grid with one auto-sized column and one column with fixed size. Rows have a fixed height.

<GridLayout columns="80, auto" rows="80, 80" backgroundColor="#3c495e">
  <label text="0,0" row="0" col="0" backgroundColor="#43b883" />
  <label text="0,1" row="0" col="1" backgroundColor="#1c6b48" />
  <label text="1,0" row="1" col="0" backgroundColor="#289062" />
  <label text="1,1" row="1" col="1" backgroundColor="#43b883" />
</GridLayout>

Example: Grid layout with mixed sizing and merged cells

The following example creates a complex grid with responsive design, mixed width and height settings, and some merged cells.

<GridLayout columns="40, auto, *" rows="40, auto, *" backgroundColor="#3c495e">
  <label text="0,0" row="0" col="0" backgroundColor="#43b883" />
  <label text="0,1" row="0" col="1" colSpan="2" backgroundColor="#1c6b48" />
  <label text="1,0" row="1" col="0" rowSpan="2" backgroundColor="#289062" />
  <label text="1,1" row="1" col="1" backgroundColor="#43b883" />
  <label text="1,2" row="1" col="2" backgroundColor="#289062" />
  <label text="2,1" row="2" col="1" backgroundColor="#1c6b48" />
  <label text="2,2" row="2" col="2" backgroundColor="#43b883" />
</GridLayout>

Props

Name Type Description
columns String A string value representing column widths delimited with commas.
Valid values: an absolute number, auto, or *.
A number indicates an absolute column width. auto makes the column as wide as its widest child. * makes the column occupy all available horizontal space. The space is proportionally divided over all star-sized columns. You can set values such as 3* and 5* to indicate a ratio of 3:5 in sizes.
rows String A string value representing row heights delimited with commas.
Valid values: an absolute number, auto, or *.
A number indicates an absolute row height. auto makes the row as tall as its tallest child. * makes the row occupy all available vertical space. The space is proportionally divided over all star-sized rows. You can set values such as 3* and 5* to indicate a ratio of 3:5 in sizes.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

When an element is a direct child of <GridLayout>, you can work with the following additional properties.

Name Type Description
row Number Specifies the row for this element. Combined with a col property, specifies the cell coordinates of the element.
The first row is indicated by 0.
col Number Specifies the column for the element. Combined with a row property, specifies the cell coordinates of the element.
The first column is indicated by 0.
rowSpan Number Specifies the number of rows which this element spans across.
colSpan Number Specifies the number of columns which this element spans across.

StackLayout

<StackLayout> is a layout container that lets you stack the child elements vertically (default) or horizontally.

::: danger Important Try not to nest too many <StackLayout/> in your markup. If you find yourself nesting a lot of <StackLayout> you will likely get better performance by switching to a <GridLayout> or <FlexboxLayout>. See Layout Nesting for more information. :::

Example: Default stacking

The following example creates a vertical stack of 3 equally-sized elements. Items are stretched to cover the entire width of the screen. Items are placed in the order they were declared in.

<StackLayout backgroundColor="#3c495e">
  <label text="first" height="70" backgroundColor="#43b883" />
  <label text="second" height="70" backgroundColor="#289062" />
  <label text="third" height="70" backgroundColor="#1c6b48" />
</StackLayout>

Example: Horizontal stacking

The following example creates a horizontal stack of 3 equally-sized elements. Items are stretched to cover the entire height of the screen. Items are placed in the order they were declared in.

<StackLayout orientation="horizontal" backgroundColor="#3c495e">
  <label text="first" width="70" backgroundColor="#43b883" />
  <label text="second" width="70" backgroundColor="#289062" />
  <label text="third" width="70" backgroundColor="#1c6b48" />
</StackLayout>

Example: Stack layout with horizontally aligned children

The following example creates a diagonal stack of items with responsive sizes. Items are vertically stacked.

<StackLayout backgroundColor="#3c495e">
  <label
    text="left"
    horizontalAlignment="left"
    width="33%"
    height="70"
    backgroundColor="#43b883"
  />
  <label
    text="center"
    horizontalAlignment="center"
    width="33%"
    height="70"
    backgroundColor="#289062"
  />
  <label
    text="right"
    horizontalAlignment="right"
    width="33%"
    height="70"
    backgroundColor="#1c6b48"
  />
  <label
    text="stretch"
    horizontalAlignment="stretch"
    height="70"
    backgroundColor="#43b883"
  />
</StackLayout>

Example: Horizontal stack layout with vertically aligned children

The following example creates a diagonal stack of items with responsive sizes. Items are horizontally stacked.

<StackLayout orientation="horizontal" backgroundColor="#3c495e">
  <label
    text="top"
    verticalAlignment="top"
    width="70"
    height="33%"
    backgroundColor="#43b883"
  />
  <label
    text="center"
    verticalAlignment="center"
    width="70"
    height="33%"
    backgroundColor="#289062"
  />
  <label
    text="bottom"
    verticalAlignment="bottom"
    width="70"
    height="33%"
    backgroundColor="#1c6b48"
  />
  <label
    text="stretch"
    verticalAlignment="stretch"
    width="70"
    backgroundColor="#43b883"
  />
</StackLayout>

Props

Name Type Description
orientation String Specifies the stacking direction.
Valid values: vertical and horizontal.
Default value: vertical.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

None.

RootLayout

<RootLayout> is a layout container designed to be used as the primary root layout container for your app with a built in api to easily control dynamic view layers. It extends a GridLayout so has all the features of a grid but enhanced with additional apis.

It's api can be observed here:

export class RootLayout extends GridLayout {
  open(view: View, options?: RootLayoutOptions): Promise<void>
  close(view: View, exitTo?: TransitionAnimation): Promise<void>
  bringToFront(view: View, animated?: boolean): Promise<void>
  closeAll(): Promise<void>
  getShadeCover(): View
}

export function getRootLayout(): RootLayout

export interface RootLayoutOptions {
  shadeCover?: ShadeCoverOptions
  animation?: {
    enterFrom?: TransitionAnimation
    exitTo?: TransitionAnimation
  }
}

export interface ShadeCoverOptions {
  opacity?: number
  color?: string
  tapToClose?: boolean
  animation?: {
    enterFrom?: TransitionAnimation // only applied if first one to be opened
    exitTo?: TransitionAnimation // only applied if last one to be closed
  }
  ignoreShadeRestore?: boolean
}

export interface TransitionAnimation {
  translateX?: number
  translateY?: number
  scaleX?: number
  scaleY?: number
  rotate?: number // in degrees
  opacity?: number
  duration?: number // in milliseconds
  curve?: any // CoreTypes.AnimationCurve (string, cubicBezier, etc.)
}

You can use getRootLayout() to get a reference to the root layout in your app from anywhere.

Example: RootLayout setup

Sample layout:

<RootLayout height="100%" width="100%">
  <GridLayout height="100%">
    <label
      verticalAlignment="center"
      textAlignment="center"
      text="MAIN CONTENT AREA"
    ></label>
  </GridLayout>
</RootLayout>

Sample api usage:

// Open a dynamic popup
const view = this.getPopup('#EA5936', 110, -30)
getRootLayout()
  .open(view, {
    shadeCover: {
      color: '#000',
      opacity: 0.7,
      tapToClose: true
    },
    animation: {
      enterFrom: {
        opacity: 0,
        translateY: 500,
        duration: 500
      },
      exitTo: {
        opacity: 0,
        duration: 300
      }
    }
  })
  .catch(ex => console.error(ex))

// Close the dynamic popup
getRootLayout()
  .close(view, {
    opacity: 0,
    translate: { x: 0, y: -500 }
  })
  .catch(ex => console.error(ex))

function getPopup(color: string, size: number, offset: number): View {
  const layout = new StackLayout()
  layout.height = size
  layout.width = size
  layout.marginTop = offset
  layout.marginLeft = offset
  layout.backgroundColor = color
  layout.borderRadius = 10
  return layout
}

You can play with the toolbox app here

You can also find a more thorough example in this sample repo

WrapLayout

<WrapLayout> is a layout container that lets you position items in rows or columns, based on the orientation property. When the space is filled, the container automatically wraps items onto a new row or column.

Example: Default wrap layout

The following example creates a row of equally-sized items. When the row runs out of space, the container wraps the last item to a new row.

<WrapLayout backgroundColor="#3c495e">
  <label text="first" width="30%" height="30%" backgroundColor="#43b883" />
  <label text="second" width="30%" height="30%" backgroundColor="#1c6b48" />
  <label text="third" width="30%" height="30%" backgroundColor="#289062" />
  <label text="fourth" width="30%" height="30%" backgroundColor="#289062" />
</WrapLayout>

Example: Vertical wrap layout

The following example creates a column of equally-sized items. When the row runs out of space, the container wraps the last item to a new column.

<WrapLayout orientation="vertical" backgroundColor="#3c495e">
  <label text="first" width="30%" height="30%" backgroundColor="#43b883" />
  <label text="second" width="30%" height="30%" backgroundColor="#1c6b48" />
  <label text="third" width="30%" height="30%" backgroundColor="#289062" />
  <label text="fourth" width="30%" height="30%" backgroundColor="#289062" />
</WrapLayout>

Props

Name Type Description
orientation String Specifies the stacking direction.
Valid values: horizontal (arranges items in rows) and vertical (arranges items in columns).
Default value: horizontal.
itemWidth Number Sets the width used to measure and layout each child.
Default value: Number.NaN, which does not restrict children.
itemHeight Number Sets the height used to measure and layout each child.
Default value is Number.NaN, which does not restrict children.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

None.

FlexboxLayout

<FlexboxLayout> is a layout container that provides a non-exact implementation of the CSS Flexbox layout. This layout lets you arrange child components both horizontally and vertically.

Example: Default flex layout

The following example creates a row of three equally-sized elements that span across the entire height of the screen.

<FlexboxLayout backgroundColor="#3c495e">
  <label text="first" width="70" backgroundColor="#43b883" />
  <label text="second" width="70" backgroundColor="#1c6b48" />
  <label text="third" width="70" backgroundColor="#289062" />
</FlexboxLayout>

Example: Column flex layout

The following example creates a column of three equally-sized elements that span across the entire width of the screen.

<FlexboxLayout flexDirection="column" backgroundColor="#3c495e">
  <label text="first" height="70" backgroundColor="#43b883" />
  <label text="second" height="70" backgroundColor="#1c6b48" />
  <label text="third" height="70" backgroundColor="#289062" />
</FlexboxLayout>

Example: Row flex layout with items aligned to flex-start

The following example creates a row of three items placed at the top of the screen. Items are placed in the order they were declared in.

<FlexboxLayout alignItems="flex-start" backgroundColor="#3c495e">
  <label text="first" width="70" height="70" backgroundColor="#43b883" />
  <label text="second" width="70" height="70" backgroundColor="#1c6b48" />
  <label text="third" width="70" height="70" backgroundColor="#289062" />
</FlexboxLayout>

Example: Row flex layout with custom order

The following example creates a row of three items placed at the top of the screen. Items are placed in a customized order.

<FlexboxLayout alignItems="flex-start" backgroundColor="#3c495e">
  <label text="first" order="2" width="70" height="70" backgroundColor="#43b883" />
  <label text="second" order="3" width="70" height="70" backgroundColor="#1c6b48" />
  <label text="third" order="1" width="70" height="70" backgroundColor="#289062" />
</FlexboxLayout>

Example: Row flex layout with wrapping

The following example creates four items with enabled line wrapping. When the row runs out of space, the container wraps the last item on a new line.

<FlexboxLayout flexWrap="wrap" backgroundColor="#3c495e">
  <label text="first" width="30%" backgroundColor="#43b883" />
  <label text="second" width="30%" backgroundColor="#1c6b48" />
  <label text="third" width="30%" backgroundColor="#289062" />
  <label text="fourth" width="30%" backgroundColor="#289062" />
</FlexboxLayout>

Example: Column flex layout with reverse order and items with a different alignSelf

The following example shows how to use:

  • flexDirection to place items in a column, starting from the bottom.
  • justifyContent to create equal spacing between the vertically placed items.
  • alignSelf to modify the position of items across the main axis.
<FlexboxLayout
  flexDirection="column-reverse"
  justifyContent="space-around"
  backgroundColor="#3c495e"
>
  <label text="first" height="70" backgroundColor="#43b883" />
  <label
    text="second"
    alignSelf="center"
    width="70"
    height="70"
    backgroundColor="#1c6b48"
  />
  <label
    text="third\nflex-end"
    alignSelf="flex-end"
    width="70"
    height="70"
    backgroundColor="#289062"
  />
  <label text="fourth" height="70" backgroundColor="#289062" />
</FlexboxLayout>

Props

Name Type Description
flexDirection String Sets the direction for placing child elements in the flexbox container.
Valid values:
row (horizontal, left to right),
row-reverse (horizontal, right to left),
column (vertical, top to bottom), and
column-reverse (vertical, bottom to top).
Default value: row.
flexWrap String Sets whether child elements are forced in a single line or can flow into multiple lines. If set to multiple lines, also defines the cross axis which determines the direction new lines are stacked in.
Valid values:
nowrap (single line which may cause the container to overflow),
wrap (multiple lines, direction is defined by flexDirection),and
wrap-reverse (multiple lines, opposite to the direction defined by flexDirection).
Default value: nowrap.
justifyContent String Sets the alignment of child elements along the main axis. You can use it to distribute leftover space when all the child elements on a line are inflexible or are flexible but have reached their maximum size. You can also use it to control the alignment of items when they overflow the line.
Valid values:
flex-start (items are packed toward the start line),
flex-end (items are packed toward the end line),
center (items are centered along the line),
space-between (items are evenly distributed on the line; first item is on the start line, last item on the end line), and
space-around (items are evenly distributed on the line with equal space around them).
Default value: flex-start.
alignItems String (Android-only) Sets the alignment of child elements along the cross axis on the current line. Acts as justifyContent for the cross axis.
Valid values:
flex-start (cross-start margin edge of the items is placed on the cross-start line),
flex-end (cross-end margin edge of the items is placed on the cross-end line),
center (items are centered оn the cross axis),
baseline (the item baselines are aligned), and
stretch (items are stretched to fill the container but respect min-width and max-width).
Default value: stretch.
alignContent String Sets how lines are aligned in the flex container on the cross axis, similar to how justifyContent aligns individual items within the main axis.
This property has no effect when the flex container has only one line.
Valid values:
flex-start (lines are packed to the start of the container),
flex-end (lines are packed to the end of the container),
center (lines are packed to the center of the container),
space-between (lines are evenly distributed; the first line is at the start of the container while the last one is at the end),
space-around (lines are evenly distributed with equal space between them), and
stretch (lines are stretched to take up the remaining space).
Default value: stretch.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Additional children props

When an element is a direct child of <FlexboxLayout>, you can work with the following additional properties.

Name Type Description
order Number Sets the order in which child element appear in relation to one another.
flexGrow Number Indicates that the child should grow in size, if necessary. Sets how much the child will grow in proportion to the rest of the child elements in the flex container.
flexShrink Number Indicates that the child should shrink when the row runs out of space. Sets how much the flex item will shrink in proportion to the rest of the child elements in the flex container. When not specified, its value is set to 1.
alignSelf String (Android-only) Overrides the alignItems value for the child.
Valid values:
flex-start (cross-start margin edge of the item is placed on the cross-start line),
flex-end (cross-end margin edge of the item is placed on the cross-end line),
center (item is centered on the cross axis),
baseline (the item baselines are aligned), and
stretch (items is stretched to fill the container but respects min-width and max-width).
Default value: stretch.
flexWrapBefore Boolean When true, forces the item to wrap onto a new line. This property is not part of the official Flexbox specification.
Default value: false.

Components

ActionBar

The ActionBar is NativeScript’s abstraction over the Android ActionBar and iOS NavigationBar. It represents a toolbar at the top of the activity window, and can have a title, application-level navigation, as well as other custom interactive items.


Example: Simple ActionBar with title

/// flavor vue

<ActionBar title="ActionBar Title" />

///

/// flavor svelte

<actionBar title="ActionBar Title" />

///

/// flavor plain

<ActionBar title="ActionBar Title" />

///

/// flavor angular

<ActionBar title="ActionBar Title"> </ActionBar>

///

/// flavor react

<actionBar title="ActionBar Title" />

///

Example: ActionBar with custom title view

/// flavor react

<actionBar>
  <stackLayout nodeRole="titleView" orientation="horizontal">
    <image src="res://icon" width={40} height={40} verticalAlignment="center" />
    <label text="NativeScript" fontSize={24} verticalAlignment="center" />
  </stackLayout>
</actionBar>

///

/// flavor vue

<ActionBar>
  <StackLayout orientation="horizontal">
    <image src="res://icon" width="40" height="40" verticalAlignment="center" />
    <label text="ActionBar Title" fontSize="24" verticalAlignment="center" />
  </StackLayout>
</ActionBar>

///

/// flavor plain

<ActionBar>
  <StackLayout orientation="horizontal">
    <Image src="res://icon" width="40" height="40" verticalAlignment="center" />
    <Label text="ActionBar Title" fontSize="24" verticalAlignment="center" />
  </StackLayout>
</ActionBar>

///

/// flavor angular

<ActionBar>
  <StackLayout orientation="horizontal">
    <image src="res://icon" width="40" height="40" verticalAlignment="center"></image>
    <label text="ActionBar Title" fontSize="24" verticalAlignment="center"></label>
  </StackLayout>
</ActionBar>

///

/// flavor svelte

<actionBar>
  <stackLayout orientation="horizontal">
    <image src="res://icon" width="40" height="40" verticalAlignment="center" />
    <label text="ActionBar Title" fontSize="24" verticalAlignment="center" />
  </stackLayout>
</actionBar>

///

Example: ActionBar with ActionItem

The <ActionItem> components are supporting the platform-specific position and systemIcon for iOS and Android.

  • Android sets position via android.position:

    • actionBar: Puts the item in the ActionBar. Action item can be rendered both as text or icon.
    • popup: Puts the item in the options menu. Items will be rendered as text.
    • actionBarIfRoom: Puts the item in the ActionBar if there is room for it. Otherwise, puts it in the options menu.
  • iOS sets position via ios.position:

    • left: Puts the item on the left side of the ActionBar.
    • right: Puts the item on the right side of the ActionBar.

/// flavor svelte

<actionBar title="ActionBar Title">
  <actionItem
    on:tap="{onTapShare}"
    ios.systemIcon="9"
    ios.position="left"
    android.systemIcon="ic_menu_share"
    android.position="actionBar"
  />
  <actionItem
    on:tap="{onTapDelete}"
    ios.systemIcon="16"
    ios.position="right"
    text="delete"
    android.position="popup"
  />
</actionBar>

///

/// flavor vue

<ActionBar title="ActionBar Title">
  <ActionItem
    @tap="onTapShare"
    ios.systemIcon="9"
    ios.position="left"
    android.systemIcon="ic_menu_share"
    android.position="actionBar"
  />
  <ActionItem
    @tap="onTapDelete"
    ios.systemIcon="16"
    ios.position="right"
    text="delete"
    android.position="popup"
  />
</ActionBar>

///

/// flavor react

<actionBar title="ActionBar Title">
  <actionItem
    nodeRole="actionItems"
    onTap={onTapShare}
    ios={{
      systemIcon: 9,
      position: 'left' as const
    }}
    android={{
      systemIcon: 'ic_menu_share' as const,
      position: 'actionBar' as const
    }}
  />
  <actionItem
    nodeRole="actionItems"
    onTap={onTapDelete}
    ios={{
      systemIcon: 16,
      position: 'right' as const
    }}
    android={{
      position: 'popup' as const
    }}
    text="delete"
  />
</actionBar>

///

/// flavor plain

<ActionBar title="ActionBar Title">
  <ActionItem
    tap="onShare()"
    ios.systemIcon="9"
    ios.position="left"
    android.systemIcon="ic_menu_share"
    android.position="actionBar"
  >
  </ActionItem>
  <ActionItem
    text="delete"
    tap="onDelete()"
    ios.systemIcon="16"
    ios.position="right"
    android.position="popup"
  >
  </ActionItem>
</ActionBar>

///

/// flavor angular

<ActionBar title="ActionBar Title">
  <ActionItem
    (tap)="onShare()"
    ios.systemIcon="9"
    ios.position="left"
    android.systemIcon="ic_menu_share"
    android.position="actionBar"
  >
  </ActionItem>
  <ActionItem
    text="delete"
    (tap)="onDelete()"
    ios.systemIcon="16"
    ios.position="right"
    android.position="popup"
  >
  </ActionItem>
</ActionBar>

///

Example: ActionBar with NavigationButton

<NavigationButton> is a UI component that provides an abstraction for the Android navigation button and the iOS back button.

/// flavor vue

<ActionBar title="ActionBar Title">
  <NavigationButton text="Go back" android.systemIcon="ic_menu_back" @tap="goBack" />
</ActionBar>

///

/// flavor react

<actionBar title="ActionBar Title">
  <navigationButton
    nodeRole="navigationButton"
    text="Go back"
    android={{
      position: undefined,
      systemIcon: 'ic_menu_back'
    }}
    onTap={goBack}
  />
</actionBar>

///

/// flavor svelte

<actionBar title="ActionBar Title">
  <navigationButton text="Go back" android.systemIcon="ic_menu_back" on:tap="{goBack}" />
</actionBar>

///

/// flavor plain

<ActionBar title="ActionBar Title">
  <NavigationButton text="Go back" android.systemIcon="ic_menu_back" tap="goBack" />
</ActionBar>

///

/// flavor angular

<ActionBar title="ActionBar Title">
  <NavigationButton
    text="Go back"
    android.systemIcon="ic_menu_back"
    (tap)="goBack()"
  ></NavigationButton>
</ActionBar>

///

:::tip Platform specific behavior

iOS Specific

On iOS the default text of the navigation button is the title of the previous page and the back button is used explicitly for navigation. It navigates to the previous page and does not allow overriding this behavior. If you need to place a custom button on the left side of the <ActionBar> (e.g., to show a Drawer button), you can use an <ActionItem> with ios.position="left".

Android Specific

On Android, you can't add text inside the navigation button. You can use the icon property to set an image (e.g., ~/images/nav-image.png or res:\\ic_nav). You can use android.systemIcon to set one of the system icons available in Android. In this case, there is no default behaviour for NavigationButton tap event, and we should set the callback function, which will be executed. :::

Example: Setting an app icon for Android in ActionBar

/// flavor vue

<ActionBar
  title="ActionBar Title"
  android.icon="res://icon"
  android.iconVisibility="always"
/>

///

/// flavor svelte

<actionBar
  title="ActionBar Title"
  android.icon="res://icon"
  android.iconVisibility="always"
/>

///

/// flavor react

<actionBar
  title="ActionBar Title"
  android={{ icon: 'res://icon', iconVisibility: 'always' }}
/>

///

/// flavor plain

<ActionBar
  title="ActionBar Title"
  android.icon="res://icon"
  android.iconVisibility="always"
/>

///

/// flavor angular

<ActionBar
  title="ActionBar Title"
  android.icon="res://icon"
  android.iconVisibility="always"
>
</ActionBar>

///

Example: Removing the border from ActionBar

By default, a border is drawn at the bottom of the <ActionBar>. In addition to the border, on iOS devices a translucency filter is also applied over the <ActionBar>.

To remove this styling from your app, you can set the flat property to true.

/// flavor vue

<ActionBar title="ActionBar Title" flat="true" />

///

/// flavor svelte

<actionBar title="ActionBar Title" flat="true" />

///

/// flavor react

<actionBar title="ActionBar Title" flat={true} />

///

/// flavor plain

<ActionBar title="ActionBar Title" flat="true" />

///

/// flavor angular

<ActionBar title="ActionBar Title" flat="true"> </ActionBar>

///

Example: Styling ActionBar

To style the <ActionBar>, you can use only background-color and color properties. Alternatively, you can use @nativescript/theme and use the default styles for each different theme. The icon property of ActionItem can use Icon Fonts with the font:// prefix. By setting up this prefix, a new image will be generated, which will be set as an <ActionItem>'s icon resource. While using this functionality, we need to specify the font-size, which will calculate the size of the generated image base on the device's dpi.

/// flavor angular

<!-- The default background-color and color of ActionBar & ActionItem are set through nativescript-theme (if used)-->
<ActionBar title="ActionBar Title">
  <!-- Explicitly hiding the NavigationBar to prevent the default one on iOS-->
  <NavigationButton visibility="collapsed"></NavigationButton>

  <!-- Using the icon property and Icon Fonts -->
  <ActionItem
    position="left"
    icon.decode="font://&#xf0a8;"
    class="fas"
    (tap)="goBack()"
  ></ActionItem>

  <!-- Creating custom views for ActionItem-->
  <ActionItem ios.position="right">
    <GridLayout width="100">
      <button text="Theme" class="-primary -rounded-lg"></button>
    </GridLayout>
  </ActionItem>
</ActionBar>

///

/// flavor plain

<!-- The default background-color and color of ActionBar & ActionItem are set through nativescript-theme (if used)-->
<ActionBar title="ActionBar Title">
  <!-- Explicitly hiding the NavigationBar to prevent the default one on iOS-->
  <NavigationButton visibility="collapsed" />

  <!-- Using the icon property and Icon Fonts -->
  <ActionItem position="left" icon.decode="font://&#xf0a8;" class="fas" tap="goBack" />

  <!-- Creating custom views for ActionItem-->
  <ActionItem ios.position="right">
    <GridLayout width="100">
      <button text="Theme" class="-primary -rounded-lg" />
    </GridLayout>
  </ActionItem>
</ActionBar>

///

:::warning Note In iOS, the color property affects the color of the title and the action items. In Android, the color property affects only the title text. However, you can set the default color of the text in the action items by adding an actionMenuTextColor item in the Android theme (inside App_Resources\Android\values\styles.xml). :::

Properties

ActionBar Properties

Name Type Description
title string Gets or sets the action bar title.
titleView View Gets or sets the title view. When set - replaces the title with a custom view.
flat boolean Removes the border on Android and the translucency on iOS. Default value is false.

ActionItem Properties

Name Type Description
text string Gets or sets the text of the action item.
icon string Gets or sets the icon of the action item. Supports local images (~/), resources (res://) and icon fonts (fonts://)
ios.position enum: left, right Sets the position of the item (default value is left).
android.position enum: actionBar, popup, actionBarIfRoom Sets the position of the item (default value is actionBar).
ios.systemIcon number iOS only Sets the icon of the action item while using UIBarButtonSystemIcon enumeration.
android.systemIcon string Android only Sets a path to a resource icon ( see the list of Android system drawables)

NavigationButton Properties

Name Type Description
text string Gets or sets the text of the action item.
icon string Gets or sets the icon of the action item.

Events

Name Description
loaded Emitted when the view is loaded.
unloaded Emitted when the view is unloaded.
layoutChanged Emitted when the layout bounds of a view changes due to layout processing.

API References

Name Type
ActionBar Module
ActionBar Class
ActionItem Class
ActionItems Class
NavigationButton Class

Native Component

Android iOS
android.widget.Toolbar UIView

See Also

Detailed documentation article about ActionBar functionalities.

Activity-Indicator

<ActivityIndicator> is a UI component that shows a progress indicator signaling to the user of an operation running in the background.


/// flavor plain

<ActivityIndicator
  busy="{{ isBusy }}"
  busyChange="{{ onBusyChanged }}"
  loaded="indicatorLoaded"
/>
import { ActivityIndicator } from '@nativescript/core'

onBusyChanged(args: EventData) {
  const indicator: ActivityIndicator = args.object
  console.log(`indicator.busy changed to: ${indicator.busy}`)
}

///

/// flavor angular

<ActivityIndicator [busy]="isBusy" (busyChange)="onBusyChanged($event)">
</ActivityIndicator>
import { ActivityIndicator } from '@nativescript/core'

onBusyChanged(args: EventData) {
  const indicator: ActivityIndicator = args.object
  console.log(`indicator.busy changed to: ${indicator.busy}`)
}

///

/// flavor vue

<ActivityIndicator busy="true" @busyChange="onBusyChanged" />
export default {
  methods: {
    onBusyChanged(args) {
      const indicator = args.object // ActivityIndicator
      console.log(`indicator.busy changed to: ${indicator.busy}`)
    }
  }
}

///

/// flavor react

<activityIndicator busy={true} />

///

/// flavor svelte

<activityIndicator busy="{true}" on:busyChange="{onBusyChanged}" />
export default {
  methods: {
    onBusyChanged(args) {
      const indicator = args.object // ActivityIndicator
      console.log(`indicator.busy changed to: ${indicator.busy}`)
    }
  }
}

///

Props

Name Type Description
busy Boolean Gets or sets whether the indicator is active. When true, the indicator is active.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
busyChange Emitted when the busy property is changed.

Native component

Android iOS
android.widget.ProgressBar (indeterminate = true) UIActivityIndicatorView

Button

<Button> is a UI component that displays a button which reacts to a user gesture.

For more information about the available gestures, see Gestures in the documentation.


/// flavor plain

<Button text="Tap me!" tap="onTap" />
import { Button } from '@nativescript/core'

export function onTap(args) {
  const button = args.object as Button
  // execute your custom logic here...
}

///

/// flavor angular

<button text="Tap me!" (tap)="onTap($event)"></button>
import { Button, EventData } from '@nativescript/core'

onTap(args: EventData) {
    const button = args.object as Button
    // execute your custom logic here...
}

///

/// flavor vue

<button text="Button" @tap="onButtonTap" />

///

/// flavor svelte

<button text="Button" on:tap="{onButtonTap}" />

///

/// flavor react

import { EventData } from '@nativescript/core'
;<button
  text="Button"
  onTap={(args: EventData) => {
    const button = args.object
  }}
/>

///

Props

Name Type Description
text String Sets the label of the button.
textWrap Boolean Gets or sets whether the widget wraps the text of the label. Useful for longer labels. Default value is false.
isEnabled Boolean Make the button disabled or enabled. A disabled button is unusable and un-clickable. Default value is true.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
tap Emitted when the button is tapped.

Styling the button

If you need to style parts of the text, you can use a combination of a FormattedString and Span elements.

<button>
  <FormattedString>
    <span text="This text has a " />
    <span text="red " style="color: red" />
    <span text="piece of text. " />
    <span text="Also, this bit is italic, " fontStyle="italic" />
    <span text="and this bit is bold." fontWeight="bold" />
  </FormattedString>
</button>

Native component

Android iOS
android.widget.Button UIButton

Date Picker

<DatePicker> is a UI component that lets users select a date from a pre-configured range.

See also: TimePicker.


/// flavor plain

<DatePicker
  year="1980"
  month="4"
  day="20"
  loaded="onDatePickerLoaded"
  date="{{ date }}"
  minDate="{{ minDate }}"
  maxDate="{{ maxDate }}"
/>
import { DatePicker, EventData, Observable, Page } from '@nativescript/core'

export function onNavigatingTo(args: EventData) {
  const page = args.object as Page
  const vm = new Observable()

  // in the following example the DatePicker properties are binded via Observableproperties
  vm.set('minDate', new Date(1975, 0, 29)) // the binded minDate property accepts Date object
  vm.set('maxDate', new Date(2045, 4, 12)) // the binded maxDate property accepts Date object

  page.bindingContext = vm
}

export function onDatePickerLoaded(data: EventData) {
  const datePicker = data.object as DatePicker
  datePicker.on('dateChange', args => {
    console.dir(args)
  })
  datePicker.on('dayChange', args => {
    console.dir(args)
  })
  datePicker.on('monthChange', args => {
    console.dir(args)
  })
  datePicker.on('yearChange', args => {
    console.dir(args)
  })
}

///

/// flavor angular

<DatePicker
  year="1980"
  month="4"
  day="20"
  [minDate]="minDate"
  [maxDate]="maxDate"
  (dateChange)="onDateChanged($event)"
  (dayChange)="onDayChanged($event)"
  (monthChange)="onMonthChanged($event)"
  (yearChange)="onYearChanged($event)"
  (loaded)="onDatePickerLoaded($event)"
  verticalAlignment="center"
>
</DatePicker>
import { Component } from '@angular/core'
import { DatePicker } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class DatePickerUsageComponent {
  minDate: Date = new Date(1975, 0, 29)
  maxDate: Date = new Date(2045, 4, 12)

  onDatePickerLoaded(args) {
    // const datePicker = args.object as DatePicker;
  }

  onDateChanged(args) {
    console.log('Date New value: ' + args.value)
    console.log('Date value: ' + args.oldValue)
  }

  onDayChanged(args) {
    console.log('Day New value: ' + args.value)
    console.log('Day Old value: ' + args.oldValue)
  }

  onMonthChanged(args) {
    console.log('Month New value: ' + args.value)
    console.log('Month Old value: ' + args.oldValue)
  }

  onYearChanged(args) {
    console.log('Year New value: ' + args.value)
    console.log('Year Old value: ' + args.oldValue)
  }
}

///

/// flavor vue

<DatePicker :date="someDate" />

<DatePicker> provides two-way data binding using v-model.

<DatePicker v-model="selectedDate" />

///

/// flavor react

import { EventData } from '@nativescript/core'
;<datePicker
  date={new Date()}
  onDateChange={(args: EventData) => {
    const datePicker = args.object
  }}
/>

///

/// flavor svelte

<datePicker date="{someDate}" />

<datePicker> provides two-way data binding using bind.

<datePicker bind:date="{selectedDate}" />

///

Props

Name Type Description
date Date Gets or sets the complete date.
minDate Date Gets or sets the earliest possible date to select.
maxDate Date Gets or sets the latest possible date to select.
day Number Gets or sets the day.
month Number Gets or sets the month.
year Number Gets or sets the year.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
dateChange Emitted when the selected date changes.

Native component

Android iOS
android.widget.DatePicker UIDatePicker

Frame

<Frame> is a UI component used to display <Page> elements. Every app needs at least a single <Frame> element, usually set as the root element.


A single root Frame

/// flavor

new Vue({
  render: h => h('Frame', [h(HomePageComponent)])
})

///

Multiple Frames

If you need to create multiple frames, you can do so by wrapping them in a Layout, for example if you want to have 2 frames side-by-side

/// flavor vue

<GridLayout columns="*, *">
  <frame col="0" />
  <frame col="1" />
</GridLayout>

///

/// flavor react

<gridLayout columns={'* *'} rows={[]}>
  <frame col={0} />
  <frame col={1} />
</gridLayout>

///

/// flavor svelte

<gridLayout columns="*, *">
  <frame col="0" />
  <frame col="1" />
</gridLayout>

///

Example: A frame with a default page

/// flavor vue

<frame>
  <Page>
    <ActionBar title="Default Page Title" />
    <GridLayout>
      <label text="Default Page Content" />
    </GridLayout>
  </Page>
</frame>

///

/// flavor react

<frame>
  <page>
    <actionBar title="Default Page Title" />
    <gridLayout>
      <label text="Default Page Content" />
    </gridLayout>
  </page>
</frame>

///

/// flavor svelte

<frame>
  <page>
    <actionBar title="Default Page Title" />
    <gridLayout>
      <label text="Default Page Content" />
    </gridLayout>
  </page>
</frame>

///

Example: A frame with a default page from an external component

/// flavor vue

<frame>
  <Page>
    <Home />
  </Page>
</frame>
import Home from './Home'

export default {
  components: {
    Home
  }
}

///

/// flavor svelte

<frame>
  <Home />
</frame>
import Home from './Home.svelte'

///

/// flavor react

import HomePage from './HomePage'

function AppContainer() {
  return (
    <frame>
      <HomePage />
    </frame>
  )
}

///

Native component

Android iOS
org.nativescript.widgets.ContentLayout UINavigationController

HtmlView

<HtmlView> is a UI component that lets you show static HTML content.

See also: WebView.


/// flavor plain

<HtmlView loaded="onHtmlLoaded" />
import { HtmlView } from '@nativescript/core'

export function onHtmlLoaded(args) {
  const myHtmlView = args.object as HtmlView
  myHtmlView.html = `<span>
        <h1><font color=\"blue\">NativeScript HtmlView</font></h1></br>
        <h3>This component accept simple HTML strings</h3></span>`
}

///

/// flavor angular

<HtmlView [html]="htmlString"></HtmlView>
import { Component } from '@angular/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class HtmlViewUsageComponent {
  htmlString: string

  constructor() {
    this.htmlString = `<span>
                          <h1>HtmlView demo in <font color="blue">NativeScript</font> App</h1>
                        </span>`
  }
}

///

/// flavor vue

<HtmlView html="<div><h1>HtmlView</h1></div>" />

///

/// flavor react

<htmlView html="<div><h1>HtmlView</h1></div>" />

///

/// flavor svelte

<htmlView html="<div><h1>HtmlView</h1></div>" />

///

Props

Name Type Description
html String The HTML content to be shown.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Native component

Android iOS
android.widget.TextView UITextView

Image

<Image> is a UI component that shows an image from an ImageSource or from a URL.

::: tip Tip When working with images following the best practices is a must. :::


Example: Displaying an image from App_Resources

/// flavor plain

<Image src="res://icon" stretch="aspectFill" />

///

/// flavor angular

<image src="res://icon" stretch="aspectFill"> </image>

///

/// flavor react

<image src="res://icon" stretch="aspectFill" />

///

/// flavor vue

<image src="res://icon" stretch="aspectFill" />

///

/// flavor svelte

<image src="res://icon" stretch="aspectFill" />

///

Example: Displaying an image relative to the app directory

/// flavor plain

<Image src="~/logo.png" stretch="aspectFill" />

///

/// flavor angular

<image src="~/logo.png" stretch="aspectFill"></image>

///

/// flavor react

<image src="~/logo.png" stretch="aspectFill" />

///

/// flavor vue

<image src="~/logo.png" stretch="aspectFill" />

///

/// flavor svelte

<image src="~/logo.png" stretch="aspectFill" />

///

Example: Displaying an image from a URL

:::tip Note

Setting loadMode to async will prevent freezing the UI on Android when loading photos async (e.g. from online API)

:::

/// flavor plain

<Image
  src="https://art.nativescript.org/logo/export/NativeScript_Logo_Blue_White.png"
  stretch="aspectFill"
/>

///

/// flavor angular

<image
  src="https://art.nativescript.org/logo/export/NativeScript_Logo_Blue_White.png"
  stretch="aspectFill"
>
</image>

///

/// flavor react

<image
  src="https://art.nativescript.org/logo/export/NativeScript_Logo_Blue_White.png"
  stretch="aspectFill"
/>

///

/// flavor vue

<image
  src="https://art.nativescript.org/logo/export/NativeScript_Logo_Blue_White.png"
  stretch="aspectFill"
/>

///

/// flavor svelte

<image
  src="https://art.nativescript.org/logo/export/NativeScript_Logo_Blue_White.png"
  stretch="aspectFill"
/>

///

Example: Displaying a base64-encoded image

/// flavor plain

<Image src="data:Image/png;base64,iVBORw..." stretch="aspectFill" />

///

/// flavor angular

<image src="data:Image/png;base64,iVBORw..." stretch="aspectFill"></image>

///

/// flavor react

<image src="data:Image/png;base64,iVBORw..." stretch="aspectFill" />

///

/// flavor vue

<image src="data:Image/png;base64,iVBORw..." stretch="aspectFill" />

///

/// flavor svelte

<image src="data:Image/png;base64,iVBORw..." stretch="aspectFill" />

///

Example: Image with CSS and an icon fonts

/// flavor plain

<Image src="font://&#xf004;" class="fas" />

///

/// flavor angular

<image src="font://&#xf004;" class="fas"></image>

///

/// flavor react

<image src="font://&#xf004;" class="fas" />

///

/// flavor vue

<image src.decode="font://&#xf004;" class="fas" />

:::warning Note

In NativeScript-Vue, .decode is required for parsing properties that have HTML entities in them.

:::

///

/// flavor svelte

<image src="font://&#xf004;" class="fas" />

///

Props

Name Type Description
src String or ImageSource Gets or sets the source of the image as a URL or an image source. If you use the new font:// icon protocol in {N} 6.2, make sure you add .decode to the name of the property - e.g. src.decode="font://&#xf004;"
imageSource ImageSource Gets or sets the image source of the image.
tintColor Color (Style property) Sets a color to tint template images.
stretch Stretch (Style property) Gets or sets the way the image is resized to fill its allocated space.
Valid values: none, aspectFill, aspectFit, or fill.
For more information, see Stretch.
loadMode Gets or sets the loading strategy for the images on the local file system.
Valid values: sync or async.
Default value: async.
For more information, see loadMode.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Native component

Android iOS
android.widget.ImageView UIImageView

Label

<Label> is a UI component that displays read-only text.

::: warning Note This <Label> is not the same as the HTML <label>. :::


Example: Simple label

/// flavor plain

<Label text="Label" />

///

/// flavor angular

<label text="Label"></label>

///

/// flavor react

<label>Label</label>

///

/// flavor vue

<label text="Label" />

///

/// flavor svelte

<label text="Label" />

///

Example: Styling the label

If you need to style parts of the text, you can use a combination of a FormattedString and Span elements.

/// flavor plain

<Label textWrap="true">
  <FormattedString>
    <Span text="This text has a " />
    <Span text="red " style="color: red" />
    <Span text="piece of text. " />
    <Span text="Also, this bit is italic, " fontStyle="italic" />
    <Span text="and this bit is bold." fontWeight="bold" />
  </FormattedString>
</Label>

///

/// flavor angular

<label textWrap="true">
  <FormattedString>
    <span text="This text has a "></span>
    <span text="red " style="color: red"></span>
    <span text="piece of text. "></span>
    <span text="Also, this bit is italic, " fontStyle="italic"></span>
    <span text="and this bit is bold." fontWeight="bold"></span>
  </FormattedString>
</label>

///

/// flavor react

import { Color } from '@nativescript/core'
;<label textWrap={true}>
  <formattedString>
    <span>This text has a </span>
    <span color={new Color('red')}>red </span>
    <span>piece of text. </span>
    <span fontStyle="italic">Also, this bit is italic, </span>
    <span fontWeight="bold">and this bit is bold.</span>
  </formattedString>
</label>

///

/// flavor vue

<label textWrap="true">
  <FormattedString>
    <span text="This text has a " />
    <span text="red " style="color: red" />
    <span text="piece of text. " />
    <span text="Also, this bit is italic, " fontStyle="italic" />
    <span text="and this bit is bold." fontWeight="bold" />
  </FormattedString>
</label>

///

/// flavor svelte

<label textWrap="{true}">
  <formattedString>
    <span text="This text has a " />
    <span text="red " style="color: red" />
    <span text="piece of text. " />
    <span text="Also, this bit is italic, " fontStyle="italic" />
    <span text="and this bit is bold." fontWeight="bold" />
  </formattedString>
</label>

///

Props

Name Type Description
letterSpacing number Gets or sets letterSpace style property.
lineHeight number Gets or sets lineHeight style property.
text string Gets or sets the Label text.
textAlignment initial, left, center, right Gets or sets text-alignment style property.
textDecoration none, underline, line-through, underline, line-through Gets or sets text swcoration style property.
textTransform initial, none, capitalize, uppercase, lowercase Gets or sets text transform style property.
textWrap boolean Gets or sets whether the Label wraps text or not.
whiteSpace initial, normal, nowrap Gets or sets the white space style.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
textChange Emitted when the label text is changed.

Native component

Android iOS
android.widget.TextView UILabel

List Picker

<ListPicker> is a UI component that lets the user select a value from a pre-configured list.


Example: Simple List Picker

/// flavor plain

<ListPicker items="{{ years }}" selectedIndex="0" loaded="onListPickerLoaded" />
import { EventData, fromObject, ListPicker, Page } from '@nativescript/core'

const years = [1980, 1990, 2000, 2010, 2020]

export function onNavigatingTo(args: EventData) {
  const page = <Page>args.object
  const vm = fromObject({
    years: years
  })
  page.bindingContext = vm
}

export function onListPickerLoaded(args) {
  const listPickerComponent = args.object
  listPickerComponent.on('selectedIndexChange', (data: EventData) => {
    const picker = data.object as ListPicker
    console.log(`index: ${picker.selectedIndex}; item" ${years[picker.selectedIndex]}`)
  })
}

///

/// flavor angular

<ListPicker [items]="items" class="picker"> </ListPicker>

///

/// flavor vue

<ListPicker
  :items="listOfItems"
  selectedIndex="0"
  @selectedIndexChange="selectedIndexChanged"
/>

<ListPicker> provides two-way data binding using v-model.

<ListPicker :items="listOfItems" v-model="selectedItem" />

///

/// flavor svelte

<listPicker
  items="{listOfItems}"
  selectedIndex="0"
  on:selectedIndexChange="{selectedIndexChanged}"
/>
let listOfItems = ['one', 'two', 'three']
const selectedIndexChanged = e => console.log(e.index)

<ListPicker> provides two-way data binding for selectedIndex.

<listPicker
  items="{listOfItems}"
  bind:selectedIndex="{selectedItem}"
/>

///

/// flavor react

import { EventData, ListPicker } from '@nativescript/core'
;<listPicker
  items={listOfItems}
  selectedIndex={0}
  onSelectedIndexChange={(args: EventData) => {
    const listPicker: ListPicker = args.object as ListPicker
    const index: number = listPicker.selectedIndex
    const item = listPicker.items[index]
  }}
/>

///

Props

Name Type Description
items Array<String> Gets or sets the items displayed as options in the list picker.
selectedIndex Number Gets or sets the index of the currently selected item.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
selectedIndexChange Emitted when the currently selected option (index) changes. The new index can be retrieved via $event.value.

Native component

Android iOS
android.widget.NumberPicker UIPickerView

ListView

<ListView> is a UI component that shows items in a vertically scrolling list. To set how the list shows individual items, you can use the <v-template> component. Using a ListView requires some special attention due to the complexity of the native implementations, with custom item templates, bindings and so on.

The NativeScript modules provides a custom component which simplifies the way native ListView is used.


::: warning Note The ListView's item template can contain only a single root view container. :::

/// flavor plain

<ListView
  items="{{ titlesArray }}"
  loaded="{{ onListViewLoaded }}"
  itemTap="onItemTap"
  loadMoreItems="onLoadMoreItems"
  separatorColor="orangered"
  rowHeight="50"
  class="list-group"
  id="listView"
>
  <ListView.itemTemplate>
    <!-- The item template can only have a single root view container (e.g. GriLayout, StackLayout, etc.) -->
    <StackLayout class="list-group-item">
      <Label text="{{ title || 'Downloading...' }}" textWrap="true" class="title" />
    </StackLayout>
  </ListView.itemTemplate>
</ListView>
import {
  EventData,
  fromObject,
  ListView,
  ObservableArray,
  ItemEventData,
  Page
} from '@nativescript/core'

export function onNavigatingTo(args: EventData) {
  const page = args.object as Page
  const titlesArray = new ObservableArray([
    { title: 'The Da Vinci Code' },
    { title: 'Harry Potter and the Chamber of Secrets' },
    { title: 'The Alchemist' },
    { title: 'The Godfather' },
    { title: 'Goodnight Moon' },
    { title: 'The Hobbit' }
  ])
  const vm = Observable()
  vm.titlesArray = titlesArray

  page.bindingContext = vm
}

export function onListViewLoaded(args: EventData) {
  const listView = args.object as ListView
}

// The event will be raise when an item inside the ListView is tapped.
export function onItemTap(args: ItemEventData) {
  const index = args.index
  console.log(`Second ListView item tap ${index}`)
}

// The event will be raised when the ListView is scrolled so that the last item is visible.
// This even is intended to be used to add additional data in the ListView.
export function onLoadMoreItems(args: ItemEventData) {
  if (loadMore) {
    console.log('ListView -> LoadMoreItemsEvent')
    setTimeout(() => {
      listArray.push(
        moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
      )
      listArray.push(
        moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
      )
      listArray.push(
        moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
      )
      listArray.push(
        moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
      )
      listArray.push(
        moreListItems.getItem(Math.floor(Math.random() * moreListItems.length))
      )
    }, 3000)

    loadMore = false
  }
}

Properties

Name Type Description
items Array<any> | ItemsSource Gets or set the items collection of the ListView. The items property can be set to an array or an object defining length and getItem(index) method.
itemTemplateSelector function A function that returns the appropriate ket template based on the data item.
itemTemplates Array<KeyedTemplate> Gets or set the list of item templates for the item template selector.
separatorColor string | Color Gets or set the items separator line color of the ListView.
rowHeight Length Gets or set row height of the ListView.
iosEstimatedRowHeight Length Gets or set the estimated height of rows in the ListView. Default value: 44px

///

/// flavor angular

<ListView [items]="items" (itemTap)="onItemTap($event)" class="list-group">
  <ng-template let-item="item" let-i="index" let-odd="odd" let-even="even">
    <!-- The item template can only have a single root view container (e.g. GridLayout, StackLayout, etc.)-->
    <GridLayout>
      <label [text]="item.name" class="list-group-item"></label>
    </GridLayout>
  </ng-template>
</ListView>
import { Component, Injectable, OnInit } from '@angular/core'
import { ItemEventData } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class ListViewUsageComponent implements OnInit {
  items: Array<Item>

  constructor(private _itemService: ItemService) {}

  ngOnInit(): void {
    this.items = this._itemService.getItems()
  }

  onItemTap(args: ItemEventData) {
    console.log(
      `Index: ${args.index}; View: ${args.view} ; Item: ${this.items[args.index]}`
    )
  }
}

@Injectable({
  providedIn: 'root'
})
export class ItemService {
  private items = new Array<Item>(
    { id: 1, name: 'Ter Stegen', role: 'Goalkeeper' },
    { id: 3, name: 'Piqué', role: 'Defender' },
    { id: 4, name: 'I. Rakitic', role: 'Midfielder' },
    { id: 5, name: 'Sergio', role: 'Midfielder' },
    { id: 6, name: 'Denis Suárez', role: 'Midfielder' },
    { id: 7, name: 'Arda', role: 'Midfielder' },
    { id: 8, name: 'A. Iniesta', role: 'Midfielder' },
    { id: 9, name: 'Suárez', role: 'Forward' },
    { id: 10, name: 'Messi', role: 'Forward' },
    { id: 11, name: 'Neymar', role: 'Forward' },
    { id: 12, name: 'Rafinha', role: 'Midfielder' },
    { id: 13, name: 'Cillessen', role: 'Goalkeeper' },
    { id: 14, name: 'Mascherano', role: 'Defender' },
    { id: 17, name: 'Paco Alcácer', role: 'Forward' },
    { id: 18, name: 'Jordi Alba', role: 'Defender' },
    { id: 19, name: 'Digne', role: 'Defender' },
    { id: 20, name: 'Sergi Roberto', role: 'Midfielder' },
    { id: 21, name: 'André Gomes', role: 'Midfielder' },
    { id: 22, name: 'Aleix Vidal', role: 'Midfielder' },
    { id: 23, name: 'Umtiti', role: 'Defender' },
    { id: 24, name: 'Mathieu', role: 'Defender' },
    { id: 25, name: 'Masip', role: 'Goalkeeper' }
  )

  getItems(): Array<Item> {
    return this.items
  }

  getItem(id: number): Item {
    return this.items.filter(item => item.id === id)[0]
  }
}

export class Item {
  constructor(public id: number, public name: string, public role: string) {}
}

Item Templates

<ListView
  [items]="items"
  class="list-group"
  [itemTemplateSelector]="templateSelector"
  row="0"
>
  <ng-template nsTemplateKey="red" let-item="item" let-i="index">
    <GridLayout>
      <label [text]="item.name" backgroundColor="red" color="white"></label>
    </GridLayout>
  </ng-template>

  <ng-template nsTemplateKey="green" let-item="item" let-i="index">
    <GridLayout>
      <label [text]="item.name" backgroundColor="green" color="yellow"></label>
    </GridLayout>
  </ng-template>
</ListView>
import { Component, Input, OnChanges, SimpleChanges, OnInit } from '@angular/core'
import { ItemService, Item } from '../usage/usage.service'
import { ItemEventData } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './tips-and-tricks.component.html'
})
export class ListViewTipsComponent implements OnInit {
  items: Array<Item>

  constructor(private _itemService: ItemService) {}

  ngOnInit(): void {
    this.items = this._itemService.getItems()
  }

  onItemTap(args: ItemEventData) {
    console.log(
      `Index: ${args.index}; View: ${args.view} ; Name: ${this.items[args.index].name}`
    )
  }

  templateSelector(item: Item, index: number, items: any) {
    return index % 2 === 0 ? 'red' : 'green'
  }
}

Properties

| Name | Type | Description | | ----------------------- | ---------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | items | Array<any> | ItemsSource | Gets or set the items collection of the ListView. The items property can be set to an array or an object defining length and getItem(index) method. | | itemTemplateSelector | function | A function that returns the appropriate key template based on the data item. | | itemTemplates | Array<KeyedTemplate> | Gets or set the list of item templates for the item template selector. | | separatorColor | string | Color | Gets or set the items separator line color of the ListView. | | rowHeight | Length | Gets or set row height of the ListView. | | iosEstimatedRowHeight | Length | Gets or set the estimated height of rows in the ListView. Default value: 44px |

///

/// flavor vue

<ListView for="item in listOfItems" @itemTap="onItemTap">
  <v-template>
    <!-- Shows the list item label in the default color and style. -->
    <label :text="item.text" />
  </v-template>
</ListView>

Using <ListView> with multiple <v-template> blocks

The v-template component is used to define how each list item is shown on the screen.

If you need to visualize one or more list items differently than the rest, you can enclose them in additional <v-template> blocks and use conditions. You can have as many <v-template> blocks as needed within one <ListView>.

<ListView for="item in listOfItems" @itemTap="onItemTap">
  <v-template>
    <label :text="item.text" />
  </v-template>

  <v-template if="$odd">
    <!-- For items with an odd index, shows the label in red. -->
    <label :text="item.text" color="red" />
  </v-template>
</ListView>

When you create conditions for <v-template>, you can use a valid JavaScript expression with the following variables:

  • $index— the index of the current item
  • $eventrue if the index of the current item is even
  • $oddtrue if the index of the current item is odd
  • item— the item of the list (the name corresponds to the iterator in the for property). E.g. if="item.text == 'danger'"

Only the above variables are available in this scope, and currently you do not have access to the component scope (component state, computed properties...).

::: warning Note

An important note about v-for

<ListView> does not loop through list items as you would expect when using a v-for loop. Instead <ListView> only creates the necessary views to display the currently visible items on the screen, and reuses the views that are already off-screen when scrolled. This concept is called view recycling and is commonly used in mobile apps to improve performance. :::

This is important, because you should not use key properties within your v-templates, as they will force the ListView to re-create the views and prevent view recycling from working properly.

To use multiple event listeners within a ListView, you can pass in the current item to the listener with @tap="onTap(item, $event)".

Check out this playground with multiple buttons in each ListView cell

If you only need to handle taps on the whole cell, you can use the itemTap event which contains the index of the tapped item and the actual item from the list.

onItemTap(event) {
  console.log(event.index)
  console.log(event.item)
}

::: warning Note If a v-for is used on a <ListView> a warning will be printed to the console, and it will be converted to the for property. :::

Props

Name Type Description
for String Provides the expression for iterating through the items.
For example:
  • item in listOfItems
  • (item, index) in listOfItems
  • item in [1, 2, 3, 4, 5]
items Array<any> An array of items to be shown in the <ListView>.
This property is only for advanced use. Use the for property instead.
separatorColor Color Sets the separator line color. Set to transparent to remove it.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

todo: cleanup API References

Name Type
@nativescript/core/ui/list-view Module
ListView Class
ItemEventData Interface
ItemsSource Interface
KeyedTemplate Interface

///

::: tip Tip Instead of manually triggering the UI update with the help of ListView's refresh method, NativeScript provides the ObservableArray. Using an ObservableArray for your listview's items source will make its members an observable objects and adding/removing an array item will automatically update the UI. :::

::: danger Important Using the ListView component inside a ScrollView or ScrollView inside the ListView's items can lead to poor performance and can reflect the user experience. To avoid this issue, we should specify the height explicitly for the ListView in the scenario when the ListView is nested in ScrollView and the ScrollView's height - when the component is used inside the ListView.

<ScrollView>
  <StackLayout>
    <ListView height="150" [items]="countries"> ... </ListView>
  </StackLayout>
</ScrollView>

:::

Events

Name Description
itemTap Emitted when an item in the <ListView> is tapped. To access the tapped item, use event.item.

Methods

Name Description
refresh() Forces the <ListView> to reload all its items.
scrollToIndex(index: number) Scrolls the specified item with index into view.
scrollToIndexAnimated(index: number) Scrolls the specified item with index into view with animation.
isItemAtIndexVisible(index: number): boolean Checks if specified item with index is visible.

Native component

Android iOS
android.widget.ListView UITableView

Page

<Page> is a UI component that represents an application screen. NativeScript apps typically consist of one or more <Page> that wrap content such as an <ActionBar> and other UI widgets.


Example: Simple Page

/// flavor svelte

<page>
  <actionBar title="My App" />
  <gridLayout>
    <label text="My Content" />
  </gridLayout>
</page>

///

/// flavor vue

<Page>
  <ActionBar title="My App" />
  <GridLayout>
    <label text="My Content" />
  </GridLayout>
</Page>

///

/// flavor react

<page>
  <actionBar title="My App" />
  <gridLayout>
    <label>My Content</label>
  </gridLayout>
</page>

The special case of the ActionBar child

It doesn't matter whether the <actionBar> is a first child, last child, or middle child of <page>. React NativeScript will automatically detect it using an child instanceof Page check, and set it as the ActionBar for the Page.

:::tip Note You can skip this check by explicitly setting <actionBar nodeRole="actionBar">, but it's not a major performance concern. ::: Any non-ActionBar child will be handled as the content view. Page only supports a single child, so if you want to insert multiple children on the Page (which is normally the case!), you should use a LayoutBase such as GridLayout to enscapsulate them.

:::tip Out of interest You'd expect to be able to set ActionBar as the content view by specifying <actionBar nodeRole="content">, but it's not supported in NativeScript Core, so React NativeScript doesn't support it either! :::

///

/// flavor plain

<Page>
  <ActionBar title="My App" />
  <GridLayout>
    <label text="My Content" />
  </GridLayout>
</Page>

///

Example: Using the loaded event for triggering UI changes

A typical scenario is performing UI changes after the page is loaded. The recommended way to do it is by using the loaded event, triggered by NativeScript when the page is fully loaded:

/// flavor plain

<Page
  loaded="onPageLoaded"
  navigatedFrom="onNavigatedFrom"
  navigatedTo="onNavigatedTo"
  navigatingFrom="onNavigatingFrom"
  navigatingTo="onNavigatingTo"
  unloaded="onUnloaded"
  layoutChanged="onLayoutChanged"
>
  <Page.actionBar>
    <ActionBar title="Page Creation" />
  </Page.actionBar>
  <!-- Each page can have only a single root view -->
  <StackLayout>
    <!-- content here -->
    <Label text="Hello, world!" />
  </StackLayout>
</Page>
import { EventData, Page } from '@nativescript/core'

export function onPageLoaded(args: EventData): void {
  console.log('Page Loaded')
  const page = args.object as Page
}
export function onLayoutChanged(args: EventData) {
  console.log(args.eventName)
  console.log(args.object)
}

export function onNavigatedTo(args: NavigatedData) {
  console.log(args.eventName)
  console.log(args.object)
  console.log(args.context)
  console.log(args.isBackNavigation)
}

export function onNavigatingFrom(args: NavigatedData) {
  console.log(args.eventName)
  console.log(args.object)
  console.log(args.context)
  console.log(args.isBackNavigation)
}

export function onUnloaded(args: EventData) {
  console.log(args.eventName)
  console.log(args.object)
}

export function onNavigatedFrom(args: NavigatedData) {
  console.log(args.eventName)
  console.log(args.object)
  console.log(args.context)
  console.log(args.isBackNavigation)
}

///

/// flavor vue

<Page @loaded="greet">
  <ActionBar title="My App" />
  <GridLayout>
    <label text="My Content" />
  </GridLayout>
</Page>
export default {
  methods: {
    greet() {
      alert('Hello!').then(() => {
        console.log('Dialog closed')
      })
    }
  }
}

::: warning Note Developers coming from a web background would usually reach for the mounted lifecycle hook Vue provides, however in NativeScript the application, and certain elements might not yet be loaded when the mounted hook is executed, thus certain actions such as alerts, dialogs, navigation etc. are not possible inside the mounted hook. To work around this limitation, the loaded event may be used, which only fires after the application is ready. In this case, we are using the loaded event of the <Page> element, but this event is available for all NativeScript elements. :::

///

Props

Name Type Description
actionBarHidden Boolean Shows or hides the <ActionBar> for the page.
Default value: false.
backgroundSpanUnderStatusBar Boolean Gets or sets whether the background of the page spans under the status bar.
Default value: false.
androidStatusBarBackground Color (Android-only) Gets or sets the color of the status bar on Android devices.
enableSwipeBackNavigation Boolean (iOS-only) Gets or sets whether the page can be swiped back on iOS.
Default value: true.
statusBarStyle String Gets or sets the style of the status bar.
Valid values:
light,
dark.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
loaded Emitted after the page has been loaded.
navigatedFrom Emitted after the app has navigated away from the current page.
navigatedTo Emitted after the app has navigated to the current page.
navigatingFrom Emitted before the app has navigated away from the current page.
navigatingTo Emitted before the app has navigated to the current page.

::: warning Note The events loaded, unloaded and layoutChanged are UI component lifecycles events and are universal for all classes that extend the View class (including Page). They can be used with all NativeScript elements (e.g. layouts, buttons, UI plugins, etc.). :::

Native component

Android iOS
org.nativescript.widgets.GridLayout UIViewController

Placeholder

<Placeholder> allows you to add any native widget to your application. To do that, you need to put a Placeholder somewhere in the UI hierarchy and then create and configure the native widget that you want to appear there. Finally, pass your native widget to the event arguments of the creatingView event.


Example: Simple Placeholder

/// flavor plain

<Placeholder creatingView="creatingView" />
import { Utils } from '@nativescript/core'

export function creatingView(args) {
  let nativeView
  if (global.isIOS) {
    // Example with UITextView in iOS
    nativeView = UITextView.new()
    nativeView.text = 'Native View (iOS)'
  } else if (global.isAndroid) {
    // Example with TextView in Android
    nativeView = new android.widget.TextView(Utils.android.getApplicationContext())
    nativeView.setText('Native View (Android)')
  }

  args.view = nativeView
}

///

/// flavor react

import { isIOS, isAndroid } from '@nativescript/core'
;<placeholder
  onCreatingView={() => {
    if (isIOS) {
      // Example with UILabel in iOS
      const nativeView = new UILabel()
      nativeView.text = 'Native View - iOS'
      args.view = nativeView
    } else if (isAndroid) {
      // Example with TextView in Android
      const nativeView = new android.widget.TextView(args.context)
      nativeView.setSingleLine(true)
      nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END)
      nativeView.setText('Native View - Android')
      args.view = nativeView
    } else {
      console.warn(
        'Unsupported platform! Did they finally make NativeScript for desktop?'
      )
    }
  }}
/>

///

/// flavor angular

<Placeholder (creatingView)="creatingView($event)" />
import { Utils, Placeholder } from '@nativescript/core'

function creatingView(args) {
  const placeholder = args.object as Placeholder

  let nativeView
  if (global.isIOS) {
    // Example with UITextView in iOS
    nativeView = UITextView.new()
    nativeView.text = 'Native View (iOS)'
  } else if (global.isAndroid) {
    // Example with TextView in Android
    nativeView = new android.widget.TextView(Utils.android.getApplicationContext())
    nativeView.setText('Native View (Android)')
  }

  placeholder.view = nativeView
}

///

/// flavor vue

<Placeholder @creatingView="creatingView" />
// Example with TextView in Android
methods: {
  creatingView: function(args) {
      const nativeView = new android.widget.TextView(args.context);
      nativeView.setSingleLine(true);
      nativeView.setEllipsize(android.text.TextUtils.TruncateAt.END);
      nativeView.setText("Native View - Android");
      args.view = nativeView;
  }
}
// Example with UILabel in iOS
methods: {
  creatingView: function(args) {
      const nativeView = new UILabel();
      nativeView.text = "Native View - iOS";
      args.view = nativeView;
  }
}

///

Props

Name Type Description
N/A N/A None.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Progress

<Progress> is a UI component that shows a bar to indicate the progress of a task.

See also: ActivityIndicator.


Example: Simple Progress

/// flavor plain

<Progress
  width="100%"
  value="{{ progressValue }}"
  maxValue="{{ progressMaxValue }}"
  loaded="onProgressLoaded"
/>
import { Observable, Page, Progress, PropertyChangeData } from '@nativescript/core'

export function onNavigatingTo(args) {
  const page = args.object as Page
  const vm = new Observable()
  vm.set('progressValue', 10) // Initial value
  vm.set('progressMaxValue', 100) // Maximum value
  // Forcing progress value change (for demonstration)
  setInterval(() => {
    const value = vm.get('progressValue')
    vm.set('progressValue', value + 2)
  }, 300)
  page.bindingContext = vm
}
export function onProgressLoaded(args) {
  const myProgressBar = args.object as Progress
  myProgressBar.on('valueChange', (pargs: PropertyChangeData) => {
    // TIP: args (for valueChange of Progress) is extending EventData with oldValue & value parameters
    console.log(`Old Value: ${pargs.oldValue}`)
    console.log(`New Value: ${pargs.value}`)
  })
}

///

/// flavor angular

<progress value="25" maxValue="100" (valueChanged)="onValueChanged($event)"></progress>
import { Component, OnInit } from '@angular/core'

@Component({
  moduleId: module.id,
  templateUrl: './styling.component.html',
  styleUrls: ['./styling.component.css']
})
export class StylingComponent implements OnInit {
  public progressValue: number

  ngOnInit() {
    this.progressValue = 25
  }
}

///

/// flavor react

function getTaskCompletionPercent() {
  // Just a stub method to illustrate the concept.
  return 10
}

;<progress value={getTaskCompletionPercent()} maxValue={100} />

///

/// flavor vue

<progress :value="currentProgress" />

///

/// flavor svelte

<progress value="{currentProgress}" />

///

Example: Styling Progress

Using backgroundColor (CSS: background-color) & color to change the Progress style.

:::tip Note backgroundColor will work only on iOS; on Android the background will be the color with applied opacity. :::

<progress value="50" maxValue="100" backgroundColor="red" color="green"></progress>
<!-- Using the @nativescript/theme CSS class to change the Progress style -->
<progress value="25" maxValue="100" class="progress"></progress>
Progress {
  color: cyan;
  background-color: green;
}

Props

Name Type Description
value Number Gets or sets the current value of the progress bar. Must be within the range of 0 to maxValue.
maxValue Number Gets or sets the maximum value of the progress bar.
Default value: 100.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
valueChange Emitted when the value property changes.

Native Component

Android iOS
android.widget.ProgressBar (indeterminate = false) UIProgressView

Repeater

The Repeater widget allows you to display a collection of data, which is present in an array.

:::tip Note <Repeater> is only applicable to plain NativeScript apps, most flavors provide directives to loop through arrays like ngFor and v-for. :::


/// flavor plain

<Label row="0" text="Binding the Repeater items property to collection" textWrap="true" />
<Button row="1" text="Add new item" tap="onTap" />
<ScrollView row="2">
    <Repeater  id="firstRepeater" items="{{ myItems }}" />
</ScrollView>
<Label row="3" text="Define the Repeater itemTemplate property" textWrap="true" />
<Button row="4" text="Add new item (Second Repeater)" tap="onSecondTap" />
<ScrollView row="5" orientation="horizontal">
    <Repeater items="{{ mySecondItems }}">
        <Repeater.itemsLayout>
            <StackLayout orientation="horizontal" />
        </Repeater.itemsLayout>
        <Repeater.itemTemplate>
            <Label text="{{ $value }}" margin="10" />
        </Repeater.itemTemplate>
    </Repeater>
</ScrollView>
import { Observable, ObservableArray, Page } from '@nativescript/core'

const colors = ['red', 'green', 'blue']
const secondColorsArray = new ObservableArray(['red', 'green', 'blue'])

export function onNavigatingTo(args) {
  const page = args.object as Page
  const vm = new Observable()

  vm.set('myItems', colors)
  vm.set('mySecondItems', secondColorsArray)
  page.bindingContext = vm
}

///

::: tip Note Changing the array after the repeater is shown will not update the UI. You can force-update the UI using the refresh() method.

When using ObservableArray the repeater will be automatically updated when items are added or removed form the array. :::

API References

Name Type
Repeater Module
Repeater Class

ScrollView

<ScrollView> is a UI component that shows a scrollable content area. Content can be scrolled vertically or horizontally.

It's important to note that <ScrollView> extends ContentView, so it can only have a single child element.


/// flavor plain

<!--
    The default value of the orientation property is 'vertical'.
    The ScrollView also supports 'horizontal' as orientation value
-->
<ScrollView scroll="onScroll">
  <GridLayout rows="200 200 200 200 200 200 200 200 200 200">
    <Label row="0" text="Some row content goes here..." />
    <Label row="1" text="Some row content goes here..." />
    <Label row="2" text="Some row content goes here..." />
    <Label row="3" text="Some row content goes here..." />
    <Label row="4" text="Some row content goes here..." />
    <Label row="5" text="Some row content goes here..." />
    <Label row="6" text="Some row content goes here..." />
    <Label row="7" text="Some row content goes here..." />
    <Label row="8" text="Some row content goes here..." />
    <Label row="9" text="Some row content goes here..." />
  </GridLayout>
</ScrollView>
import { Page, ScrollEventData, ScrollView } from '@nativescript/core'

export function onScroll(args: ScrollEventData) {
  const scrollView = args.object as ScrollView

  console.log('scrollX: ' + args.scrollX)
  console.log('scrollY: ' + args.scrollY)
}

///

/// flavor angular

<ScrollView (scroll)="onScroll($event)">
  <GridLayout rows="200 200 200 200 200 200 200 200 200 200">
    <label row="0" text="Some row content goes here..."></label>
    <label row="1" text="Some row content goes here..."></label>
    <label row="2" text="Some row content goes here..."></label>
    <label row="3" text="Some row content goes here..."></label>
    <label row="4" text="Some row content goes here..."></label>
    <label row="5" text="Some row content goes here..."></label>
    <label row="6" text="Some row content goes here..."></label>
    <label row="7" text="Some row content goes here..."></label>
    <label row="8" text="Some row content goes here..."></label>
    <label row="9" text="Some row content goes here..."></label>
  </GridLayout>
</ScrollView>
import { Component } from '@angular/core'
import { ScrollView, ScrollEventData } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './tips-and-tricks.component.html'
})
export class TipsAndTricksComponent {
  onScroll(args: ScrollEventData) {
    const scrollView = args.object as ScrollView

    console.log('scrollX: ' + args.scrollX)
    console.log('scrollY: ' + args.scrollY)
  }
}

///

/// flavor vue

<ScrollView orientation="horizontal">
  <StackLayout orientation="horizontal">
    <label text="this" />
    <label text="text" />
    <label text="scrolls" />
    <label text="horizontally" />
    <label text="if necessary" />
  </StackLayout>
</ScrollView>

///

/// flavor svelte

<scrollView orientation="horizontal">
  <stackLayout orientation="horizontal">
    <label text="this" />
    <label text="text" />
    <label text="scrolls" />
    <label text="horizontally" />
    <label text="if necessary" />
  </stackLayout>
</scrollView>

///

/// flavor react

<scrollView orientation="horizontal">
  <stackLayout orientation="horizontal">
    <label text="this" />
    <label text="text" />
    <label text="scrolls" />
    <label text="horizontally" />
    <label text="if necessary" />
  </stackLayout>
</scrollView>

///

Props

name type description
orientation String Gets or sets the direction in which the content can be scrolled: horizontal or vertical.
Default value: vertical.
scrollBarIndicatorVisible Boolean Specifies if the scrollbar is visible.
Default value: true.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
scroll Emitted when a scroll event occurs.

Native component

Android iOS
android.view UIScrollView

SearchBar

<SearchBar> is a UI component that provides a user interface for entering search queries and submitting requests to the search provider.


/// flavor plain

<SearchBar
  id="searchBar"
  hint="Enter search term here ..."
  text="{{sbText}}"
  clear="onClear"
  submit="onSubmit"
/>
import { Observable, Page, PropertyChangeData, SearchBar } from '@nativescript/core'

export function onNavigatingTo(args) {
  const page = args.object as Page
  const vm = new Observable()
  vm.set('sbText', '')
  vm.on(Observable.propertyChangeEvent, (propertyChangeData: PropertyChangeData) => {
    if (propertyChangeData.propertyName === 'sbText') {
      const searchBar = propertyChangeData.object as SearchBar
      console.log(`Input changed! New value: ${propertyChangeData.value}`)
    }
  })
  page.bindingContext = vm
}

export function onSubmit(args) {
  const searchBar = args.object as SearchBar
  console.log(`Searching for ${searchBar.text}`)
}

export function onClear(args) {
  const searchBar = args.object as SearchBar
  console.log(`Clear event raised`)
}

///

/// flavor angular

<SearchBar
  hint="Enter search term here ..."
  [text]="searchPhrase"
  (textChange)="onTextChanged($event)"
  (clear)="onClear($event)"
  (submit)="onSubmit($event)"
>
</SearchBar>
import { Component } from '@angular/core'
import { SearchBar } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class UsageComponent {
  searchPhrase: string

  onSubmit(args) {
    const searchBar = args.object as SearchBar
    console.log(`Searching for ${searchBar.text}`)
  }

  onTextChanged(args) {
    const searchBar = args.object as SearchBar
    console.log(`Input changed! New value: ${searchBar.text}`)
  }

  onClear(args) {
    const searchBar = args.object as SearchBar
    console.log(`Clear event raised`)
  }
}

///

/// flavor vue

<SearchBar
  hint="Search hint"
  :text="searchPhrase"
  @textChange="onTextChanged"
  @submit="onSubmit"
/>

<SearchBar> provides two-way data binding using v-model.

<SearchBar v-model="searchQuery" />

///

/// flavor svelte

<searchBar
  hint="Search hint"
  text="{searchQuery}"
  on:textChange="{onTextChanged}"
  on:submit="{onSubmit}"
/>

<SearchBar> provides two-way data binding for text.

<searchBar bind:text="{searchQuery}" />

///

/// flavor react

<searchBar
  hint="Search hint"
  text="searchPhrase"
  onTextChange={onTextChanged}
  onSubmit={onSubmit}
  onClose={onClose}
/>

///

Props

Name Type Description
hint String Gets or sets placeholder text for the input area.
text String Gets or sets the value of the search query.
textFieldBackgroundColor Color Gets or sets the background color of the input area.
textFieldHintColor Color Gets or sets the color of the placeholder text.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

name description
textChange Emitted when the text is changed.
submit Emitted when the search input is submitted.
clear Emitted when the current search input is cleared through the X button in the input area.

Native Component

Android iOS
android.widget.SearchView UISearchBar

SegmentedBar

<SegmentedBar> is a UI bar component that displays a set of buttons for discrete selection. Can show text or images.

As opposed to <TabView>:

  • The position of <SegmentedBar> is not fixed.
  • You can place and style it as needed on the page or inside additional app elements such as hamburger menus.
  • You need to handle the content shown after selection separately.

Example: SegmentedBar with SegmentedBarItem

/// flavor plain

<SegmentedBar>
  <SegmentedBarItem title="First" />
  <SegmentedBarItem title="Second" />
  <SegmentedBarItem title="Third" />
</SegmentedBar>

///

/// flavor angular

<SegmentedBar>
  <SegmentedBarItem title="First"></SegmentedBarItem>
  <SegmentedBarItem title="Second"></SegmentedBarItem>
  <SegmentedBarItem title="Third"></SegmentedBarItem>
</SegmentedBar>

///

/// flavor svelte

<segmentedBar>
  <segmentedBarItem title="First" />
  <segmentedBarItem title="Second" />
  <segmentedBarItem title="Third" />
</segmentedBar>

///

/// flavor react

<segmentedBar>
  <segmentedBarItem title="First" />
  <segmentedBarItem title="Second" />
  <segmentedBarItem title="Third" />
</segmentedBar>

///

/// flavor vue

<SegmentedBar>
  <SegmentedBarItem title="First" />
  <SegmentedBarItem title="Second" />
  <SegmentedBarItem title="Third" />
</SegmentedBar>

///

Example: SegmentedBar with selectedIndex

/// flavor plain

<SegmentedBar row="0" class="m-5" selectedIndex="{{ sbSelectedIndex }}">
  <SegmentedBar.items>
    <SegmentedBarItem title="Item 1" />
    <SegmentedBarItem title="Item 2" />
    <SegmentedBarItem title="Item 3" />
  </SegmentedBar.items>
</SegmentedBar>
import { Observable, Page, PropertyChangeData } from '@nativescript/core'

export function onNavigatingTo(args) {
  const page = args.object as Page
  // set up the SegmentedBar selected index
  const vm = new Observable()
  vm.set('prop', 0)
  vm.set('sbSelectedIndex', 0)
  // handle selected index change
  vm.on(Observable.propertyChangeEvent, (data: PropertyChangeData) => {
    if (data.propertyName === 'sbSelectedIndex') {
      vm.set('prop', data.value)
    }
  })
  page.bindingContext = vm
}

///

/// flavor angular

<SegmentedBar
  [items]="mySegmentedBarItems"
  selectedIndex="0"
  (selectedIndexChanged)="onSelectedIndexChanged($event)"
>
</SegmentedBar>
import { Component, ChangeDetectionStrategy } from '@angular/core'
import {
  SegmentedBar,
  SegmentedBarItem,
  SelectedIndexChangedEventData
} from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BasicSegmentedBarComponent {
  mySegmentedBarItems: Array<SegmentedBarItem> = []

  constructor() {
    for (let i = 1; i < 5; i++) {
      const item = new SegmentedBarItem()
      item.title = 'Item ' + i
      this.mySegmentedBarItems.push(item)
    }
  }

  public onSelectedIndexChanged(args: SelectedIndexChangedEventData) {
    const segmentedBar = args.object as SegmentedBar
    const oldIndex = args.oldIndex
    const newIndex = args.newIndex
  }
}

///

/// flavor vue

<SegmentedBar
  :items="listOfItems"
  selectedIndex="0"
  @selectedIndexChanged="onSelectedIndexChange"
/>

<SegmentedBar> provides two-way data binding using v-model.

<SegmentedBar :items="listOfItems" v-model="selectedItem" />

///

/// flavor svelte

<segmentedBar selectedIndex="0" on:selectedIndexChanged="{onSelectedIndexChange}" />

<segmentedBar> can be populated with {each} block.

<segmentedBar>
  {#each listOfItems as item}
  <segmentedBarItem title="{item}" />
  {/each}
</segmentedBar>
let listOfItems = ['First', 'Second', 'Third']

<segmentedBar> provides two-way data binding of selectedIndex.

<segmentedBar bind:selectedIndex="{selectedItem}" >

///

/// flavor react

<segmentedBar
  items={listOfItems}
  selectedIndex={0}
  selectedIndexChanged={onSelectedIndexChange}
/>

///

Props

Name Type Description
items Array<SegmentedBarItem> An array of items to be displayed in the segmented bar. Represents the button labels or icons of the segmented bar.
The array must be created in advance.
selectedIndex Number Gets or sets the index of the selected item.
selectedBackgroundColor Color (Style property) Gets or sets the background color of the selected item. To set the background color of the entire bar, use backgroundColor.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
selectedIndexChanged Emitted when the an item on the segmented bar is tapped.

Native component

Android iOS
android.widget.TabHost UISegmentedControl

Slider

<Slider> is a UI component that provides a slider control for picking values within a specified numeric range.


Example: Simple Slider

/// flavor plain

<Slider value="10" minValue="0" maxValue="100" loaded="onSliderLoaded" />
import { Slider } from '@nativescript/core'

export function onSliderLoaded(args) {
  const sliderComponent = args.object as Slider
  sliderComponent.on('valueChange', data => {
    console.log(`Slider new value ${data.value}`)
  })
}

///

/// flavor angular

<Slider
  value="10"
  minValue="0"
  maxValue="100"
  (valueChange)="onSliderValueChange($event)"
>
</Slider>
import { Component } from '@angular/core'
import { Slider } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class UsageComponent {
  onSliderValueChange(args) {
    const slider = args.object as Slider
    console.log(`Slider new value ${args.value}`)
  }
}

///

/// flavor vue

<Slider value="80" @valueChange="onValueChanged" />

<Slider> provides two-way data binding using v-model:

<Slider v-model="value" />

///

/// flavor svelte

<slider
  value="80"
  on:valueChange="{onValueChanged}"
/>

<slider> provides two-way data binding of value:

<slider bind:value="{value}" />

///

/// flavor react

<slider value={0} onValueChange={onValueChange} />

///

Props

Name Type Description
value Number Gets or sets the currently selected value of the slider.
Default value: 0.
minValue Number Gets or sets the minimum value of the slider.
Default value: 0.
maxValue Number Gets or sets the maximum value of the slider.
Default value: 100.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
valueChange Emitted when the value of the slider changes.

Native component

Android iOS
android.widget.SeekBar UISlider

Switch

<Switch> is a UI component that lets users toggle between two states.

The default state is false or OFF.


Example: Simple Switch

/// flavor plain

<Switch checked="true" loaded="onSwitchLoaded" />
import { Switch } from '@nativescript/core'

export function onSwitchLoaded(argsloaded) {
  const mySwitch = argsloaded.object as Switch
  mySwitch.on('checkedChange', args => {
    const sw = args.object as Switch
    const isChecked = sw.checked
    console.log(`Switch new value ${isChecked}`)
  })
}

///

/// flavor angular

<Switch checked="true" (checkedChange)="onCheckedChange($event)"> </Switch>
import { Component } from '@angular/core'
import { EventData, Switch } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class BasicSwitchComponent {
  onCheckedChange(args: EventData) {
    const sw = args.object as Switch
    const isChecked = sw.checked // boolean
  }
}

///

/// flavor vue

<Switch checked="true" />

<Switch>provides two-way data binding using v-model.

<Switch v-model="itemEnabled" />

///

/// flavor svelte

<switch
  checked="{true}"
  on:checkedChange="{onCheckedChange}"
/>

<switch>provides two-way data binding for checked.

<switch bind:checked="{switchEnabled}" />

///

/// flavor react

<switch checked={true} />

///

Props

Name Type Description
checked Boolean Gets or sets the value of the switch selection.
Default value: false.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
checkedChange Emitted when the switch selection changes.

Native component

Android iOS
android.widget.Switch UISwitch

TabView

<TabView> is a navigation component that shows content grouped into tabs and lets users switch between tabs.


Example: Simple TabView

/// flavor plain

<TabView
  loaded="onLoaded"
  selectedIndex="{{tabSelectedIndex}}"
  selectedIndexChanged="onSelectedIndexChanged"
  androidTabsPosition="bottom"
  androidOffscreenTabLimit="0"
>
  <TabViewItem title="Profile">
    <StackLayout>
      <Label
        text="{{ tabSelectedIndexResult }}"
        class="h2 m-t-16 text-center"
        textWrap="true"
      />
      <Button text="Change Tab" tap="changeTab" class="btn btn-primary btn-active" />
    </StackLayout>
  </TabViewItem>
  <TabViewItem title="Stats">
    <StackLayout>
      <Label
        text="{{ tabSelectedIndexResult }}"
        class="h2 m-t-16 text-center"
        textWrap="true"
      />
      <Button text="Change Tab" tap="changeTab" class="btn btn-primary btn-active" />
    </StackLayout>
  </TabViewItem>
  <TabViewItem title="Settings">
    <StackLayout>
      <Label
        text="{{ tabSelectedIndexResult }}"
        class="h2 m-t-16 text-center"
        textWrap="true"
      />
      <Button text="Change Tab" tap="changeTab" class="btn btn-primary btn-active" />
    </StackLayout>
  </TabViewItem>
</TabView>
import {
  Dialogs,
  Observable,
  TabView,
  SelectedIndexChangedEventData
} from '@nativescript/core'

export function onLoaded(args) {
  const tabView = args.object as TabView
  const vm = new Observable()
  vm.set('tabSelectedIndex', 0)
  vm.set('tabSelectedIndexResult', 'Profile Tab (tabSelectedIndex = 0 )')

  tabView.bindingContext = vm
}

export function changeTab(args) {
  const vm = args.object.bindingContext
  const tabSelectedIndex = vm.get('tabSelectedIndex')
  if (tabSelectedIndex === 0) {
    vm.set('tabSelectedIndex', 1)
  } else if (tabSelectedIndex === 1) {
    vm.set('tabSelectedIndex', 2)
  } else if (tabSelectedIndex === 2) {
    vm.set('tabSelectedIndex', 0)
  }
}
// displaying the old and new TabView selectedIndex
export function onSelectedIndexChanged(args: SelectedIndexChangedEventData) {
  if (args.oldIndex !== -1) {
    const newIndex = args.newIndex
    const vm = (args.object as TabView).bindingContext
    if (newIndex === 0) {
      vm.set('tabSelectedIndexResult', 'Profile Tab (tabSelectedIndex = 0 )')
    } else if (newIndex === 1) {
      vm.set('tabSelectedIndexResult', 'Stats Tab (tabSelectedIndex = 1 )')
    } else if (newIndex === 2) {
      vm.set('tabSelectedIndexResult', 'Settings Tab (tabSelectedIndex = 2 )')
    }
    Dialogs.alert(
      `Selected index has changed ( Old index: ${args.oldIndex} New index: ${args.newIndex} )`
    ).then(() => {
      console.log('Dialog closed!')
    })
  }
}

///

/// flavor angular

Using a <TabView> inside an Angular app requires some special attention about how to provide title, iconSource and content (view) of the TabViewItem. In a pure NativeScript application TabView has an items property which could be set via XML to an array of <TabViewItem>s (basically, an array of objects with title, view and iconSource properties). However, NativeScript-Angular does not support nested properties in its HTML template, so adding <TabViewItem> to <TabView> is a little bit different. NativeScript-Angular provides a custom Angular directive that simplifies the way native <TabView> should be used. The following example shows how to add a <TabView> to your page (with some clarifications later):

<TabView selectedIndex="0" (selectedIndexChanged)="onSelectedIndexchanged($event)">
  <StackLayout *tabItem="{title: 'First Tab', iconSource: 'res://icon'}">
    <StackLayout>
      <label
        text="First Tab"
        textWrap="true"
        class="m-15 h2 text-left"
        color="blue"
      ></label>
    </StackLayout>
  </StackLayout>
  <StackLayout *tabItem="{title: 'Second Tab', iconSource: 'res://icon'}">
    <StackLayout>
      <label
        text="Second Tab"
        textWrap="true"
        class="m-15 h2 text-left"
        color="blue"
      ></label>
    </StackLayout>
  </StackLayout>
</TabView>

::: warning Note If you have set the iconSource property on a <TabViewItem>, but are not seeing any icons next to the title, this might be because the icon is not present in your App_Resources folder. See the Working with Images article for information on how to add and reference your resource images. :::

///

/// flavor svelte

<tabView selectedIndex="{selectedIndex}" on:selectedIndexChange="{indexChange}">

	<tabViewItem title="Tab 1">
		<label text="Content for Tab 1" />
	</tabViewItem>

	<tabViewItem title="Tab 2">
		<label text="Content for Tab 2" />
	</tabViewItem>

</tabView>
function indexChange(event) {
  let newIndex = event.value
  console.log('Current tab index: ' + newIndex)
}

///

/// flavor vue

<TabView :selectedIndex="selectedIndex" @selectedIndexChange="indexChange">
  <TabViewItem title="Tab 1">
    <label text="Content for Tab 1" />
  </TabViewItem>
  <TabViewItem title="Tab 2">
    <label text="Content for Tab 2" />
  </TabViewItem>
</TabView>
methods: {
  indexChange: function(args) {
      let newIndex = args.value
      console.log('Current tab index: ' + newIndex)
  }
}

///

/// flavor react

import { SelectedIndexChangedEventData } from '@nativescript/core'
;<tabView
  selectedIndex={selectedIndex}
  onSelectedIndexChange={(args: SelectedIndexChangedEventData) => {
    const { oldIndex, newIndex } = args
    console.log(`Changed from tab index ${oldIndex} -> ${newIndex}.`)
  }}
>
  <tabViewItem nodeRole="items" title="Tab 1">
    <label text="Content for Tab 1" />
  </tabViewItem>
  <tabViewItem nodeRole="items" title="Tab 2">
    <label text="Content for Tab 2" />
  </tabViewItem>
</tabView>

///

::: warning Note Currently, TabViewItem expects a single child element. In most cases, you might want to wrap your content in a layout. :::

Example: Adding icons to tabs

/// flavor vue

<TabView :selectedIndex="selectedIndex" iosIconRenderingMode="alwaysOriginal">
  <TabViewItem title="Tab 1" iconSource="~/images/icon.png">
    <label text="Content for Tab 1" />
  </TabViewItem>
  <TabViewItem title="Tab 2" iconSource="~/images/icon.png">
    <label text="Content for Tab 2" />
  </TabViewItem>
</TabView>

///

/// flavor svelte

<tabView selectedIndex="{selectedIndex}" iosIconRenderingMode="alwaysOriginal">
  <tabViewItem title="Tab 1" iconSource="~/images/icon.png">
    <label text="Content for Tab 1" />
  </tabViewItem>
  <tabViewItem title="Tab 2" iconSource="~/images/icon.png">
    <label text="Content for Tab 2" />
  </tabViewItem>
</tabView>

///

/// flavor react

<tabView selectedIndex={selectedIndex} iosIconRenderingMode="alwaysOriginal">
  <tabViewItem nodeRole="items" title="Tab 1" iconSource="~/images/icon.png">
    <label text="Content for Tab 1" />
  </tabViewItem>
  <tabViewItem nodeRole="items" title="Tab 2" iconSource="~/images/icon.png">
    <label text="Content for Tab 2" />
  </tabViewItem>
</tabView>

///

::: tip Tip You can use images for tab icons instead of icon fonts. For more information about how to control the size of icons, see Working with image from resource folders. :::

Styling

The TabView component has the following unique styling properties:

  • tabTextColor (corresponding CSS property tab-text-color ) - Changes the text color for the tabs.

  • selectedTabTextColor (corresponding CSS property selected-tab-text-color ) - Changes the color of the text for the selected tab.

  • tabBackgroundColor (corresponding CSS property tab-background-color) - Sets the background color of the tabs.

  • tabTextFontSize (corresponding CSS property tab-text-font-size) - Sets the font size of the tabs.

  • textTransform (corresponding CSS property text-transform) - Sets the text transform individually for every TabViewItem. Value options: capitalize, lowercase, none, and uppercase.

  • androidSelectedTabHighlightColorandroid specific property (corresponding CSS property android-selected-tab-highlight-color) - Sets the underline color of the tabs in Android.

Props

Name Type Description
selectedIndex Number Gets or sets the currently selected tab. Default is 0.
tabTextColor Color (Style property) Gets or sets the text color of the tabs titles.
tabTextFontSize Color Gets or sets the font size of the tabs titles.
tabBackgroundColor Color (Style property) Gets or sets the background color of the tabs.
selectedTabTextColor Color (Style property) Gets or sets the text color of the selected tab title.
androidTabsPosition String Sets the position of the TabView in Android platform
Valid values: top or bottom.
androidOffscreenTabLimit number Gets or sets the number of tabs that should be retained to either side of the current tab in the view hierarchy in an idle state.
androidSelectedTabHighlightColor Color Gets or sets the color of the horizontal line drawn below the currently selected tab on Android.
iosIconRenderingMode automatic, alwaysOriginal, alwaysTemplate Gets or sets the icon rendering mode on iOS.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

TabViewItem Properties

Name Type Description
title string Gets or sets the title of the tab strip entry.
iconSource string Gets or sets the icon source of the tab strip entry. Supports local image paths (~), resource images (res://) and icon fonts (font://)

Events

Name Description
selectedIndexChange Emits an event object containing an newIndex property with the index of the tapped <TabViewItem> (and an oldIndex property with the index of the previous tab).

Native component

Android iOS
android.support.v4.view.ViewPager UITabBarController

TextField

<TextField> is an input component that creates an editable single-line box.

<TextField> extends TextBase and EditableTextBase which provide additional properties and events.


/// flavor plain

<TextField hint="Enter text" color="orangered" backgroundColor="lightyellow" />

///

/// flavor angular

<TextField
  hint="Enter Date"
  secure="false"
  keyboardType="datetime"
  returnKeyType="done"
  autocorrect="false"
  maxLength="10"
  [text]="name"
  (returnPress)="onReturnPress($event)"
  (focus)="onFocus($event)"
  (blur)="onBlur($event)"
>
</TextField>
import { Component } from '@angular/core'
import { TextField, Utils } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class UsageComponent {
  name = ''

  onReturnPress(args) {
    // returnPress event will be triggered when user submits a value
    const textField = args.object as TextField

    // Gets or sets the placeholder text.
    console.log(textField.hint)
    // Gets or sets the input text.
    console.log(textField.text)
    // Gets or sets the secure option (e.g. for passwords).
    console.log(textField.secure)

    // Gets or sets the soft keyboard type. Options: "datetime" | "phone" | "number" | "url" | "email"
    console.log(textField.keyboardType)
    // Gets or sets the soft keyboard return key flavor. Options: "done" | "next" | "go" | "search" | "send"
    console.log(textField.returnKeyType)
    // Gets or sets the autocapitalization type. Options: "none" | "words" | "sentences" | "allcharacters"
    console.log(textField.autocapitalizationType)

    // Gets or sets a value indicating when the text property will be updated.
    console.log(textField.updateTextTrigger)
    // Gets or sets whether the instance is editable.
    console.log(textField.editable)
    // Enables or disables autocorrection.
    console.log(textField.autocorrect)
    // Limits input to a certain number of characters.
    console.log(textField.maxLength)

    Utils.setTimeout(() => {
      textField.dismissSoftInput() // Hides the soft input method, ususally a soft keyboard.
    }, 100)
  }

  onFocus(args) {
    // focus event will be triggered when the users enters the TextField
    const textField = args.object as TextField
  }

  onBlur(args) {
    // blur event will be triggered when the user leaves the TextField
    const textField = args.object as TextField
  }
}

///

/// flavor vue

<TextField :text="textFieldValue" hint="Enter text..." />

<TextField> provides two-way data binding using v-model.

<TextField v-model="textFieldValue" />

///

/// flavor svelte

<textField text="{textFieldValue}" hint="Enter text..." />

<textField> provides two-way data binding using bind.

<textField bind:text="{textFieldValue}" />

///

/// flavor react

<textField text={textFieldValue} hint="Enter text..." />

///

Props

Name Type Description
text String Gets or sets the value of the field.
hint String Gets or sets the placeholder text.
isEnabled Boolean Make the field disabled or enabled. Default value is true.
editable Boolean When true, indicates that the user can edit the value of the field.
maxLength Number Limits input to the specified number of characters.
secure Boolean Hides the entered text when true. Use this property to create password input fields.
Default value: false.
keyboardType KeyboardType Shows a custom keyboard for easier text input.
Valid values: datetime, phone, number, url, or email.
returnKeyType ReturnKeyType Gets or sets the label of the return key.
Valid values: done, next, go, search, or send.
autocorrect Boolean Enables or disables autocorrect.
autocapitalizationType AutocapitalizationType Gets or sets the autocapitalization type.
letterSpacing number Gets or sets letter space style property.
lineHeight number Gets or sets line height style property.
textAlignment TextAlignment Gets or sets the text alignment.
textDecoration TextDecoration Gets or sets the text decoration.
textTransform TextTransform Gets or sets the text transform.
whiteSpace WhiteSpace Gets or sets white space style property.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
textChange Emitted when the text changes.
returnPress Emitted when the return key is pressed.
focus Emitted when the field is in focus.
blur Emitted when the field loses focus.

Native component

Android iOS
android.widget.EditText UITextField

TextView

<TextView> is a UI component that shows an editable or a read-only multi-line text container. You can use it to let users type large text in your app or to show longer, multi-line text on the screen.

<TextView> extends TextBase and EditableTextBase which provide additional properties and events.


/// flavor plain

<TextView
  loaded="onTextViewLoaded"
  hint="Enter Date"
  text="{{ viewDate }}"
  secure="false"
  keyboardType="datetime"
  returnKeyType="done"
  autocorrect="false"
  maxLength="10"
/>
import { Observable, Page, TextView } from '@nativescript/core'

export function onNavigatingTo(args) {
  const page = args.object as Page
  const vm = new Observable()
  vm.set('viewDate', '')
  page.bindingContext = vm
}
export function onTextViewLoaded(argsloaded) {
  const textView = argsloaded.object as TextView
  textView.on('focus', args => {
    const view = args.object as TextView
    console.log('On TextView focus')
  })
  textView.on('blur', args => {
    const view = args.object as TextView
    console.log('On TextView blur')
  })
}

///

/// flavor angular

<TextView hint="Enter some text..." [text]="tvtext" (textChange)="onTextChange($event)">
</TextView>
import { Component } from '@angular/core'
import { EventData, TextView } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class UsageComponent {
  tvtext = ''

  onTextChange(args: EventData) {
    const tv = args.object as TextView
    console.log(tv.text)
  }
}

///

/// flavor vue

<TextView text="Multi\nLine\nText" />

<TextView> provides two-way data binding using v-model.

<TextView v-model="textViewValue" />

///

/// flavor svelte

<textView text="Multi\nLine\nText" />

<textView> provides two-way data binding using bind.

<textView bind:text="{textViewValue}" />

///

/// flavor react

<textView text={'Multi\nLine\nText'} />

///

Displaying multi-style text

To apply multiple styles to the text in your <TextView>, you can use <FormattedString>

/// flavor vue

<TextView editable="false">
  <FormattedString>
    <span text="You can use text attributes such as " />
    <span text="bold, " fontWeight="Bold" />
    <span text="italic " fontStyle="Italic" />
    <span text="and " />
    <span text="underline." textDecoration="Underline" />
  </FormattedString>
</TextView>

///

/// flavor svelte

<textView editable="{false}">
  <formattedString>
    <span text="You can use text attributes such as " />
    <span text="bold, " fontWeight="Bold" />
    <span text="italic " fontStyle="Italic" />
    <span text="and " />
    <span text="underline." textDecoration="Underline" />
  </formattedString>
</textView>

///

/// flavor plain

<TextView editable="false">
  <FormattedString>
    <span text="You can use text attributes such as " />
    <span text="bold, " fontWeight="Bold" />
    <span text="italic " fontStyle="Italic" />
    <span text="and " />
    <span text="underline." textDecoration="Underline" />
  </FormattedString>
</TextView>

///

/// flavor angular

<TextView editable="false">
  <FormattedString>
    <span text="You can use text attributes such as "></span>
    <span text="bold, " fontWeight="Bold"></span>
    <span text="italic " fontStyle="Italic"></span>
    <span text="and "></span>
    <span text="underline." textDecoration="Underline"></span>
  </FormattedString>
</TextView>

///

/// flavor react

<textView editable={false}>
  <formattedString>
    <span text="You can use text attributes such as " />
    <span text="bold, " fontWeight="bold" />
    <span text="italic " fontStyle="italic" />
    <span text="and " />
    <span text="underline." textDecoration="underline" />
    <!-- To set text on the <span> element, please do use the `text` prop; it can't safely take text nodes as children! -->
  </formattedString>
</textView>

///

Props

Name Type Description
text String Gets or sets the value of the component.
hint String Gets or sets the placeholder text when the component is editable.
editable Boolean When true, indicates that the user can edit the contents of the container.
maxLength Number Sets the maximum number of characters that can be entered in the container.
keyboardType KeyboardType Shows a custom keyboard for easier text input.
Valid values: datetime, phone, number, url, or email.
returnKeyType Gets or sets the label of the return key. Currently supported only on iOS.
Valid values: done, next, go, search, or send.
autocorrect Boolean Enables or disables autocorrect.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
textChange Emitted when the text changes.
returnPress Emitted when the return key is pressed.
focus Emitted when the container is in focus.
blur Emitted when the container loses focus.

Native component

Android iOS
android.widget.EditText UITextView

TimePicker

<TimePicker> is a UI component that lets users select time.

See also: DatePicker.


/// flavor plain

<TimePicker
  hour="10"
  minute="25"
  loaded="onPickerLoaded"
  row="2"
  col="0"
  colSpan="2"
  class="m-15"
  verticalAlignment="center"
/>
import { TimePicker } from '@nativescript/core'

export function onPickerLoaded(args) {
  const timePicker = args.object as TimePicker

  // Configurable properties of TimePicker
  timePicker.hour = 10
  timePicker.minute = 25
  timePicker.minuteInterval = 5
  timePicker.minHour = 7
  timePicker.maxHour = 11
  timePicker.minMinute = 10
  timePicker.maxMinute = 45
  timePicker.time = new Date()

  // handling 'timeChange' event via code behind
  timePicker.on('timeChange', (data: any) => {
    // data is of type PropertyChangeData
    console.log('Picked TIME: ', data.value)
    console.log('Previous TIME: ', data.oldValue)
  })
}

///

/// flavor angular

<TimePicker
  hour="9"
  minute="25"
  maxHour="23"
  maxMinute="59"
  minuteInterval="5"
  (timeChange)="onTimeChanged($event)"
>
</TimePicker>
import { Component } from '@angular/core'
import { TimePicker } from '@nativescript/core'

@Component({
  moduleId: module.id,
  templateUrl: './usage.component.html'
})
export class UsageComponent {
  todayObj: Date = new Date()

  onTimeChanged(args) {
    const tp = args.object as TimePicker

    const time = args.value
    console.log(`Chosen time: ${time}`)
  }
}

///

/// flavor vue

<TimePicker :hour="selectedHour" :minute="selectedMinute" />

<TimePicker> provides two-way data binding using v-model.

<TimePicker v-model="selectedTime" />

///

/// flavor svelte

<timePicker hour="{selectedHour}" minute="{selectedMinute}" />

<timePicker> provides two-way data binding using bind.

<timePicker bind:time="{selectedTime}" />

///

/// flavor react

<timePicker hour={selectedHour} minute={selectedMinute} />

///

Props

Name Type Description
hour Number Gets or sets the selected hour.
minute Number Gets or sets the selected minute.
time Date Gets or sets the selected time.
minHour Number Gets or sets the minimum selectable hour.
maxHour Number Gets or sets the maximum selectable hour.
minMinute Number Gets or sets the minimum selectable minute.
maxMinute Number Gets or sets the maximum selectable minute.
minuteInterval Number Gets or sets the selectable minute interval. For example: 5 or 15 minutes.
Default value: 1.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
timeChange Emitted when the selected time changes.

Native component

Android iOS
android.widget.TimePicker UIDatePicker

WebView

<WebView> is a UI component that lets you show web content in your app. You can pull and show content from a URL or a local HTML file, or you can render static HTML content.

See also: HtmlView.


/// flavor plain

<WebView row="1" loaded="onWebViewLoaded" id="myWebView" src="{{ webViewSrc }}" />

///

/// flavor angular

<WebView
  [src]="webViewSrc"
  (loadStarted)="onLoadStarted($event)"
  (loadFinished)="onLoadFinished($event)"
>
</WebView>

///

/// flavor vue

<WebView src="http://nativescript-vue.org/" />

<WebView src="~/html/index.html" />

<WebView src="<div><h1>Some static HTML</h1></div>" />

///

/// flavor svelte

<webView src="http://nativescript.org/" />

<webView src="~/html/index.html" />

<webView src="<div><h1>Some static HTML</h1></div>" />

///

/// flavor react

<webView src="http://nativescript.org/" />

<webView src="~/html/index.html" />

<webView src="<div><h1>Some static HTML</h1></div>" />

///

::: tip Tip To be able to use gestures in WebView component on Android, we should first disabled the zoom control. To do that we could access the android property and with the help of setDisplayZoomControls to set this control to false. :::

Props

Name Type Description
src String Gets or sets the displayed web content.
Valid values: an absolute URL, the path to a local HTML file, or static HTML.
...Inherited Inherited Additional inherited properties not shown. Refer to the API Reference

Events

Name Description
loadStarted Emitted when the page has started loading in the <WebView>.
loadFinished Emitted when the page has finished loading in the <WebView>.

Native component

Android iOS
android.webkit.WebView WKWebView

CSS

You change the looks and appearance of views (elements) in a NativeScript application similarly to how you do it in a web application using Cascading Style Sheets (CSS) or changing the style object of the elements in JavaScript. Only a subset of the CSS language is supported.

Similarly to the DOM Style Object, each View instance exposes a style property, which holds all the style properties for the view. When the view is displayed, all its style properties are applied to the underlying native widget.


Supported CSS Properties

This list of properties can be set in CSS or through the style property of each view:

CSS Property JavaScript Property Description
color color Sets a solid-color value to the matched view’s foreground.
background background Sets a solid-color value or a linear gradient to the matched view’s background.
background-color backgroundColor Sets a solid-color value to the matched view’s background.
placeholder-color placeholderColor Sets the placeholder (hint) font color to matched views.
background-image backgroundImage Sets a image url to the matched view’s background image.
background-repeat backgroundRepeat Sets if/how the background image should be repeated. Possible values: repeat, repeat-x, repeat-y, no-repeat
background-position backgroundPosition Sets the starting position of the background image. You can set the position with absolute, percent or alignment values. More info here.
background-size backgroundSize Sets the size of the background image. Possible values: length length, percent% percent%, cover or contain.
border-color borderColor Sets border colors to the matched view’s.
border-top-color borderTopColor Sets a top border color to the matched view’s.
border-right-color borderRightColor Sets a right border color to the matched view’s.
border-bottom-color borderBottomColor Sets a bottom border color to the matched view’s.
border-left-color borderLeftColor Sets a left border color to the matched view’s.
border-width borderWidth Sets border widths to the matched view’s.
border-top-width borderTopWidth Sets a top border width to the matched view’s.
border-right-width borderRightWidth Sets a right border width to the matched view’s.
border-bottom-width borderBottomWidth Sets a bottom border width to the matched view’s.
border-left-width borderLeftWidth Sets a left border width to the matched view’s.
border-radius borderRadius Sets a border radius to the matched view’s.
box-shadow boxShadow Sets a box shadow to the matched view's.
font font Sets the font properties (this includes font-family, font-size, font-style and font-weight) of the matched view.
font-family fontFamily Sets the font family of the matched view.
font-size fontSize Sets the font size of the matched view (only supports device-independent units).
font-style fontStyle Sets the font style of the matched view. Possible values: italic, normal.
font-weight fontWeight Sets the font weight of the matched view Possible values: bold, normal OR 100,200,300,400,500,600,700,800,900, where 400 is normal and 700 is bold (NOTE: Some fonts do not support all available variants)
text-align textAlignment Sets text alignment in the matched view. Possible values: left , center, right.
text-decoration textDecoration Sets the text formatting. Possible values: none, line-through, underline.
text-transform textTransform Sets the text transform. Possible values: none, capitalize, uppercase, lowercase.
letter-spacing letterSpacing Sets the text letter spacing. (On Android API Level 21 and above.)
line-height lineHeight Sets the text line height
z-index zIndex Sets the z-index. (On Android API Level 21 and above.)
clip-path clip-path Sets the clip-path. Supported shapes are circle, ellipse, rect and polygon. You can define your own shape using clippy
vertical-align verticalAlignment Sets the vertical alignment of the current view within its parent. Possible values: top, center, bottom, stretch.
horizontal-align horizontalAlignment Sets the horizontal alignment of the current view within its parent. Possible values: left, center, right, stretch.
margin margin Sets the margin of the view within its parent.
margin-top marginTop Sets the top margin of the view within its parent.
margin-right marginRight Sets the right margin of the view within its parent.
margin-bottom marginBottom Sets the bottom margin of the view within its parent.
margin-left marginLeft Sets the left margin of the view within its parent.
width width Sets the view width.
height height Sets the view height.
min-width minWidth Sets the minimal view width.
min-height minHeight Sets the minimal view height.
padding padding Sets the distance between the boundaries of the layout container and its children.
padding-top paddingTop Sets the top padding of a layout container.
padding-right paddingRight Sets the right padding of a layout container.
padding-bottom paddingBottom Sets the bottom padding of a layout container.
padding-left paddingLeft Sets the left padding of a layout container.
text-shadow textShadow Sets a text shadow on a label.
visibility visibility Sets the view visibility. Possible values: visible, collapse (or collapsed).
opacity opacity Sets the view opacity. The value is in the [0, 1] range.

NativeScript Specific CSS Properties

In the context of mobile development, there are a number of properties that are mobile specific (and sometimes even platform specific e.g Android or iOS). In NativeScript, these featured properties are still accessible through both the code (inline, JavaScript, and TypeScript) but are also exposed as CSS properties. Apart from the API references, the below list is providing most of the non-common CSS properties in NativeScript.

CSS Property JavaScript Property Platform Compatibility Description
tab-text-color tabTextColor Both TabView Sets the text color of the tabs titles.
selected-tab-text-color selectedTabTextColor Both TabView Sets the color of the text, while selecting some of the tabs.
tab-background-color tabBackgroundColor Both TabView Sets the background color of the tabs.
tab-text-font-size tabTextFontSize Both TabView Sets the tab titles font size, without changing the font size of all contents of the tab.
text-transform textTransform Both TabViewItem Sets the text transform individually for every TabViewItem. Value options: capitalize, lowercase, none, and uppercase.
android-selected-tab-highlight-color androidSelectedTabHighlightColor Android TabView Sets the underline color of the tabs in Android.
android-elevation androidElevation Android View Sets the elevation of the View in Android.
android-dynamic-elevation-offset androidDynamicElevationOffset Android View Sets the elevation of the View in Android, which will be shown when an action was performed(e.g. tap, touch).
off-background-color offBackgroundColor Both Switch Sets the background color of the Switch when it is turned off.
highlight-color highlightColor Both TabStrip Gets or sets the underline color of the selected TabStripItem.

::: warning Note Currently, we can set only the backgroundColor, color, fontFamily, fontSize, fontStyle, fontWeight and textTransform styling properties to the Label and Image components inside the TabStripItem. More about the usage of those properties can be found in the Supported CSS Properties section. :::

::: warning Note On iOS, the TabStripItems can not be stylied individually. :::

Using the androidElevation property on Android

Since {N} 5.4, a new Android-specific property, called androidElevation, is introduced. View's elevation is represented by Zproperty and determines the visual appearance of its shadow. With higher elevation value larger, softer shadows will be set to the View and smaller shadow while using lower elevation.

<StackLayout class="home-panel">
  <TextView
    class="tvElevation"
    editable="false"
    textWrap="true"
    text="TextView"
  ></TextView>
  <label androidElevation="5" class="sampleLabel" textWrap="true" text="Label"></label>
  <button androidElevation="7" class="sampleButton" text="Button"></button>
</StackLayout>
.tvElevation {
  android-elevation: 5;
}

::: warning Note Since NativeScript 5.4, the buttons on Android have default elevation (shadow) of 2, to provide Material Design elevation support. Removing the shadow will allow you to create a transparent button. To explicitly remove the elevation, set the android-elevation property to 0 as shown below:

.btn-no-elevation {
  android-elevation: 0;
}

:::

Using the androidDynamicElevationOffset property on Android

Another property introduced with {N} 5.4 is androidDynamicElevationOffset. This property allows setting an elevation, which will be shown when an action was performed. Those actions can be, for example, tap, touch etc.

Example:

<StackLayout class="home-panel">
  <button
    androidElevation="7"
    androidDynamicElevationOffset="8"
    class="sampleButton"
    text="Button"
  ></button>
  <button class="sampleButton2" text="Button"></button>
</StackLayout>
.sampleButton2 {
  background-color: lightcyan;
  android-elevation: 7;
  android-dynamic-elevation-offset: 7;
}

Supported Selectors

::: warning Note Currently the CSS support is limited only to the selectors and properties listed in the current documentation. :::

NativeScript supports a subset of the CSS selector syntax. Here is how to use the supported selectors:

Type Selector

Like CSS element selectors, type selectors in NativeScript select all views of a given type. Type selectors are case insensitive, so you can use both button and Button.

button { background-color: gray }

Class Selector

Class selectors select all views with a given class. The class is set using the className property of the view.

::: warning Note To use className in JS/TS to add a class to an element, the class rule must be in a CSS file that is higher up the component tree than the element, such as app.css. :::

<label className="title"></label>
.title {
  font-size: 32;
}
import { Label } from '@nativescript/core'
const label = new Label()
label.className = 'title'

ID Selector

Id selectors select all views with a given id. The id is set using the id property of the view.

<button id="login-button"></button>
#login-button {
  background-color: blue;
}
import { Button } from '@nativescript/core'
const btn = new Button()
btn.id = 'login-button'

Attribute Selector

<button testAttr="flower"></button>
button[testAttr] {
  background-color: blue;
}

This selector will select all buttons that have the attribute testAttr with some value.

Also, some more advanced scenarios are supported:

  • button[testAttr='flower'] {...} - Will apply CSS on every button that has the testAttr property set exactly to the value flower.
  • button[testAttr~='flower'] {...} - Selects all buttons with a testAttr property that contains a space-separated list of words, one of which is "flower".
  • button[testAttr|='flower'] {...} - Selects all buttons with a testAttr property value that begins with "flower". The value has to be a whole word, either alone like btn['testAttr'] = 'flower', or followed by hyphen (-), like btn['testAttr'] = 'flower-house'.
  • button[testAttr^='flower'] {...} - Selects all buttons with a testAttr property value that begins with "flower". The value does not have to be a whole word.
  • button[testAttr$='flower'] {...} - Selects all buttons with a testAttr property value that ends with "flower". The value does not have to be a whole word.
  • button[testAttr*='flo'] {...} - Selects all buttons with a testAttr property value that contains "flo". The value does not have to be a whole word.

Attribute selectors could be used alone or could be combined with all type of CSS selectors.

<button id="login-button" testAttr="flower"></button>
<label testAttr="some value"></label>
#login-button[testAttr='flower'] {
  background-color: blue;
}
[testAttr] {
  color: white;
}

Pseudo Selector

A pseudo-selector or also pseudo-class is used to define a special state of an element. Currently, NativeScript supports only :highlighted pseudo-selector.

<button testAttr="flower"></button>
button:highlighted {
  background-color: red;
  color: gray;
}

Hierarchical Selector (CSS Combinators)

A CSS selector could contain more than one simple selector, and between selectors a combinator symbol could be included.

  • (space) - Descendant selector. For example, the following code will select all buttons inside StackLayouts (no matter) at which level.
StackLayout Button {
  background-color: blue;
}
  • (>) - A direct child selector. Using the previous example, if the CSS is changed to:
StackLayout > Button {
  background-color: blue;
}

The background-color rule will not be applied. In order to apply the selector, the WrapLayout element would need to be removed so that the Button is a direct child of the StackLayout.

  • (+) - An adjacent sibling selector, allows to select all elements, which are siblings of a specified element.
Direct Sibling Test by Class
<StackLayout class="layout-class">
  <label text="Direct sibling test by id"></label>
  <button class="test-child" text="First Button"></button>
  <button class="test-child-2" text="Second Button"></button>
</StackLayout>
.layout-class .test-child + .test-child-2 {
  background-color: green;
}
Direct Sibling Test by ID
<StackLayout class="layout-class">
  <label text="Direct sibling test by id"></label>
  <button id="test-child" text="First Button"></button>
  <button id="test-child-2" text="Second Button"></button>
</StackLayout>
.layout-class #test-child + #test-child-2 {
  background-color: green;
}
Direct Sibling by Type
<StackLayout class="direct-sibling--type">
  <label text="Direct sibling by type"></label>
  <button text="Test Button"></button>
  <label text="Test Label"></label>
  <button text="Test Button"></button>
  <label text="Test Label"></label>
  <button text="Test Button"></button>
  <label text="Test Label"></label>
</StackLayout>
StackLayout Button + Label {
  background-color: green;
  color: white;
}

CSS Overview


Applying CSS Styles

The CSS styles can be set on 3 different levels:

If there is CSS declared on different levels—all will be applied. The inline CSS will have the highest priority and the application CSS will have the lowest priority.

It is also possible to apply platform-specific CSS.

Application Wide CSS

When the application starts, NativeScript checks if the file app.css exists. If it does, any CSS styles that it contains are loaded and used across all application pages. This file is a convenient place to store styles that will be used on multiple pages.

You can change the name of the file from which the application-wide CSS is loaded. You need to do the change before the application is started, usually in the app.js or app.ts file as shown below:

/// flavor plain

import { Application } from '@nativescript/core'
Application.setCssFileName('style.css')

Application.run({ moduleName: 'main-page' })

///

/// flavor angular

platformNativeScriptDynamic({ bootInExistingPage: false, cssFile: 'style.css' })

///

::: tip Note The path to the CSS file is relative to the application root folder. :::

You could also check the name of the application-wide CSS file by using getCssFileName() method as shown below:

import { Application } from '@nativescript/core'
const fileName = Application.getCssFileName()
console.log(`fileName ${fileName}`)

/// flavor plain

Page Specific CSS

When the page's XML declaration file is loaded, NativeScript looks for a CSS file with the same name (if such exists), reads any CSS styles that it finds, and automatically loads and applies them to the page. For example, a page named mypage.xml will automatically load any CSS in mypage.css. The CSS file must exist in the same folder as the XML file to be automatically applied.

If you import any custom components on your page, the CSS from those components will be applied to the page, too. As a best practice, scope the CSS of custom components so that component styles do not "leak" on to pages.

<StackLayout class="mywidget">
  <Label text="Custom component layout" class="label" />
</StackLayout>
/* GOOD: This will ONLY apply to the custom component */
.mywidget .label {
  color: blue;
}

/* BAD: This will apply to the custom component AND potentially to the page where the component is used */
.label {
  color: blue;
}

You can also override CSS styles specified in the file by using the page's css property:

page.css = 'button { color: red }'

///

/// flavor angular

Component Specific CSS

In an Angular application everything is a component, therefore, it is a very common task to add some CSS code that should only apply to one component. Adding component-specific CSS in a NativeScript-Angular app involves using a component’s styles or styleUrls property.

@Component({
    selector: 'list-test',
    styleUrls: ['style.css'],
    template: ...

// Or

@Component({
    selector: 'list-test',
    styles: ['.third { background-color: lime; }'],
    template: ...

///

Adding CSS String

This snippet adds a new style to the current set of styles. This is quite useful when you need to add a small CSS chunk to an element (for example, for testing purposes):

page.addCss('button {background-color: blue}')

Adding CSS File

This snippet adds new CSS styles to the current set. However, this method reads them from a file. It is useful for organizing styles in files and reusing them across multiple pages.

page.addCssFile(cssFileName)

Inline CSS

Similarly to HTML, CSS can be defined inline for a UI view in the XML markup:

<button text="inline style" style="background-color: green;"></button>

Platform-specific CSS

NativeScript conventions make it easy to apply platform-specific CSS, either via separate stylesheets or via in-line declarations. For an overview of NativeScript's convention-based file name rules for targeting files at specific platforms and screen sizes, refer to this article in the docs.

There are 4 primary ways to target styles at iOS or Android:

/// flavor plain

  1. Platform-specific stylesheets (styles.ios.css, styles.android.css)
  2. Platform-specific markup blocks (<ios> ... </ios>, <android> ... </android>)
  3. Platform-specific attributes (<Label ios:style="..." android:style="...")
  4. Platform-specific CSS rules (.ns-ios .mystyle { ... }, .ns-android .mystyle { ... })

///

/// flavor angular

  1. Platform-specific stylesheets (styles.component.ios.css, styles.component.android.css)
  2. Platform-specific markup blocks (<ios> ... </ios>, <android> ... </android>)
  3. Platform-specific attributes (<Label ios:style="..." android:style="...")
  4. Platform-specific CSS rules (:host-content(.ns-ios) .mystyle { ... }, :host-context(.ns-android) .mystyle { ... })

///

The most common and maintainable pattern for managing platform-agnostic and platform-specific styles in NativeScript is with multiple stylesheets and CSS imports.

/// flavor plain With this pattern, a page has 3 separate stylesheets: common, iOS and Android. For example, for page myPage.xml you would have 3 stylesheets:

  1. myPage-common.css
  2. myPage.ios.css
  3. myPage.android.css

In both myPage.ios.css and myPage.android.css you then import the shared common styles from myPage-common.css:

/* Import shared style rules */
@import './myPage-common.css';

/* Add iOS/Android specific rules (if any) */
.mystyle { ... }

///

/// flavor angular With this pattern, a page (or component) has 3 separate stylesheets: common, iOS and Android. For example, for page home.component.html you would have 3 stylesheets:

  1. home-common.css
  2. home.component.ios.css
  3. home.component.android.css

In both home.component.ios.css and home.component.android.css you then import the shared common styles from home-common.css:

/* Import shared style rules */
@import './home-common.css';

/* Add iOS/Android specific rules (if any) */
.mystyle { ... }

///

At build time, NativeScript will automatically import the common styles and choose the correct iOS or Android stylesheet depending on the target build platform.

Root Views CSS Classes

To allow flexible styling and theming, NativeScript adds a CSS class to the root views in the application for specific states.

The deafult CSS classes are are:

  • .ns-root - a class assigned to the application root view
  • .ns-modal - a class assigned to the modal root view

The CSS classes for each application and modal root view are:

  • .ns-android, .ns-ios - classes that specify the application platform
  • .ns-phone, .ns-tablet - classes that specify the device type
  • .ns-portrait, .ns-landscape, .ns-unknown - classes that specify the application orientation
  • .ns-light, .ns-dark - classes that specify the system appearance.

::: tip Note In native modals in Angular, the classes are applied to the first layout view in your modal component's HTML. If you are targeting a class that is applied to the root layout in your modal, you would target it with .ns-dark.your-class. :::

For additional information on the Dark Mode support, refer to this documentation article.

Supported Measurement Units

NativeScript supports DIPs (Device Independent Pixels), pixels (via postfix px) and percentages (partial support for width, height and margin) as measurement units.

NativeScript's recommended measurement unit is DIP. All measurable properties like width, height, margin, paddings, border-width, etc.) support device independent pixels. The font sizes are always measured in DIPs.

.myLabel {
  font-size: 28;
  width: 200;
  height: 30;
}

The device independent pixels (DIPs) are equal to the device screen's pixels divided by the device screen scale (density).

import { Screen } from '@nativescript/core'

// mainScreen is of type ScreenMetrics interface /api-reference/interfaces/_platform_.screenmetrics
const scale = Screen.mainScreen.scale
const widthPixels = Screen.mainScreen.widthPixels
const heightPixels = Screen.mainScreen.heightPixels
const widthDIPs = Screen.mainScreen.widthDIPs // DIPs === pixels/scale (e.g. 1024 pixels / 2x scale = 512 DIPs)
const heightDIPs = Screen.mainScreen.heightDIPs

NativeScript supports percentage values for width, height and margins. When a layout pass begins, first the percent values are calculated based on parent available size. This means that on vertical StackLayout if you place two Buttons with height='50%' they will get all the available height (e.g., they will fill the StackLayout vertically.). The same applies for margin properties. For example, if you set marginLeft = '5%', the element will have a margin that corresponds to 5% of the parent's available width.

Using CSS variables

NativeScript supports CSS variables (also known as custom properties or cascading variables) for reusable values through the CSS used in the app.

CSS variables cascades from parent to child views.

Declaring variables:

/* Define --my-custom-color as a global value */
.ns-root {
  --my-custom-color: black;
}

/* In landscape mode change the value to blue */
.ns-landscape {
  --my-custom-color: blue;
}

Overriding a variable from a child-element:

/* Change --my-custom-color to green for elements below */
.ns-root .override-color {
  --my-custom-color: green;
}

Using a variable:

.using-variable {
  color: var(--my-custom-color);
}

The default value of --my-undefined-value will be black. In landscape mode it will be blue. If a parent element have the class override-color the value will be green.

Using a fallback value:

.using-variable {
  color: var(--my-undefined-value, yellow);
}

The color of --my-undefined-value will fallback to yellow, because --my-undefined-value is not defined.

Using a nested fallback value:

.using-variable {
  color: var(--my-undefined-value, var(--my-custom-color, yellow));
}

Using CSS calc()

NativeScript supports CSS calc() functions for performing simple calculations on CSS values.

Syntax:

element {
  width: calc(100% * 1.25); /* width: 125% */
}

Used with CSS variables:

element {
    --my-variable: 10:
    width: calc(100% * var(--my-variable)); /* width: 125% */
}

Accessing NativeScript component properties with CSS

You can set NativeScript component properties value that are not part of the CSS specification. For example:

StackLayout {
   orientation: horizontal;
}

This feature is limited to properties with simple types like string, number and boolean, and will set a local property value similar to component markup declaration in your template markup via XML or HTML. CSS inheritance is not supported.

Using Fonts

The font-family property can hold several values. The first supported font in the list will be used. There is also support for the following generic font-families:

  • serif (ex. Times New Roman)
  • sans-serif (ex. Helvetica)
  • monospace (ex. Courier New)

Platform specifics:

  • Android: The supported fonts depend very much on the system, thus using the generic font-families or custom-fonts is recommended.
  • iOS: There are more than 30 default fonts available on iOS. You can check the supported fonts for specific iOS versions and devices. To use a built-in font, simply specify the font name in the font-family property, such as font-family: "American Typewriter";. Adjust the font variant using the font-weight property.
Custom fonts

You can use custom fonts in your app (in .TTF or .OTF format). The NativeScript runtime will look for the font files under the app/fonts/ (or src/fonts/ if you use Angular) directory and load them automatically.

::: tip Tip Since NativeScript 7.1, the CLI has the ns fonts command. Executing this command will print out the css styles you need for any custom fonts found in your application. :::

::: warning Note On iOS your font file should be named exactly as the font name. If you have any doubt about the original font name, use the Font Book app to get the original font name, or try using ns fonts from your terminal using NS 7.1 or newer. :::

Using Icon Fonts in NativeScript

While bitmap images are great, they present challenges in designing mobile applications. Images increase the size of the application if they are embedded in it. If not, they require additional http requests to be fetched. Images consume memory. Furthermore, bitmap images do not scale well. If scaled up, they lose quality. If scaled down, they waste space. On the other hand, fonts scale well, do not require additional http requests for each glyph and do not increase memory usage significantly. Icon fonts contain icons instead of alphabet characters and can be used instead of images in mobile applications.

  1. Choose or generate an icon font that best matches your needs. Two popular icon fonts are IcoMoon and Font Awesome.
  2. Once you have downloaded the icon font to your machine, locate the TrueType font file with extension .ttf.
  3. In your root application folder (This is the app folder for NativeScript Core, and the src folder for Angular 6+), create a folder called fonts and place the .ttf there.
  4. Follow the instructions on the icon font webpage to determine the hex codes of each font glyph, i.e., icon. Add a Label component to your NativeScript app and bind the Label's text property to a one-letter string generated from the character code of the icon you want to show, i.e., \ue903. Prefix the character (in this example: e903) with a \u

:::tip Note

While this documentation article is focused on icon fonts, the above workflow is a hundred percent applicable for both text fonts and icon fonts (except that with text fonts step 4 as they don't include icons but only plain text).

:::

Platform Specific Font Recognition

There is a conceptual difference in how .ttf fonts are recognized on iOS and Android. On Android, the font is recognized by its file name while on iOS it is recognized by its font name. This means that fonts that are created with a font name which is different from the file name has to be registered with both names in your CSS rule.

.fa-brands {
    font-family: "Font Awesome 5 Brands", "fa-brands-400";
}

In the above example, the fa-brands-400.ttf (as downloaded from the FontAwesome site) has a font name Font Awesome 5 Brands. With the above CSS, the font is recognized on both iOS (by the font name Font Awesome 5 Brands) and Android (by the file name fa-brands-400).

:::tip Note

There are specific scenarios where the creators of the fonts might have released two differently named ttf files but with the same font name (see the example below).

:::

file name font name
fa-solid-900.ttf Font Awesome 5 Free
fa-regular-400.ttf Font Awesome 5 Free

Notice that in the above example the file names are different, but the registered font name is the same (use the Font Book application on Mac or the Control Panel Fonts section on Windows to see the actual font name). While this is no issue on Android, it renders the second font unusable on iOS. To handle similar cases additional CSS font properties, such as for example font-weight, must be added.

/*
    File name: fa-regular-400.ttf
    Font name: Font Awesome 5 Free
*/
.far {
    font-family: "Font Awesome 5 Free", "fa-regular-400";
    font-weight: 400;
}

/*
    File name: fa-solid-900.ttf
    Font name: Font Awesome 5 Free
*/
.fas {
    font-family: "Font Awesome 5 Free", "fa-solid-900";
    font-weight: 900;
}

Import CSS

The @import CSS rule allows you to import CSS from a local file. This rule must precede all other types of rules.

@import url('~/your-style.css');

Using SASS

With NativeScript, it is possible to manage your app styles using the SASS CSS pre-compiler instead of plain CSS files. Just as with web projects, SASS gives your stylesheets extra capabilities like shared variables, mixins and nested style tags.

To use SASS with NativeScript, a SASS compiler like sass is required. This compiler will hook-in to the NativeScript build process and automatically convert .scss/.sass files to .css during build and livesync operations. Since SASS is compiled to CSS at build time, it does not require any changes to your stylesheet naming conventions for NativeScript's normal convention-based patterns to work. SASS files with the same name as a NativeScript page will still be automatically linked.

You can use SASS with either enabling it manually:

npm i sass --save-dev

Or by using a template that has SASS already enabled. For example:

ns create  mySassApp --template @nativescript/template-drawer-navigation-ts

For projects created with NativeScript 5.x and below (which are using the legacy nativescript-dev-webpack), you can run the migrate command to update the SASS compiler (and remove the legacy plugin). Note that the migrate command is available in NativeScript CLI 6 and above.

ns migrate