- Setting up NativeScript
- Building the app
- Running the app
- Debugging the app
The completed source code for this app is available from the tutorial GitHub repo.
1. Setting Up NativeScript
To set up NativeScript, you first have to install Node.js. Once Node.js is installed, you can install the NativeScript command-line tool by executing npm install -g nativescript on your terminal.
The final step is to install the development tool for each platform that you want to deploy to. For Android, this is the Android SDK. For iOS, it's XCode. You can follow the installation guide on the NativeScript website for more detailed instructions on how to set up the necessary software for your development environment.
Once you've set up your environment, execute tns doctor to make sure that your environment is ready for NativeScript development. If you're on Linux or Windows, you'll see something like this if your environment is ready:
- NOTE: You can develop for iOS only on Mac OS X systems.
- To be able to work with iOS devices and projects, you need Mac OS X Mavericks or later.
- Your components are up-to-date.
- No issues were detected.
If you run into any problems during the setup, you can get an invitation to join the NativeScript Slack Community and once you have joined, go to the getting started channel and ask your questions in there.
2. Creating the App
The app that we're going to build is a note-taking app. It will allow the user to create notes, each with an optional image attachment that will be captured with the device camera. The notes are persisted using NativeScript application settings, and can be individually deleted.
Here's what the app is going to look like:
![]() |
- tns create noter --appid "com.yourname.noter"
- app
- node_modules
- platforms
- package.json
Next, navigate to the app directory and delete all files except the App_Resources folder. Then create the following files:
- app.js
- app.css
- notes-page.js
- notes-page.xml
If you need more information about the NativeScript directory structure, check out Chapter 2 of the NativeScript Getting Started Guide.
3. The Entry Point File
Open the app.js file and add the following code:
- var application = require("application");
- application.start({ moduleName: "notes-page" });
4. Adding the UI Markup
Open the notes-page.xml file and add the following code:
- <Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
- <Page.actionBar>
- <ActionBar title="{{ app_title }}">
- <ActionBar.actionItems>
- <ActionItem tap="newNote" ios.position="right" android.position="actionBar">
- <ActionItem.actionView>
- <StackLayout orientation="horizontal">
- <Label text="New Item" color="#fff" cssClass="header-item" />
- </StackLayout>
- </ActionItem.actionView>
- </ActionItem>
- </ActionBar.actionItems>
- </ActionBar>
- </Page.actionBar>
- <StackLayout>
- <StackLayout id="form" cssClass="form-container">
- <TextView text="{{ item_title }}" hint="Title" />
- <Button text="Attach Image" cssClass="link label" tap="openCamera" />
- <Image src="{{ attachment_img }}" id="attachment_img" cssClass="image" visibility="{{ attachment_img ? 'visible' : 'collapsed' }}" />
- <Button text="Save Note" tap="saveNote" cssClass="primary-button" />
- </StackLayout>
- <ListView items="{{ notes }}" id="list" visibility="{{ showForm ? 'collapsed' : 'visible' }}">
- <ListView.itemTemplate>
- <GridLayout columns="*,*" rows="auto,auto" cssClass="item">
- <Label text="{{ title }}" textWrap="true" row="0" col="0" />
- <Image src="{{ photo }}" horizontalAlignment="center" verticalAlignment="center" cssClass="image" row="1" col="0" visibility="{{ photo ? 'visible' : 'collapsed' }}" />
- <Button text="delete" index="{{ index }}" cssClass="delete-button" tap="deleteNote" row="0" col="1" horizontalAlignment="right" loaded="btnLoaded" />
- </GridLayout>
- </ListView.itemTemplate>
- </ListView>
- </StackLayout>
- </Page>
If you visit the schema URL specified, you can see the definition of all the XML tags that you can use within NativeScript. The loaded attribute specifies the function to be executed once the page is loaded. We'll take a look at this function definition later on in the notes-page.js file.
- <Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded">
- ...
- </Page>
Below we've used the mustache syntax to output the value of app_title defined in the notes-page.js file. This is how you output values that are bound to the page.
- <Page.actionBar>
- <ActionBar title="{{ app_title }}">
- ...
- </ActionBar>
- </Page.actionBar>
To specify the button text, you could use the <ActionItem>'s text attribute. However, NativeScript doesn't currently allow changing the text color of the button through CSS. That's why instead we've used <ActionItem.actionView> to define the content of the button and to set its text color.
- <ActionBar.actionItems>
- <ActionItem tap="newNote" ios.position="right" android.position="actionBar">
- <ActionItem.actionView>
- <StackLayout orientation="horizontal">
- <Label text="New Item" color="#fff" cssClass="header-item" />
- </StackLayout>
- </ActionItem.actionView>
- </ActionItem>
- </ActionBar.actionItems>
StackLayout allows you to stack all the elements inside of it. By default, the orientation of this layout is vertical, so that each UI component is stacked below the last. Think of lego bricks with a downward flow.
On the other hand, GridLayout allows you to arrange elements in a table structure. If you've ever used Bootstrap or other CSS grid frameworks then this should seem natural to you. The GridLayout lets you define rows and columns among which each UI component can be placed. We'll take a look at how this is implemented later on. For now, let's move on to the code.
First, let's define the form for creating a new note. Just like in HTML, you can define attributes such as id and cssClass (equivalent to HTML's class attribute). The id attribute is attached to an element if you want to manipulate it from code. In our case, we want to animate the form later on. cssClass is used to specify the cssClass that you will use to style the element.
Inside the form is a text field for entering the note title, a button for attaching an image, the selected image, and a button for saving the note. The image element is only visible if the attachment_img has a truthy value. That will be the case if an image was previously attached.
- <StackLayout id="form" cssClass="form-container">
- <TextView text="{{ item_title }}" hint="Title" />
- <Button text="Attach Image" cssClass="link label" tap="openCamera" />
- <Image src="{{ attachment_img }}" id="attachment_img" cssClass="image" visibility="{{ attachment_img ? 'visible' : 'collapsed' }}" />
- <Button text="Save Note" tap="saveNote" cssClass="primary-button" />
- </StackLayout>
If you do not need to perform any form of update (e.g. deleting or updating a field) to each item in the array, a plain JavaScript array will do. Otherwise, use an observable array which allows you to perform updates to the array and have it automatically reflected to the UI. We'll take a look at how an observable array is defined later on.
Also note that a ListView can have an itemTap attribute, which allows you to specify the function to be executed when an item in the ListView is tapped. But in this case we haven't really added it since we don't need to perform any action when an item is tapped.
- <ListView items="{{ notes }}" id="list" visibility="{{ showForm ? 'collapsed' : 'visible' }}">
- ...
- </ListView>
<GridLayout>
to create two rows and two columns. The columns attribute is used to specify how many columns you want in each row.In this case, *,* means that there are two columns, each taking up an equal amount of the available space in the current row. So if the whole row has a total width of 300 pixels, each column will be 150 pixels wide. So basically each * represents one column, and you use a comma to separate each of them.
The rows attribute works similarly, but controls the amount of space used by a single row. auto means it will only consume the amount of space needed by the children of each row.
After defining the columns and rows in the GridLayout, you still have to specify which of its children belongs to which row and column. The first row contains the title of the item (1st column) and the delete button (2nd column). The second row contains the image that was attached to the item (1st column). The row and columns are specified by using the row and col attribute for each element.
Also notice the use of horizontalAlignment and verticalAlignment. You can think of this as the NativeScript equivalent of HTML's text-align attribute. But instead of text, we're aligning UI components. horizontalAlignment can have a value of right, left, center, or stretch, while verticalAlignment can have a value of top, bottom, center, or stretch. Most of these are self-explanatory, except for stretch, which stretches to take up the available horizontal or vertical space.
In this case, horizontalAlignment and verticalAlignment are used to center the image both horizontally and vertically inside its column. And horizontalAlignment is used on the delete button to align it to the right-most part of the second column.
- <ListView.itemTemplate>
- <GridLayout columns="*,*" rows="auto,auto" cssClass="item">
- <Label text="{{ title }}" textWrap="true" row="0" col="0" />
- <Image src="{{ photo }}" horizontalAlignment="center" verticalAlignment="center" cssClass="image" row="1" col="0" visibility="{{ photo ? 'visible' : 'collapsed' }}" />
- <Button text="delete" index="{{ index }}" cssClass="delete-button" tap="deleteNote" row="0" col="1" horizontalAlignment="right" loaded="btnLoaded" />
- </GridLayout>
- </ListView.itemTemplate>
Also notice the loaded attribute. Just as <Page> has a loaded attribute, buttons can also have one. You'll see later on how this is used.
Written by Wernher-Bel Ancheta (continue)
If you found this post interesting, follow and support us.
Suggest for you:
Build Apps with React Native
The Complete Android Developer Course - Build 14 Apps
Ionic by Example: Create Mobile Apps in HTML5
The Complete Android & Java Course - Build 21 Android Apps
Android Application Programming - Build 20+ Android Apps
No comments:
Post a Comment