NativeScript Core

Tab View

The TabView component provides a simple way to navigate between different views by tapping on some of the tabs or by swiping between the views. By default the TabView will load the view of the first tab, however it is possible to load alternative tabs when the app starts by setting the component’s selectedIndex property.

const textViewModule = require("tns-core-modules/ui/text-view");

The general behaviour of the TabView component is to load its items demand. This means that every TabViewItem view will be loaded when it is shown and will be unloaded when it disappears. Respectively loaded and unloaded events will be fired while showing or hiding each view. However, there are some specifics for each platform(iOS and Android), which are described in the notes below.

Note (iOS specific): UITabBarController is used in the implementation, which means that only one TabViewItem can be shown at a given time and only one needs to be loaded. When the user selects a new TabViewItem, we load the new item and unload the previous one.

Note (Android specific): In the Android implementation is used ViewPager controller, which allows using the swipe gesture to navigate to the next or previous tab. This means that only one TabViewItem can be shown, but multiple TabViewItems need to be loaded. Otherwise, after left or right swipe, you will not see the TabViewItem's contents, after the swiping. By default, the ViewPager controller will pre-load one TabViewItem on the left and on on the right. Regarding that, if one of the items is already pre-loaded, it will not be loaded again. In the Android, we have exposed a property called androidOffscreenTabLimit, which allow specifying, how many components should be pre-load on the left and right (if you are setting up androidOffscreenTabLimit to 0, the Android TabView will match to the iOS TabView).

The iOS and Android UX guidelines regarding the Tab controls differ greatly. The difference is described in the below points:

  • The iOS tabs have their tab bar, which will be displayed always on the bottom and does not allow swipe gesture for changing tabs.
  • The Android tabs are on top and will enable the swipe navigation between the tabs.
  • For Android we have androidTabsPosition property which has two options top(default value) and bottom. Setting up this property to bottom allows mimicking Bottom Tab Navigation control(provided by android support library v25 release). Setting the Tabs at the bottom will disable the swipe navigation and the items preloading functionality.

Basics

In a pure NativeScript application, TabView has an items property which could be set via XML to an array of TabViewItems (basically, an array of objects with title and view properties). The following example shows how to add a TabView to your page:

XML

<TabView id="tabViewContainer">
    <TabViewItem title="NativeScript">
        <StackLayout>
            <Label text="NativeScript" class="m-15 h2 text-left" color="blue" />
            <ScrollView>
                <StackLayout height="100%">
                    <Label text="{{ content }}" textWrap="true" class="m-15" />
                </StackLayout>
            </ScrollView>
        </StackLayout>
    </TabViewItem>
    <TabViewItem title="Icon">
        <StackLayout>
            <Image class="m-t-30 m-b-15" src="res://icon" width="80" height="80" />
            <Label text="NativeScript" textWrap="true" class="h2 m-x-auto" color="blue" />
        </StackLayout>
    </TabViewItem>
</TabView>

JavaScript

function onNavigatingTo(args) {
    const page = args.object;
    const sampleText = "NativeScript is a free and open source framework for building native iOS and Android apps using JavaScript and CSS. NativeScript renders UIs with the native platform’s rendering engine—no WebViews—resulting in native-like performance and UX.NativeScript provides a best-of-both-worlds development experience. Our cross-platform JavaScript modules give you the convenience of writing iOS and Android apps from a single JavaScript codebase, while our runtimes give you the power of accessing native APIs, SDKs, and frameworks when you need them—all without needing to open Xcode or Android Studio. NativeScript was created and is supported by Telerik.\n\n\n NativeScript doesn’t require Angular, but it’s even better when you use it. You can fully reuse skills and code from the web to build beautiful, high performance native mobile apps without web views. NativeScript features deep integration with Angular, the latest and greatest (and fastest) Angular framework. Open source and backed by Telerik.";
    const vm = new observableModule.Observable();
    vm.set("content", sampleText);

    page.bindingContext = vm;
}
exports.onNavigatingTo = onNavigatingTo;

Improve this document

Demo Source


Code Behind

This sample shows how to create TabView via code-behind

JavaScript

// creating TabView Item content body
const stackLayout0 = new StackLayout();
const label0 = new Label();
label0.text = "Tab 0";
stackLayout0.addChild(label0);

const stackLayout1 = new StackLayout();
const label1 = new Label();
label1.text = "Tab 1";
stackLayout1.addChild(label1);

const tabViewItem0 = new tabViewModule.TabViewItem();
tabViewItem0.title = "Tab 0";
tabViewItem0.view = stackLayout0;

const tabViewItem1 = new tabViewModule.TabViewItem();
tabViewItem1.title = "Tab 1";
tabViewItem1.view = stackLayout1;

// creating TabView
const tabView = new tabViewModule.TabView();
// setting up its items and the selected index
const items = [];
items.push(tabViewItem0);
items.push(tabViewItem1);
tabView.items = items;

tabView.selectedIndex = 1;
// handling selectedIndexChangedEvent
tabView.on(tabViewModule.TabView.selectedIndexChangedEvent, (args) => {
    dialogs.alert(`Selected index has changed ( Old index: ${args.oldIndex} New index: ${args.newIndex})`)
        .then(() => {
            console.log("Dialog closed!");
        });
});

Improve this document

Demo Source


Icon Fonts

The example demonstrates, how to use Icon font for the TabView items title.

<TabView class="icon" selectedIndex="0">
    <TabViewItem title="&#xe913;">
        <StackLayout>
            <Label text="First TabView item with Icon Font" textAlignment="center" textWrap="true" class="h2 m-x-auto" color="blue" />
            <Label text="&#xe913;" textWrap="true" class="h2 m-x-auto" color="blue" />
        </StackLayout>
    </TabViewItem>
    <TabViewItem title="&#xe908;">
        <StackLayout>
            <Label text="Second TabView item with Icon Font" textAlignment="center" textWrap="true" class="h2 m-x-auto" color="green" />
            <Label text="&#xe908;" textWrap="true" class="h2 m-x-auto" color="green" />
        </StackLayout>
    </TabViewItem>
</TabView>
.icon{
    font-family: 'icomoon';
}

Improve this document

Demo Source


Styling

The following example shows how to use selectedIndex property and how to handle its change. In the sample code, you will also find how to change the TabView index via code behind as well as how to set up some platform specific styling properties.

For the TabView component could be set three different styling properties

  • selectedTabTextColor (coresponding CSS property selected-tab-text-color ) - change the color of the text, while selecting some of the tabs.

  • tabBackgroundColor (coresponding CSS property tab-background-color) - changing the background of the tabs.

  • textTransform (coresponding CSS property text-transform) - setting up textTransform individual for every TabViewItem. Value options: capitalize, lowercase, none, uppercase.

  • androidSelectedTabHighlightColorandroid specific property (coresponding CSS property android-selected-tab-highlight-color) - setup underline color of the Tabs in Android.

XML

<TabView selectedIndex="{{tabSelectedIndex}}" selectedIndexChanged="onSelectedIndexChanged" selectedTabTextColor="#FF0000" iosIconRenderingMode="alwaysOriginal" androidSelectedTabHighlightColor="red">
    <TabViewItem title="Profile" iconSource="res://icon">
        <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" textTransform="lowercase">
        <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>

JavaScript

function onNavigatingTo(args) {
    const page = args.object;
    const vm = new observableModule.Observable();
    vm.set("tabSelectedIndex", 0);
    vm.set("tabSelectedIndexResult", "Profile Tab (tabSelectedIndex = 0 )");

    page.bindingContext = vm;
}

function changeTab(args) {
    const page = args.object.page;
    const vm = page.bindingContext;
    const tabSelectedIndex = vm.get("tabSelectedIndex");
    if (tabSelectedIndex === 0) {
        vm.set("tabSelectedIndex", 1);
        vm.set("tabSelectedIndexResult", "Stats Tab (tabSelectedIndex = 1 )");
    } else if (tabSelectedIndex === 1) {
        vm.set("tabSelectedIndex", 2);
        vm.set("tabSelectedIndexResult", "Settings Tab (tabSelectedIndex = 2 )");
    } else if (tabSelectedIndex === 2) {
        vm.set("tabSelectedIndex", 0);
        vm.set("tabSelectedIndexResult", "Profile Tab (tabSelectedIndex = 0 )");
    }
}
// displaying the old and new TabView selectedIndex
function onSelectedIndexChanged(args) {
    if (args.oldIndex !== -1) {
        const tabSelectedIndex = args.object.selectedIndex;
        const page = args.object.page;
        const vm = page.bindingContext;
        if (tabSelectedIndex === 0) {
            vm.set("tabSelectedIndexResult", "Profile Tab (tabSelectedIndex = 0 )");
        } else if (tabSelectedIndex === 1) {
            vm.set("tabSelectedIndexResult", "Stats Tab (tabSelectedIndex = 1 )");
        } else if (tabSelectedIndex === 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!");
            });
    }
}
exports.onNavigatingTo = onNavigatingTo;
exports.changeTab = changeTab;
exports.onSelectedIndexChanged = onSelectedIndexChanged;

Improve this document

Demo Source


Tabs Limit

Setting up the limit of the tabs, which should be pre-loaded on the left and right sides.

<TabView id="tabViewContainer" androidOffscreenTabLimit="0">
    <TabViewItem title="NativeScript">
        <StackLayout>
            <Label text="NativeScript" class="m-15 h2 text-left" color="blue" />
            <ScrollView>
                <StackLayout height="100%">
                    <Label text="{{content}}" textWrap="true" class="m-15" />
                </StackLayout>
            </ScrollView>
        </StackLayout>
    </TabViewItem>
    <TabViewItem title="Icon">
        <StackLayout>
            <Image class="m-t-30 m-b-15" src="res://icon" width="80" height="80" />
            <Label text="NativeScript" textWrap="true" class="h2 m-x-auto" color="blue" />
        </StackLayout>
    </TabViewItem>
</TabView>

Improve this document

Demo Source


Tabs Position

Setting up the bottom Tabs position for Android.

<TabView id="tabViewContainer" androidTabsPosition="bottom">
    <TabViewItem title="NativeScript">
        <StackLayout>
            <Label text="NativeScript" class="m-15 h2 text-left" color="blue" />
            <ScrollView>
                <StackLayout height="100%">
                    <Label text="{{content}}" textWrap="true" class="m-15" />
                </StackLayout>
            </ScrollView>
        </StackLayout>
    </TabViewItem>
    <TabViewItem title="Icon">
        <StackLayout>
            <Image class="m-t-30 m-b-15" src="res://icon" width="80" height="80" />
            <Label text="NativeScript" textWrap="true" class="h2 m-x-auto" color="blue" />
        </StackLayout>
    </TabViewItem>
</TabView>

Improve this document

Demo Source


API Reference for the TabView Class

Native Component

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