Crea tu primera aplicación NativeScript

En el último artículo, te presenté a NativeScript. Allí aprendió los conceptos básicos de NativeScript y en qué se diferencia de otros marcos de desarrollo de dispositivos móviles. Esta vez te ensuciarás las manos al crear tu primera aplicación NativeScript. Lo guiaré a través de todo el proceso de creación de una aplicación con NativeScript, desde la configuración de su entorno de desarrollo hasta la ejecución de la aplicación en su dispositivo. Aquí hay un resumen de lo que voy a discutir:

  1. Configurando NativeScript
  2. Construyendo la aplicación
  3. Ejecutando la aplicación
  4. Depurando la aplicación

Estaremos ejecutando específicamente la aplicación en la plataforma Android. Pero aún puede seguir adelante si desea implementar en iOS, ya que el código será prácticamente el mismo. Las únicas diferencias están en el proceso para configurar NativeScript y los comandos que ejecuta al ejecutar la aplicación.

El código fuente completado para esta aplicación está disponible en el tutorial GitHub repo.

1. Configuración de NativeScript

Para configurar NativeScript, primero tiene que instalar Node.js. Una vez instalado Node.js, puede instalar la herramienta de línea de comandos NativeScript ejecutando npm install -g nativescript en su terminal. 

El último paso es instalar la herramienta de desarrollo para cada plataforma en la que desea implementar. Para Android, este es el SDK de Android. Para iOS, es XCode. Puede seguir la guía de instalación en el sitio web de NativeScript para obtener instrucciones más detalladas sobre cómo configurar el software necesario para su entorno de desarrollo..

Una vez que haya configurado su entorno, ejecute doctor tns para asegurarse de que su entorno está listo para el desarrollo de NativeScript. Si está en Linux o Windows, verá algo como esto si su entorno está listo:

NOTA: Puede desarrollar para iOS solo en sistemas Mac OS X. Para poder trabajar con dispositivos y proyectos iOS, necesita Mac OS X Mavericks o posterior. Sus componentes están actualizados. No se detectaron problemas.

Hay una nota allí que solo puedes desarrollar para iOS solo en sistemas Mac OS X. Esto significa que si estás en una PC, solo podrás implementarlo en dispositivos Android. Sin embargo, si estás en Mac, podrás implementarlo en plataformas iOS y Android.

Si tiene algún problema durante la configuración, puede recibir una invitación para unirse a la Comunidad Slack de NativeScript y, una vez que se haya unido, vaya al canal de inicio y haga sus preguntas allí..

2. Creando la aplicación

La aplicación que vamos a construir es una aplicación para tomar notas. Le permitirá al usuario crear notas, cada una con un archivo adjunto de imagen opcional que se capturará con la cámara del dispositivo. Las notas se conservan utilizando la configuración de la aplicación NativeScript y se pueden eliminar individualmente..

Así es como se verá la aplicación:

Comience ejecutando el siguiente comando para crear un nuevo proyecto de NativeScript:

tns create noter --appid "com.yourname.noter"

noter es el nombre del proyecto, y com.yourname.noter es la ID de aplicación única. Esto se usará más adelante para identificar su aplicación una vez que la envíe a Play o App Store. Por defecto, el tns crear comando creará las siguientes carpetas y archivos para usted:

  • aplicación
  • nodo_módulos
  • plataformas
  • paquete.json

Normalmente solo tendrás que tocar los archivos dentro de la aplicación directorio. Pero también hay casos en los que es posible que necesite editar archivos dentro de la plataformas /androide directorio. Uno de estos casos es cuando un complemento que está intentando usar no vincula automáticamente las dependencias y los activos que necesita.. 

A continuación, vaya a la aplicación directorio y eliminar todos los archivos excepto el App_Resources carpeta. Luego crea los siguientes archivos:

  • app.js
  • app.css
  • notas-page.js
  • notes-page.xml

Estos son los archivos que se utilizarán en el tiempo de ejecución de NativeScript. Al igual que al construir páginas web., .css los archivos se utilizan para el estilo, y .js Archivos de funcionalidad. Pero para el marcado de la aplicación, usamos XML en lugar de HTML. Por lo general, creará una carpeta separada para cada pantalla de la aplicación (por ejemplo, inicio de sesión, registro o panel de control) y tendrá archivos XML, CSS y JavaScript dentro de cada carpeta. Pero como esta aplicación solo tiene una pantalla, creamos todos los archivos dentro del directorio raíz..

Si necesita más información sobre la estructura de directorios de NativeScript, consulte el Capítulo 2 de la Guía de introducción de NativeScript.

3. El archivo del punto de entrada

Abre el app.js Archivo y añadir el siguiente código:

var application = require ("application"); application.start (moduleName: "notes-page");

Este es el punto de entrada para una aplicación NativeScript. Utiliza el módulo de aplicación y su comienzo Método para especificar el módulo utilizado para la página inicial de la aplicación. En este caso, hemos especificado. notas-página, lo que significa que el módulo es notas-page.js, el marcado es notes-page.xml, y el estilo de la página es notas-page.css. Esta es una convención utilizada en NativeScript, que todos los archivos de una página específica deben tener el mismo nombre.

4. Agregando el marcado UI

Abre el notes-page.xml Archivo y añadir el siguiente código:

                

Al crear páginas de aplicaciones en NativeScript, siempre debe comenzar con la  etiqueta. Así es como NativeScript sabe que está intentando crear una nueva página. los xmlns atributo especifica la URL del esquema utilizado para el archivo XML. 

Si visita la URL del esquema especificada, puede ver la definición de todas las etiquetas XML que puede usar dentro de NativeScript. los cargado atributo especifica la función que se ejecutará una vez que se carga la página. Vamos a echar un vistazo a esta definición de la función más adelante en el notas-page.js expediente.

... 

Por defecto, el encabezado de la aplicación solo contiene el título de la aplicación. Si quisiera agregar otros componentes de UI, tendría que redefinirlo usando . Luego, dentro de ti, define las cosas que quieres ver en el encabezado. El título se especifica utilizando  y poniendo su título Atribuye al título de la página que quieras.. 

A continuación, hemos utilizado la sintaxis del bigote para generar el valor de título de la aplicación definido en el notas-page.js expediente. Así es como se imprimen los valores que están enlazados a la página..

 ...  

Para definir botones, primer uso  como el padre, y cada uno  Serán los botones que quieras definir. los grifo atributo especifica una función que se ejecutará cuando se toca el botón, mientras que os.position y posición de android Son las posiciones del botón en iOS y Android.. 

Para especificar el texto del botón, puede utilizar el es texto atributo. Sin embargo, NativeScript no permite actualmente cambiar el color del texto del botón a través de CSS. Es por eso que en su lugar hemos utilizado  para definir el contenido del botón y configurar su color de texto.

       

El siguiente es el contenido real de la página. Puede organizar los diferentes elementos utilizando uno o más de los contenedores de diseño. A continuación hemos utilizado dos de los diseños disponibles: StackLayout y Diseño de cuadrícula

StackLayout Te permite apilar todos los elementos en su interior. De forma predeterminada, la orientación de este diseño es vertical, de modo que cada componente de la interfaz de usuario se apila debajo del último. Piensa en ladrillos lego con un flujo descendente.. 

Por otra parte, Diseño de cuadrícula Le permite organizar elementos en una estructura de tabla. Si alguna vez ha usado Bootstrap u otros marcos de cuadrícula CSS, esto debería parecerle natural. los Diseño de cuadrícula le permite definir filas y columnas entre las cuales se puede colocar cada componente de la interfaz de usuario. Veremos cómo se implementa esto más adelante. Por ahora, pasemos al código..

Primero, definamos el formulario para crear una nueva nota. Al igual que en HTML, puede definir atributos como carné de identidad y clase css (equivalente a HTML's clase atributo). los carné de identidad el atributo se adjunta a un elemento si desea manipularlo desde el código. En nuestro caso, queremos animar el formulario más adelante.. clase css se utiliza para especificar la clase CSS que usará para diseñar el elemento. 

Dentro del formulario hay un campo de texto para ingresar el título de la nota, un botón para adjuntar una imagen, la imagen seleccionada y un botón para guardar la nota. El elemento de imagen solo es visible si el attachment_img Tiene un valor veraz. Ese será el caso si una imagen fue adjunta previamente. 

  

La siguiente es la lista que muestra las notas que ya fueron agregadas por el usuario. Las listas se crean utilizando el Vista de la lista componente. Esto acepta artículos como un atributo requerido. El valor puede ser una matriz simple o una matriz observable. 

Si no necesita realizar ningún tipo de actualización (por ejemplo, eliminar o actualizar un campo) a cada elemento de la matriz, una matriz de JavaScript simple funcionará. De lo contrario, use una matriz observable que le permita realizar actualizaciones a la matriz y hacer que se refleje automáticamente en la interfaz de usuario. Vamos a echar un vistazo a cómo se define una matriz observable más adelante. 

También tenga en cuenta que un Vista de la lista puede tener un itemTap atributo, que le permite especificar la función que se ejecutará cuando un elemento en el Vista de la lista está girado Pero en este caso no lo hemos agregado realmente, ya que no necesitamos realizar ninguna acción cuando se toca un elemento..

... 

Los artículos en el Vista de la lista se puede definir usando . Aquí estamos usando una  Para crear dos filas y dos columnas. los columnas atributo se utiliza para especificar cuántas columnas desea en cada fila. 

En este caso, *, * significa que hay dos columnas, cada una de las cuales ocupa una cantidad igual del espacio disponible en la fila actual. Entonces, si toda la fila tiene un ancho total de 300 píxeles, cada columna tendrá 150 píxeles de ancho. Así que básicamente cada * representa una columna y usas una coma para separar cada una de ellas. 

los filas el atributo funciona de manera similar, pero controla la cantidad de espacio utilizado por una sola fila. auto significa que solo consumirá la cantidad de espacio que necesitan los hijos de cada fila. 

Después de definir el columnas y filas en el Diseño de cuadrícula, todavía tiene que especificar cuál de sus hijos pertenece a qué fila y columna. La primera fila contiene el título del elemento (primera columna) y el botón de eliminar (segunda columna). La segunda fila contiene la imagen que se adjuntó al artículo (1ra columna). La fila y las columnas se especifican mediante el uso de la filacolumna atributo para cada elemento. 

Note también el uso de alineación horizontal y alineamiento vertical. Puedes pensar en esto como el equivalente de NativeScript de HTML texto alineado atributo. Pero en lugar de texto, estamos alineando los componentes de la interfaz de usuario. alineación horizontal puede tener un valor de Correcto, izquierda, centrar, o tramo, mientras alineamiento vertical puede tener un valor de parte superior, fondo, centrar, o tramo. La mayoría de estos son autoexplicativos, a excepción de tramo, que se estira para ocupar el espacio horizontal o vertical disponible. 

En este caso, alineación horizontal y alineamiento vertical Se utilizan para centrar la imagen tanto horizontal como verticalmente dentro de su columna. Y alineación horizontal se usa en el botón Eliminar para alinearlo con la parte más a la derecha de la segunda columna.

  

No hemos especificado un itemTap atributo para el Vista de la lista. En su lugar, queremos adjuntar una acción de eliminación que se ejecutará cada vez que se toque un botón de eliminar dentro de un elemento de la lista. Cada elemento tiene un índice atributo, que estamos pasando como un atributo personalizado para el botón de eliminar. Esta es la clave única que se utiliza para identificar cada elemento, de modo que podamos consultarlos fácilmente cuando sea necesario.. 

También note el cargado atributo. Tal como  tiene un cargado atributo, los botones también pueden tener uno. Más adelante verás cómo se usa esto..

5. Código JavaScript

Ahora estamos listos para ver el JavaScript que hace que todo funcione. En esta sección, codificaremos la notas-page.js expediente.

Inicialización

Primero importamos el datos / observable y datos / matriz observable módulos Estos son módulos incorporados en NativeScript que nos permiten crear objetos y matrices observables. Los observables nos permiten actualizar automáticamente la interfaz de usuario cada vez que estos objetos y matrices se actualizan. 

En nuestra app, pageArray se utiliza para almacenar la matriz de notas, y pageData Se usa para atarlo a la página.. pageData También sirve como contenedor general para todos los datos que queremos mostrar en la interfaz de usuario.

var Observable = require ("data / observable"); var ObservableArray = require ("data / observable-array"); var pageArray = new ObservableArray.ObservableArray (); var pageData = new Observable.Observable (notes: pageArray);

A continuación, importe todos los demás módulos que usaremos en esta página:

  • cámara: para trabajar con la cámara del dispositivo..
  • ver: para referirse a elementos específicos en la página. Piense en ello como el equivalente de document.getElementById en NativeScript.
  • ui / enums: un diccionario global de valores constantes para cualquier cosa relacionada con las interfaces de usuario.
  • ui / animación: para animar elementos.
  • Configuraciones de la aplicación: para la persistencia de datos locales.
  • sistema de archivos: para trabajar con el sistema de archivos.
var cameraModule = require ("camera"); var view = require ("ui / core / view"); var uiEnums = require ("ui / enums"); var animation = require ("ui / animation"); var appSettings = require ("configuración de la aplicación"); var fs = require ("sistema de archivos");

A continuación, inicialice los valores para las variables que se utilizarán en todo el archivo. página Se utiliza para almacenar una referencia a la página actual., notasArr es la copia de matriz simple de las notas actuales en la página, y current_index es el valor inicial del índice que se utiliza como ID única para cada nota.

página var var notesArr = []; var current_index = -1;

los pageLoaded () Función

Las funciones están disponibles en el contexto de la página mediante el uso de las exportaciones. Temprano en el notes-page.xml archivo, viste que el pageLoaded () La función se ejecuta cuando se carga la página.. 

exports.pageLoaded = function (args) …

Dentro de pageLoaded () función, empezaremos por obtener la referencia a la página. Luego mostramos el formulario para crear una nueva nota, y obtenemos los valores almacenados actualmente del nuevo título de la nota y las notas de la configuración de la aplicación.

page = args.object; pageData.set ('showForm', true); var new_note_title = appSettings.getString ('new_note_title'); var notes = appSettings.getString ('notas');

A continuación, todavía dentro de la pageLoaded () función, compruebe si hay notas que se almacenan localmente. Si no, creamos una matriz de notas. Esta matriz servirá como contenido predeterminado para los nuevos usuarios de la aplicación. Sin embargo, si ya hay algunas notas almacenadas localmente, las convertimos en una matriz y luego enviamos esos datos a la matriz observable. 

Tenga en cuenta que antes de insertar los elementos en la matriz observable, primero verificamos si está vacío. Tenemos que hacer esto porque al usar el módulo de cámara se ejecuta el cargado evento en la página una vez más después de seleccionar una imagen. Esto significa que si no tenemos cuidado, terminaremos insertando duplicados en la matriz cada vez que el usuario use la cámara.. 

si (! notas) notas = [índice: 0, título: '100 flexiones', índice: 1, título: '100 sentadillas', índice: 2, título: '100 sentadillas', índice: 3, título: '10km corriendo'];  else notes = JSON.parse (notas);  notesArr = notas; if (! pageArray.length) para (var x = 0; x < notes.length; x++) current_index += 1; pageArray.push(notes[x]);  

Ahora que hemos configurado los datos de las notas, podemos actualizar el título de la página configurando su item_title atribuir al valor que obtuvimos de la configuración de la aplicación anterior. Entonces se unen pageData a la página para que la interfaz de usuario se actualice automáticamente cada vez que se realice un cambio en los elementos que hemos establecido. 

pageData.set ('item_title', new_note_title); args.object.bindingContext = pageData;

Animar el formulario para crear nuevas notas. Hacemos esto usando el getViewById función en el ver y pasar en el contexto (la página actual) como el primer argumento y el carné de identidad Atributo asignado al elemento que desea manipular.. 

A continuación, llame al animar función. Esto acepta un objeto que contiene la configuración de animación. Aquí queremos que la forma se deslice hacia abajo 160 píxeles desde su posición original durante un período de 800 milisegundos.

view.getViewById (página, 'formulario'). animate (translate: x: 0, y: 160, duración: 800,);

los nueva nota() Función

los nueva nota() función se ejecuta cuando el usuario pulsa en el Nuevo artículo elemento de acción en el encabezado. Esto oculta y muestra el nuevo elemento. Vista de la lista y desliza el formulario hacia arriba o hacia abajo dependiendo del valor actual de showForm

Si showForm es cierto, lo que significa que actualmente se está mostrando, cambiamos la opacidad de la Vista de la lista a 1 en el transcurso de 400 milisegundos, y luego deslice el formulario hacia arriba para ocultarlo. De lo contrario, ocultamos el Vista de la lista y deslice el formulario hacia abajo.

exports.newNote = function () var showForm = pageData.get ('showForm'); var top_position = (showForm)? -160: 160; var list_visibility = (showForm)? 1: 0; view.getViewById (página, 'lista'). animate (opacity: list_visibility, duration: 400); view.getViewById (página, 'formulario'). animate (translate: x: 0, y: top_position, duración: 800,); pageData.set ('showForm',! showForm); 

los btn cargado () Función

En el notes-page.xml archivo, tenemos un cargado atributo en el botón para borrar una nota. Esta es la función que se ejecuta cuando ocurre ese evento.. 

Por defecto, la función asignada a la itemTap atributo en el Vista de la lista no se ejecutará cuando se define un botón dentro de un Vista de la lista ít. Esto se debe a que NativeScript asume que las acciones a realizar para cada elemento de la lista se pueden activar solo desde esos botones. 

El siguiente código es una solución para ese comportamiento predeterminado. Básicamente, esto elimina el enfoque en el botón de eliminar para que aún pueda ejecutar una función cuando un usuario toca un Vista de la lista ít. En este caso, no necesitamos realmente este código ya que no hemos asignado ninguna funcionalidad a los toques de elementos, pero es una buena herramienta cuando se trabaja con listas.

exports.btnLoaded = function (args) var btn = args.object; btn.android.setFocusable (falso); 

los cámara abierta() Función

Siguiente es el cámara abierta() función, que se ejecuta cuando el usuario pulsa en el Adjuntar imagen botón. El estado actual no se mantiene cuando se utiliza el módulo de la cámara, por lo que primero debemos guardar el título de la nueva nota en la configuración de la aplicación.. 

Luego, podemos iniciar la aplicación de la cámara predeterminada en el dispositivo llamando al tomar la foto() método. Este método acepta un objeto que contiene la configuración de la imagen. Una vez que el usuario ha tomado una foto y ha tocado el Salvar botón en Android o el usar la imagen botón en iOS, la promesa se resuelve y la función de devolución de llamada pasa a entonces() se ejecuta. 

La imagen real se pasa como un argumento a la función, y usamos esto para guardar el archivo en la ruta de los documentos. Una vez hecho esto, guardamos la ruta completa del archivo a la configuración de la aplicación y al estado actual de la aplicación para que podamos obtener el valor más adelante, antes de guardar la nota..

exports.openCamera = function () appSettings.setString ('new_note_title', pageData.get ('item_title')); cameraModule.takePicture (width: 300, height: 300, keepAspectRatio: true). then (function (img) var filepath = fs.path.join (fs.knownFolders.documents (). path, "img_" + ( new Date (). getTime () / 1000) + ".jpg"); img.saveToFile (filepath, uiEnums.ImageFormat.jpeg); appSettings.setString ('new_note_photo', filepath); pageData.set ('attachment_img', ruta de archivo); ); 

los saveNote () Función

los saveNote () función se ejecuta cuando el usuario pulsa en el Guardar nota botón. Esto obtiene el valor actual del campo de texto del título de la nota y la ruta de la imagen, incrementa la current_index, e inserta el nuevo elemento en la matriz de notas planas y en la matriz de notas observables. A continuación, guarda las notas actuales y el current_index en la configuración de la aplicación, elimina los valores para la nueva nota de la configuración de la aplicación, actualiza la interfaz de usuario para que el formulario muestre su estado vacío y muestre la lista mientras oculta el nuevo formulario de nota.

exports.saveNote = function () var new_note_title = pageData.get ('item_title'); var new_note_photo = pageData.get ('attachment_img'); current_index + = 1; var new_index = current_index; var new_item = index: new_index, title: new_note_title, photo: new_note_photo, show_photo: false; notesArr.push (new_item); pageArray.push (new_item); appSettings.setString ('notes', JSON.stringify (notesArr)); appSettings.setNumber ('current_index', new_index); appSettings.remove ('new_note_title'); appSettings.remove ('new_note_photo'); pageData.set ('showForm', false); pageData.set ('item_title', "); pageData.set ('attachment_img', null); view.getViewById (página, 'list'). animate (opacity: 1, duration: 400); view.getViewById ( página, 'formulario'). animate (translate: x: 0, y: -160, duración: 800,);

los borrar nota() Función

Por último, tenemos la borrar nota() función que se ejecuta cuando un usuario pulsa el botón de eliminar dentro de un elemento de la lista. Como ya ha visto en funciones anteriores, un objeto se pasa como un argumento a las funciones que se adjuntan como un controlador de eventos para un componente específico. Este objeto tiene la objeto propiedad, que se refiere al componente en sí. 

A partir de ahí, puede obtener el valor de un atributo que se le pasó. En este caso, estamos obteniendo el valor de la índice atributo, y lo usamos para obtener el índice real del elemento que queremos eliminar.

exports.deleteNote = function (args) var target = args.object; var index_to_delete = notesArr.map (función (e) return e.index;). indexOf (target.index); notesArr.map (función (elemento, índice) if (index == index_to_delete) notesArr.splice (index_to_delete, 1); pageArray.splice (index_to_delete, 1); return false;); appSettings.setString ('notes', JSON.stringify (notesArr)); 

6. Añadiendo estilos

Abre el app.css Archivo y agregar los siguientes estilos globales:

Barra de acción color de fondo: # b898ff; color: #fff;  .header-item text-transform: mayúsculas;  .item relleno: 20; tamaño de fuente: 20px;  .form-container background-color: #fff; margen superior: -160px; relleno: 20px; índice z: 10;  .label font-size: 18px;  .link text-align: left; color de fondo: transparente; color: # 0275d8; relleno: 5px; margen: 10px 0; transformación de texto: mayúsculas; tamaño de fuente: 15px;  .imagen ancho: 300; margen: 20 0;  .primary-button padding: 5px; color: #fff; color de fondo: # 0723bb; transformación de texto: mayúsculas;  .delete-button font-size: 15px; color de fondo: # f50029; color: #fff;  

Si desea aplicar estilos específicos de la página, también puede crear un notas-page.css archiva y define tus estilos allí. 

7. Ejecutando y depurando la aplicación

Puede ejecutar la aplicación en su dispositivo ejecutando tns correr y luego la plataforma donde desea desplegar. Aquí hay un ejemplo para Android:

tns ejecuta android

Esto instala automáticamente la plataforma Android si aún no se ha instalado y luego ejecuta la aplicación en su dispositivo una vez que está instalada. Una vez que la aplicación se está ejecutando, puede ejecutar tns livesync android --watch para actualizar automáticamente la aplicación cada vez que realice cambios en los archivos de origen.

Depuración

Al igual que cualquier otro marco de aplicación, NativeScript permite a los desarrolladores depurar su aplicación. Esto se hace con las herramientas de desarrollo de Chrome. Hay dos maneras de hacer esto:

  1. Si ya tiene una aplicación en ejecución, puede abrir una nueva ventana de terminal y ejecutar tns debug android --start para adjuntar un depurador a la instancia actualmente en ejecución de la aplicación.
  2. Si aún no tiene una aplicación en ejecución, use tns debug android --debug-brk para construir una instancia de la aplicación con un depurador adjunto.

Independientemente de la opción que elija, esto abrirá una nueva pestaña en el navegador Google Chrome que le permite depurar la aplicación como una aplicación web de JavaScript normal. Esto significa que realmente puedes usar console.log en su código fuente para inspeccionar el contenido de las variables con las que está trabajando.

Conclusión y próximos pasos

En este artículo, has aprendido cómo construir una aplicación con NativeScript. Específicamente, ha aprendido conceptos como el uso de componentes de interfaz de usuario, diseños, estilos, animaciones, el uso de la cámara del dispositivo y el mantenimiento del estado de la aplicación con la configuración de la aplicación.. 

Ahora que ha creado su primera aplicación NativeScript, ahora es el momento de llevar sus habilidades aún más lejos al ver qué más puede hacer con NativeScript y compilar algunas aplicaciones más con él.. 

  • Cree una aplicación de gestión