Nothing Special   »   [go: up one dir, main page]

Android Programming For Beginners

Download as pdf or txt
Download as pdf or txt
You are on page 1of 94

ANDROID PROGRAMMING FOR

BEGINNERS: THE FAST AND EASIEST WAY


CREATING YOUR FIRST A NDROID A PPLICATION THE FAST AND
EASIEST WAY USING C ORONA SDK
B Y AJ S OTELO
Copyright 2017 All Rights Reserved.
No part of this publication may be reproduced, distributed, or transmitted in
any form or by any means, including photocopying, recording, or other
electronic or mechanical methods, or by any information storage and
retrieval system without the prior written permission of the publisher,
except in the case of very brief quotations embodied in critical reviews and
certain other noncommercial uses permitted by copyright law.

Every effort has been made in the preparation of this book to ensure the
accuracy of the information presented. However, the information contained
in this book is sold without warranty, either express or implied, neither the
author nor its dealers and distributors will be held liable for any damages
caused or alleged to be caused directly or indirectly by this book.
WHY I WROTE T HIS BOOK
Today, there are so many available softwares for developing Mobile Apps
and Games but they require high spec and quality computers. How about those
people who want to learn or develop Apps with low end computer and cant
afford high end computer? In addition, documentations or resources are also
hard to find or even if you found some they rarely give you working examples.

The internet is now too crowded. I know, we hate to wait or research and
download large files or read long chapters, blog posts or documentations with
too much information and yet it only has little of what we really need. So I
wrote this book to share my knowledge in developing Apps the fast and easiest
way even you dont have experience in developing one before.

I am not a guru or geek and I barely know Java and C# but I can still
develop my own Apps and Games and what more interesting is that it is easy
to learn. So if you have idea in mind then get ready for making it real.
WHY YOU SHOULD READ T HIS BOOK
You want to learn how to develop Mobile Apps but you dont have the
resources and your computer doesnt meet the system requirements? No
problem, this book is for you.

This book will guide you on how to develop an Android Application but
consider this as a compilation and tutorials of simple start up Applications in
developing your first Android Apps.

Learn while doing actual codes, see results in real time right away from
your device without rebuilding the App. Display images, text, vectors, play
sounds and animate objects with just few lines.

I assure you, you dont need to download 300mb IDE, 2GB SDK, or
upgrade your laptop just to be able to develop and learn how to code your first
App. I will not try to be complete or precise but I want you to start learning as
quickly as possible. We will focus on what is currently needed or commonly
used APIs so we wont get stuck.
T ABLE OF CONTENTS
Why I Wrote This Book
Why You Should Read This Book
Table Of Contents
Chapter 1: Introduction to Android
What is Android?
What is An Android App?
What are the Editors and Tools available online?
What are the basic skills needed to develop an App?
Chapter 2: Getting Ready
Introduction to Corona SDK
System Requirements
What do we need?
Setting up Corona SDK
Corona Simulator
Corona Simulator Output
A Short Introduction to Sublime Text
Chapter 3: Building Your First App
Chapter 4: Simultaneous Device Testing
Creating a Live Build
Starting the Corona Server
Connecting the Device and Testing
Closing the Live Server
Chapter 5: The Project Files
The build.settings
The config.lua
The Ultimate config.lua
Icons
Chapter 6: Status Bar and Android System UI Visibility
What is Status Bar?
How to Change Status Bar?
What is Android System UI Visibility?
Chapter 7: Understanding Tables, Functions, Methods and Events Listeners
Tables
Functions
Methods
Events
Chapter 8: Tips and Understanding Errors
Runtime Errors
Tips
Chapter 9: Creating a Simple IO App
Interface
Text Display Object
Native Text Field
Button Widget
Native Alerts
Chapter 10: Simple App Using Composer API
Scenes
Overlay Scene
Calling a Parent Scene Method from an Overlay
Chapter 11: Creating a Simple Movie List App
Movie List Module
Menu Scene Interface
Detail Scene Interface
Chapter 12: Using SQLite3
Creating and Connecting a Database
Executing SQL Command
Closing the Connection
Chapter 13: A Simple App with Database
Setting up The Database
Interface
The Process
About The Author
CHAPTER 1: INTRODUCTION TO ANDROID
Let us view a short introduction of Android.

What is Android?
Android is an Operating System that is designed for touchscreen devices
such as tablets and smartphones. Android Version Names are based on sweet
desserts. Android Version 1.5 or also known as Cupcake was released in
April 2009, followed by Donut (1.6) in September 2009, clair (2.0 2.1) in
October 2009, Froyo (2.2 2.2.3) in May 2010, Gingerbread (2.3 2.3.7)
December 2010, Honeycomb (3.0 3.2.6) February 2011, Ice Cream
Sandwich (4.0 4.0.4) October 2011, Jelly Bean (4.1 4.3.1) July 2012,
Kitkat (4.4 4.4.4) October 2013, Lollipop (5.0 5.1.1) November 2014,
Marshmallow (6.0 6.0.1) October 2015 and the latest version, Nougat (7.0
7.1.1) which was released in August 2016.
Since Android is Open Source it became popular and it became the best-
seller OS on tablets since 2013. In September 2015, Android had 1.4 billion
active users making it the most used OS for mobile devices. Android is now
used for TVs, watches, notebooks, digital cameras, game consoles and many
more. Android was owned by Android Inc. which later on bought by Google in
2005.

What is An Android App?


Android Applications (Apps) are written using the Android Studio,
Cordova, Unity or any other similar software. Android Apps are applications
that run on Android powered devices and have a file extension of .apk
(Android Application Package) which can be downloaded through an
application store like Google Play Store. Google Play Store allows user to
browse, download, update and uninstall an application. Application extends
the functionality of the device. Here are some Applications which most users
download, Facebook, Messenger, Snapchat, ShareIt, Skype, Twitter, YouTube,
Google Maps, Instagram and many more. Based on Statista.com Google Play
Store currently has 2.8 million Apps which are categorized by the following:
Music, Sports, Travel, Business, Social Media, Games, Books, and Navigation
etc.

What are the Editors and Tools available


online?
There are so many free Editors and Tools today that are available online.
But the Editors and Tools that you will use will depend on what language you
know and computer system requirements. Here is a list of IDE/SDK/Tools.

1. Android Studio - is the official integrated development environment (IDE)


for the Android platform. It has the following features:
1. Intelligent code editor - which helps you writing your code faster.
2. Instant Run - Instant Run feature pushes code and resource changes to
your running app.
3. Fast and feature-rich emulator - The Android Emulator installs and
starts your apps faster than a real device and allows you to prototype and
tests your app on various Android device configurations: phones, tablets,
Android Wear, and Android TV devices. You can also simulate a variety
of hardware features such as GPS location, network latency, motion
sensors, and multi-touch input.
It has also sample apps and code templates. Android Studio is optimized for
all Android Devices and designed for teams.
2. Apache Cordova (formerly PhoneGap) Apache Cordova enables
programmers to build mobile applications using CSS3, HTML5, and
JavaScript. Applications build with Cordova is neither native nor purely
web-based since apps have access to native device APIs.
3. Xamarin - Uses C# for codebase and let developers use it to write native
Android, iOS, and Windows apps with native user interfaces and share
code across multiple platforms, including Windows and macOS.
4. Corona SDK like other software mentioned above, Corona SDK is also
cross platform. It enables developers to build from single codebase and test
their apps through different devices instantly without rebuilding the app by
creating live builds. It uses Lua scripting language and doesnt need
Android SDK for building the App.

What are the basic skills needed to develop an


App?
The basic skills you need to be able to develop an App are the
following:
1. Design You should be creative and good in designing. Knowledge in
Photoshop or Illustrator or other similar software is a plus. But of course
you can also download or buy graphics for your Application.

2. Programming You should have a basic knowledge of the language that


you will use. Though you can learn them along the way. Here is a list of
languages mostly used in mobile development:
1. Java for Android Studio and Eclipse
2. C# for Xamarin, Unity, Visual Studio and Monogame
3. Lua for Corona SDK
4. HTML, CSS3 and JavaScript for Apache Cordova, Intel XDK,
PhoneGap and Titanium
But of course, if you dont know any of these, you can start learning by
actual coding. Even the best programmer starts from zero.

3. Good Analytical thinking the ability to visualize, articulate,


conceptualize or solve both complex and uncomplicated problems by
making decisions that are sensible given the available information. You
should be able to formulate a solution or know the best approach for the
project that you will do. You should also be good in organizing data and
other files used.

4. Resourcefulness many people quit just because they lack of resources.


So before you start you should know where you can get resources and how
you can use them so that you wont solve a problem that is already solved
by others unless you a better solution.
CHAPTER 2: GETTING READY
Let us view a short introduction to the softwares that we will use.

Introduction to Corona SDK


Corona SDK was developed by Corona Labs Inc. It is a cross-platform
framework which enables every developer to create and develop Apps or
games in different platforms with a single code base including iOS, Kindle,
Android, Windows Phone 8, tvOS, Android TV, Windows and OS X. It also
enables the developers to test their Apps in real time. It also has a friendly
community and a whole lot of plugins that you can integrate to your App.
Corona also now has its own Marketplace where you can buy free and paid
assets, templates, plugins and more. Corona uses the scripting language Lua
which is moon in Portuguese. Lua is easy to learn, fast and lightweight.
Building Apps in Corona doesnt require Android SDK but requires Java
and internet connection. You also dont need to start an emulator in your PC to
test your Apps. You can start the simulator to simulate your App or create a
live build for your App and install it to different devices. This enables the
developer to test the App in real time without rebuilding the App. At the top of
everything, Corona SDK is 100% free.

System Requirements
Corona SDK on Windows only supports building Android and Windows
32 Applications and it requires the following basic system elements:
Windows 10, Windows 8, Windows 7, Vista, or XP Service Pack 3
1 GHz processor (recommended)
1 GB of RAM (recommended)
OpenGL 2.1 or higher (available in most modern Windows systems)
In order to build Apps for Android, you should download and install Java
7 Development Kit if not yet installed. You can click here to go to the
download page. Read the license agreement and accept it if you agree. Then
download the JDK for Windows x86 (even if your system is 64 bit).
Make sure to install JRE as part of installation.
Note that Corona SDK built Applications only supports Android devices
that runs Android 4.0.3 (ICS) or higher with ARMv7 processor. ARMv6 is
not supported.

What do we need?
Here are the things that you need to get started:
1. Download Corona SDK and create an account with Coronalabs.com
1. Go to https://coronalabs.com/ and enter your email then click Download
Free SDK.

2. You will be redirected to a new page where you need to register or login
if already a member. Remember your account email and password for
you will use it to activate Corona SDK after installation.
3. After creating an account you will be redirected to a new page. Click
Download Corona SDK

4. If you can see below, the system requirements are enough to install it on
a notebook. Click Download.

5. Install Corona SDK and open the Corona Simulator. You will be ask to
login. Enter your information from Coronalabs.com account and your
SDK will be activated.
2. Download Offline Version of Corona SDK documentation.
1. From the current page, scroll to the very bottom and you will see the
Corona SDK daily build. Look for the corresponding CoronaApiDocs
zip for your downloaded Corona SDK version and download it.

2. Now, look for the zip file and extract it to anywhere you want and open
the index.html file.

3. Open it with your favorite browser and pin it so you can access it
anytime you want without opening the directory where it is stored.
Just right click the tab and click Pin tab.
4. Now, you can browse the documentation of Corona SDK offline. This
is handy when you are stuck in a situation that you need examples and
API reference while you are offline. You can also visit Coronalabs
Forum here anytime when you are online. Every time you encounter a
new API or function, go to Coronalabs Documentation and click for
API Reference-> press ctrl+f enter the API or function and click
the highlighted link.

3. Download Sublime Text Editor and Integrate Corona Editor


a) Now go to https://coronalabs.com/products/editor/ and read the
information regarding the IDE and go to Sublime Text Website.

b) Download Sublime Text editor and choose the version that fits your
OS.
c) Extract it to local C under Program Files and create a shortcut to
your desktop by simply right-click -> send to -> Desktop (Create
Shortcut).

4. Lets Integrate Corona Editor to Sublime Text.


1. Download the code here https://github.com/coronalabs/CoronaSDK-
SublimeText by clicking Clone or Download then click Download ZIP.
2. When done, extract the zip file and do the following:
1. Open Sublime Text editor
2. Go to Preferences -> Browse Packages

3. Copy and Paste the extracted folder to the package folder.

4. The Sublime Text Editor should now Display a menu Corona Editor.
Restart Sublime if Corona Editor Menu doesnt appear.

5. Sublime Text Editor is now integrated with Corona Editor. Lastly, lets
set our default syntax to Corona SDK Lua. Go to View -> Syntax ->
Corona SDK Lua.
Setting up Corona SDK
After downloading Corona SDK, install it and open Corona Simulator. The
Corona Simulator will prompt you to login (if not yet logged in).

To be able to change the Simulators preferences, you need to click File->


Preferences.
From here, you can check or uncheck the preferences that you want. But to
be able to relaunch automatically your App every time you save changes to the
code, click Always under Relaunch Simulator when project is modified?

Corona Simulator
Corona Simulator is where you can simulate your Apps. But there are
functionalities that the simulator cant simulate like multi touch, GPS,
notifications, accelerometer, gyroscope and camera. Good thing Corona
enables developers to create a live build where your Apps can be tested in
real time without rebuilding it. But the downside of it is that sometimes you
cant track the errors in live builds, thats why it is still important to run the
simulator while your live build is connected.

Corona Simulator Output


Corona Simulator Output is where you can see the outputs, warnings and
logs. When using Sublime Text Integrated with Corona Editor, the simulator
output will not appear but the outputs will be printed to the build panel of
Sublime Text which appears below the editor.
You are all set! You can browse some sample Apps from the simulator.
Open Corona Simulator and click Samples. Select the sample project that you
want and it will run to the simulator.

A Short Introduction to Sublime Text


Sublime Text is a sophisticated text editor for code, markup and pose.
Sublime Text has the following features:
1. Use Multiple Selections to rename variables quickly. Ctrl+D is used to
select the next occurrence of the current word.
2. Make batch edits with Multiple Selections. Ctrl+Shift+L is used to split a
selection into lines, and each line is then edited simultaneously
3. The Command Palette gives fast access to functionality. Ctrl+Shift+P is
used to show the Command Palette, "sspy" (short for Set Syntax: Python) is
used set the syntax of the current file to Python.
4. Use Goto Anything to quickly navigate between files, even in the largest
projects. Ctrl+P shows Goto Anything, and typing then filters on file and
directory names.
5. Goto Anything can also be used to show a function, line or word within a
file. Type @ after a file name to filter on symbols.

6. Find and Replace with regular expressions. Example, unwanted whitespace


can be removed by using the regex " +" to find groups of spaces, which are
then selected simultaneously with the Find All button.
For more information about Sublime Text visit
https://www.sublimetext.com/.

How to use auto-completion function of Sublime?


Sublime has auto-complete function where suggestions will pop up and
you can select the syntax that you need.

Just make sure that you set the syntax so that the auto-complete function
will suggest syntax that is related to that particular language that you use. You
can press the tab for completing the arguments of the syntax.

Using this, you can complete a project within a couple of hours.

How to run an Android App project using Sublime


Text?
With Corona Editor integrated to Sublime, you can run your projects by
simply pressing ctrl+b, +f10 or by going to Tools - > Build from Sublime
menu.
Remember that running your projects from Sublime Text requires opening
the main.lua file in the Editor or any other Lua file that resides in the root
folder project alongside main.lua file. If you run your project with a file
from a subfolder of your project this error will appear.

This error occurred because I run my project while the opened file was
inside a subfolder lib while my main.lua resides outside of that folder.
Thats why it prompts that the main.lua file was not found.
Before we move on, here are some Sublime Text useful keyboard
shortcuts.
1. ctrl+] and ctrl+[ increase and decrease indent of the line.
2. ctrl+g go to line number. Using this you can quickly jump to lines
where an error occurred.
3. ctrl+h search and replace a word.
4. ctrl+f search for a word.
5. ctrl+r search for function name
6. ctrl+/ - comment a line or highlighted lines.
7. ctrl+shift+up moves a line or highlighted lines upward.
8. ctrl+shift+down moves a line or highlighted lines downward.

For the next chapters please download the project files here.
CHAPTER 3: BUILDING YOUR FIRST APP
Making your first App will be easy but your next Apps will be difficult but
challenging.

Go and create a simple App. Print a simple hello world to the simulator
output or build panel. Follow the instructions bellow.
1. Open Corona Simulator and go to File -> New Project. You can also use
the keyboard shortcut ctrl+n. Enter Hello World as the Application
Name. You can change the directory of your project just click Browse and
locate the directory that you want for the project. For now, we will let the
settings that way.

2. The folder of your project will pop up. Open the file main.lua to your
Sublime Text Editor. If opened via notepad then set the default application
for opening Lua files. You can do this by right clicking the Lua file
1. Right click the file. Open with -> Browse -> Locate the
sublime_text.exe.
2. Click ok then check the Always use the selected program to open
this kind of file. then click Ok.
3. Once the file is opened, write the following code and save it:
print(Hello World!);

4. Now go to Tools - > Build or simply press ctrl+bor +f10.


5. The Simulator will appear without the output window. Notice the panel
appeared below the editor?

6. Now change the previous code to the following:


local helloWorld = display.newText( "Hello World", display.contentCenterX,
display.contentCenterY, native.systemFont, 40 )

The output should look like this.


7. Go and build it to your device. Click the Simulator and go to File -> Build -
> Android or press the keyboard shortcut ctrl+bor +f10.

8. Android Build Setup will now appear. Note that you need internet
connection and JDK installed in your PC. Now, fill in the following
information needed.
Change the Target App Store to none and if you want to change the
directory where your App will be saved you can browse and locate the
directory that you want. For now, you will use the default values. If the
Simulator ask for a password, input android and save it and click Build.

9. Once completed, wait for Corona to notify you that building is complete.
Copy the file to your device. (This process is not recommended) Now look
for the App in your device and install it. If the App is blocked, enable your
device to install non-market Apps. Click the Settings icon on your device,
select Applications, and then check the box next to Unknown Sources. If
you cant locate the Unknown Sources, try under Lock Screen and
Security. For the complete documentation on how to build and test android
Apps using Corona, visit the offline version of Corona SDK documentation
that you pinned in your browser.
1. Open browser where you pin the offline version of Corona SDK
documentation.
2. Click Guides -> Look and click for Building and Distribution ->
Click Building and Signing Android.
3. Click Device installation.
10. When finished installing, look for the icon and launch it. And there you
have it.
CHAPTER 4: SIMULTANEOUS DEVICE T ESTING
Corona has a feature where you can test your App in real time. To be able to
use Live Builds on Windows, you need to install iTunes. This feature requires
Corona Daily Build 2016.2993 or later. Note that this will only work for
debug keystores.

Creating a Live Build


Live built Apps require internet connection. Open your build.settings
file and add the following code if not yet included. For more information about
permissions visit your Offline/Online Corona Documentation and go to
Guides-> Building/Distribution -> Permissions.
android =
{
usesPermissions =
{
"android.permission.INTERNET",
},
},

Try to build your Hello World App and check Create Live Build.

After building the App, Corona Live Server will automatically start. Inside
the Corona Live Server is the project folder Hello World. Note that inside
your root folder is a file named .CoronaLiveBuild. This file syncs your
project from your PC to your installed App.
Starting the Corona Server
Distribute and install your App (the Live Build .apk file) to any Android
device. If the Corona Live Server doesnt automatically start, try to locate and
run it from Drive C:/Program Files/Corona Labs/Corona SDK or C:/Program
Files (x86)/Corona Labs/Corona SDK where Corona SDK is installed and
open Corona.LiveServer.exe.

If Corona Live Server is empty, you can drag and drop your projects
folder which contains the .CoronaLiveBuild file. You can also use the +
button and locate the project folder.

Connecting the Device and Testing


Launch your App from your device. Make sure that your device is
connected to the same network where your PC is connected. If you currently
dont have Wi-Fi connection but you already have the live build App installed
you can start a hotspot (recommended) from your device and connect your PC.
After some time, your App should be synchronizing now or restarting.
Now try to modify a code from your Hello World project like changing the text
Hello World to Live Build.

After saving the code, the App from your device should now restart and the
text displayed is now changed to Live Build.
Closing the Live Server
If you want to close and exit the Corona Live Server, go to the system tray
and Right click-> Exit. Note that the Server will not exit by just closing the
window.

For more information about Live Builds visit Offline/Online Corona


Documentation. Go to Guides-> Building and Distribution -> Generating
Live Builds.
CHAPTER 5: T HE PROJECT FILES
The project files are consists of code assets (libraries, modules, config.lua,
build.settings and the main.lua file) and non-code assets (icons, image files,
audio files). The Icons are used for your Apps launch icon which the user taps
when they want to start your Application. Icons must follow the standard
Android Icon names and sizes. The Image and Audio files are the multimedia
assets of your App. You can organize them inside a folder to make your project
neat. The config.lua is the configuration of your App where you can set the x
and y alignment of the screen, the width and height of your App, the content
scaling and the frame rate of your App. The build.settings file is where you set
the Apps supported orientation, permissions, features, screen support,
expansion files and plugins. The main.lua is where your App is being
initialized. It is the first file that is called by your App.
The build.settings
Your build.settings is required to contain a table with a key name
settings. This is where you are going to put all your Apps settings like
orientation. Since we are going to develop Android Apps we will only focus
to settings subject to Android Apps. Lets begin with the Apps Orientation.
settings =
{
orientation =
{
default = "portrait",
supported = { "portrait", "portraitUpsideDown" },
},
}

Orientation accepts 2 optional key values which are default and


supported. The default key contains a string value portrait which is the
default and initial launch orientation of the App and the supported key has a
table of strings portrait and portraitUpsideDown which are the
orientations supported by the App.
Supported values for orientation are the following:
1. portrait
2. portraitUpsideDown
3. landscapeLeft
4. landscapeRight

Android Permissions are the Apps permissions included into the


AndroidManifest.xml file. For example, your App needs internet connection.
You can add this permission by adding android.permission.INTERNET to
usesPermissions table inside android table.

settings =
{
android =
{
usesPermissions =
{
"android.permission.INTERNET",
"android.permission.WRITE_EXTERNAL_STORAGE", -- saving media and camera
support
"android.permission.ACCESS_FINE_LOCATION", -- allow access to GPS
"android.permission.ACCESS_COARSE_LOCATION", -- allows getting location from
WIFI/Cellular Service
},
},
}

Android Features are parameters that tells the Android App Store which
hardware does the App requires. You can do this by adding a feature inside the
usesFeatures table like the example below.
settings =
{
android =
{
usesFeatures =
{
{ name="android.hardware.camera", required=true }, -- required
{ name="android.hardware.location", required=false }, -- optional
{ name="android.hardware.location.gps", required=false }, -- optional
}
},
}

Note that if your App grants permission to use the camera, the Android
assumes that you also require this feature. In this case, all devices without
camera will unable to install your App. So if your App is granted a permission
that is optional, you can set the required key to false like the example above.
In addition, if you want your App to be categorized as Game in Google
Play, set isGame to true. If your App supports Android TV set supportsTV to
true.
settings = {
android = {
supportsTV = true,
isGame = true,
},
}

Other settings will be discussed later. So far these are the basic things that
you need to know about build.settings.
The config.lua
The config.lua file sets the basic configuration of your App. This file
consists of application table which has sub-table content.
application = {
content = {
-- Parameters
}
}

Android Apps should support multiple screen dimensions. Good thing


Corona does the hard work for us. Corona scales down or change the
displayed objects depending on the base content area that we set and also
substitutes image files with different resolution when needed. But in order for
Corona to do this, you should display your images dynamically by using
display.newImageRect function instead of display.newImage function. This will be
discussed later.
Here are the parameters that you can set up:
1. width the width of the screen for the App
2. height the width of the screen for the App
3. xAlign the x alignment of the screen. Accepts top, center and
bottom. Default is center.
4. yAlign the y alignment of the screen. Accepts top, center and
bottom. Default is center.
5. scale the scaling method. Accepts the following values:
1. letterbox scales the content area to fill the screen while preserving the
same aspect ratio. The entire content area will reside on the screen, but this
might result in "black bars" on devices with aspect ratios that differ from
your content aspect ratio. Note that you can still utilize this "blank" area
and fill it with visual elements by positioning them outside the content area.
2. zoomEven scales the content area to fill the screen while preserving the
same aspect ratio. Some content may "bleed" off the screen edges on
devices with aspect ratios that differ from your content aspect ratio.
3. zoomStretch - scales the content area to fill the entire screen. All content
will remain on the screen, but it may be stretched horizontally or vertically.
This mode is not recommended since it will typically distort the content
area.
6. fps frame rate. Values supported are 30 and 60 frames per second. Other
values will be ignored.
application = {
content = {
width = 320,
height = 480,
scale = "letterbox",
xAlign = "left",
yAlign = "top",
fps = 30
}
}
The Ultimate config.lua
The ultimate config.lua is a configuration shared in Coronalabs blog. It is
shared by Rob Miracle but the post is now went missing. This configuration is
flexible to all screen devices but it is only intended for games.
local aspectRatio = display.pixelHeight / display.pixelWidth
application = {
content = {
width = (aspectRatio > 1.5 and 800 or math.floor( 1200 / aspectRatio )),
height = (aspectRatio < 1.5 and 1200 or math.floor( 800 * aspectRatio )),
scale = "zoomStretch",
xAlign = "left",
yAlign = "top",
},
}

The variable aspectRatio is the scale factor for the current device. This is
where the width and height of the App will be based. If the aspectRatio is
greater than 1.5, width will set to 800 else it will be set to 1200 divided by
aspectRatio. In most cases the width is always set to 800. The same
computation is done with the height. This ensures that the width and height of
the App will be relative to 800x1200. The scale method is set to
zoomStretch since some App Store requires fullscreen and Apps with black
bars are discouraged, though you can still set it to letterbox. Dont worry, in
this configuration the zoomStretch will fit to any screen dimension and
image wont be stretched that much. Lastly, the xAlign and yAlign are set to
left and top. By default, the alignment of the screen is set to center. In
some cases the immersiveSticky mode drags the screen or objects towards
the edge when alignment was set to default. Note that the above config template
is intended for games. Since we will be creating Apps we will change 800 to
320 and 1200 to 480 to make the dimension relative to 320x480 which is the
standard dimension for Apps.

Icons
Android requires 6 different Icon that follows the standard Android icon
names and sizes. These icons should be located in your root folder alongside
with your main.lua file. You can create your own Icons using Photoshop or
other similar software.
Name Size (wxh)pixels
Icon-xxxhdpi.png 192x192
Icon-xxhdpi.png 144x144
Icon-xhdpi.png 96x96
Icon-hdpi.png 72x72
Icon-mdpi.png 48x48
Icon-ldpi.png 36x36

You can create your own Android Template Folder that consists of the
mentioned files above.

Rename the folder to Android Template. Every time you will create a
project, simply create a copy of the template and rename it to your Project
Application Name.

Lets recap what you have learned and what you have done so far:
1. You learned what Android is.
2. You also learned what an Android Application is.
3. You are introduced to the tools and IDE available online.
4. You downloaded the installers and files that you needed.
5. You installed, configured and activated the SDK and IDE.
6. You built your first simple App and installed it into your device.
7. You built your first live build App and able to test it in your device in
real time.
8. You learned about project files and have a template to start an Android
Application.
CHAPTER 6: STATUS BAR AND ANDROID SYSTEM
UI VISIBILITY
Status bar and System UI are the first thing that you want to change or modify
for your App before starting and building them.

What is Status Bar?


Status Bar is the bar at the top of the screen of your device where your
notifications, time, signal strength, and battery is located. In Applications the
status bar is sometimes translucent or dark. In Games, status bar is always
hidden.
Here is a list of modes that you can use in setting your status bar. Note that
status bar is only supported from Android 4.0 up to the latest version.
1. display.HiddenStatusBar status bar is hidden. (Default) Mostly used for
games and fullscreen Apps.
2. display.TranslucentStatusBar translucent status bar.
3. display.DarkStatusBar dark status bar.
4. display.DefaultStatusBar the default status bar.

How to Change Status Bar?


Pass one of these modes to the function display.setStatusBar. Using your
Live Built App (Hello World) you can test all of the modes above. To be able
to see the effect of translucent status bar you should change the default
background color.
What is Android System UI Visibility?
Android System UI is the status bar and navigation bar or the Soft Key Bar
which consists of the Back, Home and Menu buttons of the device. When
creating an App, the System UI is what you want to hide or change its behavior.
If you are creating a game and you want it to be in fullscreen mode, you can
hide the UI and make it reappear later using native.setProperty function. Here is
a list of UI modes:
1. immersiveSticky Supports Android Kitkat or higher. It will
make the status bar and navigation bar to disappear. User
can swipe from the top or bottom part of the device to
make the navigation and status bar to reappear. After
some time the System UI will disappear again.
2. immersive Supports Android Kitkat or higher. It will
hide the System UI and when the user swipes the screen
from the top or bottom, the System UI will reappear and
this time it will stay.
3. lowProfile Only supported on Android Ice Cream
Sandwich. It dims the navigation bar icons.
4. default resets the value.
Syntax: native.setProperty(androidSystemUiVisibility, mode).

For more information about Android System UI Visibility, visit the


Offline/Online Corona Documentation. API Reference-> native* ->
native.setProperty() -> androidSystemUiVisibility.
CHAPTER 7: UNDERSTANDING T ABLES,
FUNCTIONS, METHODS AND EVENTS LISTENERS
Corona SDK uses Lua as its code base. So its important to understand how
Lua works. Lua is a scripting Language which is intended to be used as a
powerful, lightweight scripting language for any program that needs one. If you
want to read a short introduction to Lua, go ahead and read it to the
Coronalabs Documentation. Go to Guides-> Getting Started-> Introduction
to Lua. If youre lazy to read it now, you can read it later, you can learn the
basic syntax or common syntax that you need along the way.

Tables
Tables in Lua are arrays that can be indexed not only with numbers but
also with strings. Lua tables can also have any values including functions
except for nil. To avoid confusions about indexing, lets call the integer index
as index and lets call the string index as property or key.
Name
t[1] Index
t[name] Property

Integer Indexed Table


Here is an example on how to initialize an empty table.
local t = {}

Here is an example on how to initialize a table and put values into it:
local t = {}
t[1] = 1
t[2] = 2
t[3] = hi

The above example is the same as: (Inline)


local t = {1, 2, hi}
The example above is a table with integer indices. You can access the
values by using brackets.
print(t[1]) output 1

String Indexed Table


Here is an example on how to initialize a table and put values into it using
string as index:
local t = {}
t[name] = Aj
t[age] = 23
t[msg] = hi

The above example is also the same with:


local t = {}
t.name = Aj
t.age = 23
t.msg = hi

Inline:
local t = {name = Aj, age = 2, msg = hi}

The example above is a table with string indices. You can access the
values by using brackets.
print(t[name]) output Aj

or using the . operator as property.


print(t.name) output Aj

The Length (#) Operator


You can get the length of a table by using the # operator. Note that only
integer indices will be counted for the length of a table.
local t = {1, 2, hi, age = 23, name = Aj, 100}
print(#t) output 4
Using the # operator to loop in a table with properties is a bad idea. You
cant access all of the content of the table with that approach. Use for
pairs(table_name) where k is the key or property name and v as the value.

Also remember that if a table has holes (nil), all elements will be
evaluated if the last element is not nil. If the last element is nil, only the last
non-nil value element will be evaluated and skips the rest.

As explained earlier, the # operator only counts an element with integer


indices. From the example above, the elements age = 23 and name = Aj are
ignored because they are properties, therefore the total length of the table is 6.
But since the table has holes or nil values and the last element value is nil it
only counts the last non-nil value element, the final length of the table is 3.
Explained by the picture below:

Now if the last element is a non-nil value element, all of the integer indices
will be counted including the nil value element.

Using Variables as index


Using variables as index or property is confusing at first. Just remember
that when using brackets in accessing a property of a table use double
quotation ( ) to indicate that it is a string. If omitted, the table will assume
that it is a variable name.
Using brackets and a string as index:
local t = {1, 2, hi, age = 23, name = Aj, 100}
print(t[age]) output 23

Using brackets and variable index as index:


local index = age
local t = {1, 2, hi, age = 23, name = Aj, 100}
print(t[index]) output 23

Where the variable index has a string value of age.


The common mistake is that programmers omit the double quote that is why
the result is nil.
local index = age
local t = {1, 2, hi, age = 23, name = Aj, 100}
print(t[age]) output error (nil value)

The variable age is not initialized resulting to nil.

Functions
Functions like in other Programming Languages, it executes a group of
statements or simply perform a task where the result can be returned. An
example is the built-in function print( ). A Function is composed of scope, a
name, body, optional argument and an optional return statement. Functions are
also variables that can be stored in a property that enables you to group them in
one table as a library like the math library. You can return multiple values as
well.

Declaring a Function
The following is an example of declaring a function:
local function getName( parameter )
local params = parameter
local name = params.name
return name
end

The local statement is the function scope. The function can only be
accessed through out the code where it is declared. The getName is the
function name which you can call for execution of the function. The parameter
is the argument for the function. Inside the function is the body of the
function. It is a group of statements or process that executes when the function
is called. Lastly the return statement which returns a value to the handler.

Here are the common ways on how to declare a function.


Local declaration:
-- local declaration
local function function_name( )
-- body
end

local function_name = function( )


-- body
end

Global declaration:
-- global declaration
function function_name( )
-- body
end

function_name = function( )
-- body
end

Methods
What is a Method in Lua?
The difference of common Functions from Methods is their syntax and the
way they access the keyword self (the object itself). A common Function that is
stored in a property is called by the use of . dot operator while Methods are
called by the use of : colon operator.
object:getLabel()

Note the keyword self is the same with the keyword this in other
programming language.

Methods can access the keyword self without passing an argument self to
the function method.
function object:touch(e)
local target = self
end

While a function needs an argument self to be able to access the object.


function touchEvent(self, e)
local target = self
end
How to construct Method?
In constructing a Method, you need to declare an object first and
construct a method.
local object = {}
object.text = this is a method
function object:getText()
return self.text
end
print(object:getText())

Note that Objects are represented by tables and no need to put a scope for
the method.

In addition, you can also evaluate if a method exist in an object by using


the . operator. This can be useful in some cases, for example the setFillColor
method for display objects. Image, text and sprite sheet display objects are
associated with this method while display.newGroup()is not associated with this
method. What if you grouped them into one table and you want to fill the color
or tint the objects by using a loop? The simulator will prompt an error that one
of the objects do not have a method setFillColor. Now, since we can evaluate if
a method exist we can simply set a condition. If object.setFillColor exists, then
fill it with color red else do nothing.
for i=1, n do
if (object[i].setFillColor) then
object[i]:setFillColor(1,0,0)
end
end

Note that in Lua, semicolons at the end of every statement are optional.

Events
Events are the interaction or the activities of the user or the system. Corona
has many different events including touch, tap, accelerometer, collision, key,
sprite, system, timer, orientation etc. Events can be registered using the
method object:addEventListener(eventName, eventListener). Where the eventName is
the name of the event and eventListener is the function listener.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )

function rect:touch( e )
print( e.phase )
end

-- register event listener


rect:addEventListener( "touch", rect )

There are many ways on how to declare a listener and how to register
them. The above example is using an object method and registering the object
as object listener where e is the event argument.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )

local function any_name( e )


print( e.phase )
end

-- register event listener


rect:addEventListener( "touch", any_name )

The above example is using a function listener which is inconvenient


because some properties or variables may not be in scope.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )

local function any_name( self, e )


print( e.phase )
end

-- register listener event


rect.touch = any_name -- function passed to an object method
rect:addEventListener( "touch", rect )

The above example is passing a function to the object method rect.touch.


This method is the same as the first example but this time the function any_name
can be shared to other objects. Using this method always remember to pass the
argument self as the first argument to the function. Passing a function to an
object method requires the keyword self, if omitted, the first argument passed
to the function will be used by the method as self or the object.
local rect = display.newRect( display.contentCenterX, display.contentCenterY, 400, 200 )
rect:setFillColor( 0.4, 0.45, 0.8 )

local function any_name( e )


print( e.phase ) -- error
end

-- register listener event


rect.touch = any_name
rect:addEventListener( "touch", rect )

The example above will result to an error of nil value. In this case, e is now
considered the self or the object where e.phase property doesnt exist.
For complete information about Events, visit Corona Documentation. Go to
Guides -> Events and Listeners-> Basic Interactivity and Event Detection.
CHAPTER 8: T IPS AND UNDERSTANDING ERRORS
As a developer, you will occasionally encounter problems in your code,
including incorrect logic, improper usage of an API, or any number of other
issues.

Runtime Errors
Runtime Errors are those that crashes your App. These will abort the
program and display an information box which includes the filename where the
error occurred, the line where the error occurred, the reason for the error and
the stack trace which can help you locate the origin of the error.

Here are some of the basic reason of errors.


1. Nil value error.
- You might enter or using a different data type than the data type the
statement is expecting. For example:

Arithmetic statements expects number values not table, string or nil. This
is also caused by wrong call or usage of APIs.

2. Upvalue error
- This is caused by using the same name or identifier/variable name and
assigning it with two different data types. For example from the
Coronalabs blog post:

The name gameover is initially a function, then later on used as a display


object. The next run or call to gameover() function will give you an
upvalue error since the function gameover is no longer exist. Simply
change the name of the display object.
3. Unexpected Symbol
- This is caused by extra character inserted to your code or incomplete
statement like omitting the = sign. For example:

Before the statement local is where the error occurred. In this example,
the previous statement is incomplete. Line 3 is an incomplete statement.

4. Expected to close error


- This is caused by unclosed function, loop or if else condition. The
statement end is omitted.

Heres the code:

Tips
To avoid some common issues, we should be aware of them and use some
tools to help us resolve them.
1. Proper Indention
- Using Integrated Development Environment (IDE), this will help you
automatically indent your codes. When your code is indented correctly, it
will be easy to see if there are omitted end statement in your code and
the block of codes will be easy to read.
2. Descriptive Naming
- Using a name with the same behavior it represent is easier to read and
other developers may understand or know what you are trying to
achieve. For example, if you are adding numbers and created a function
for the addition process, you should name the function addition or
add so that other developers know that the function you made is for
adding numbers.
3. Device Consideration
- The simulator is not case sensitive when it comes to project files, but
when an App is built for actual device, it causes errors since the device
is case sensitive. For example, the filename background.PNG is
different from background.png when it comes to the actual device. So
use the same case when accessing filenames and use lowercase for file
extensions.

For the complete guide for debugging errors, visit Coronalabs


documentation and go to Guides-> Basics-> Debugging Guide. If you are
tired and really dont know what to do, reach out our fellow developers from
Corona Forum. There you can post and ask for help but before posting your
problems, dont forget to search first if your problem already exist in the forum
and if already solved.
CHAPTER 9: CREATING A SIMPLE IO APP
The following steps will teach you how to create a simple input/output App
with the help of widget and native API. You can still use the Live Build Hello
World App in this chapter or create a new project folder by duplicating your
Android Template. If you want to use the live built App then go ahead and
connect your Laptop/PC and Device to the same network. Open the Corona
Server and drag and drop the Hello World Project folder. After connecting the
Device and your PC, open the Hello World App from your Device. The App
will restart and sync with your current codes from your PC. If you are having
problems with connecting your Device from the server, read and follow the
instructions from Chapter 3 carefully. I recommend connecting your Device to
a hotspot. If everything works just fine then lets start.

Interface
Open the main.lua file from your Hello World Project. Clear the content
and save it. Notice that your App from your device restarts. Now your App is
empty and turned into a black blank App. Lets change the default background
color of your App.
display.setDefault( "background", 1, 1, 1 ) -- white

The function display.setDefault() accepts key and colors. Colors in Corona


are represented by a RGBA table red, green, blue which value is from 0 to 1
and an optional alpha for opacity. You can enter { 1, 0, 0 } to make it red or {
0, 1, 0 } to make it green or { 0, 0, 1 } to make it blue. After saving the code,
the Device restarts. Your App background should be white or the color that you
selected by now. The next thing we need to do is to require or include the API
or libraries that we will need.
-- include widget API
local widget = require ("widget")

This doesnt have effect yet since we only require the API. The next thing
we need to do is to declare constants.
-- constants
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight

For more information about display content constants, go to Coronas


documentation and click Guides-> Project Configuration-> Content
Properties.
Next is to declare the needed handlers that will hold objects and data.
-- reference names
local label
local inputText
local submitBtn
local padding = 20

You will also learn in this chapter on how to display a label, text field and
a button. The output later on should look like this:

Text Display Object


Now do this step by step. Display a label which is a text display object.
In the next line of code, type in
label = display.newTe

Using Corona Editor integrated to Sublime Text, you will see suggestions
like this:

Press enter and the syntax is automatically completed for you.

Notice the brackets in the syntax? These are optional arguments. Delete
parentGroup and use tab to go to the next argument. Fill in the text, x, y, font and
fontSize like the code below:
label = display.newText( "Name:", 0, 0, native.systemFont, 20 )

The Name: is the text displayed to the Device, x and y are the coordinates
of the text object, native.systemFont is the font of the text field and 20 for the
fontSize of the text. Note that coordinates [0,0] is located at the top left corner
of the screen and every display object has an anchor point (center) where the
coordinates of the object will be based on. Since the background color is
white and the default color for text object is white, we need to change the color
of the text object to be able for use to see the label.
label:setFillColor( 0.2, 0.2, 0.2 )

The setFillColor method is only for display objects like text, image and
shapes. For more information about setFillColor go to Coronalabs
Documentation and click API Reference-> press ctrl+f and enter
setFillColor -> click the highlighted link.
As you can see, the label is on the top left corner of the screen.
Lets go and try to change the anchor point of the object. If you are familiar
with Photoshop, anchor point is the circle inside an object when using
transform tool. This is where they based the rotation and coordinates of the
object. Use the . operator and set anchorX and anchorY any value from 0 to 1.
The default value is 0.5. Go ahead and experiment.
label.anchorX = 0

Here is the output from the above code:

Now, we will change the coordinates of the object to 10 pixels from left
and 80 pixels up from center y.
label.x = 10
label.y = centerY - 80
For more information about display.newText() go to Coronalabs
documentation -> API Reference-> press ctrl+f and enter newText and
click the highlighted link.

Native Text Field


We already have the label, next is the text field. Text Fields in Corona are
native, which dont follow the rules applied on display objects and they always
appear at the top of display objects. Use the autocomplete of Sublime Text and
code the following.
inputText = native.newTextField( centerX, 0, _W-50, 60 )

The text field is handled by inputText and positioned at the center x


coordinates and positioned at 0 in y coordinates. The width of the text field is
the width of the screen minus 50 pixels and 60 pixels in height. Now, we will
reposition the y coordinates of the text field relative to labels y coordinates.
inputText.y = label.contentBounds.yMax + (inputText.height * 0.5)

The contentBounds is a read-only table that is available for display objects.


The following are the contentBounds properties:
1. xMin minimum x boundary of the object.
2. xMax maximum x boundary of the object.
3. yMin minimum y boundary of the object.
4. yMax maximum y boundary of the object.
To be able to set the y of inputText below the label, we need to get the y
max boundary of label then add the half height (not the whole height because
the anchor point is the center of the object) of the inputText. Next is to set a
placeholder or hint for the text field.
inputText.placeholder = "Enter your name:"

In some cases, we may want to change the font size and the font of the text
field. We can do this by:
inputText.size = 20
inputText.font = native.newFont( "Arial.ttf", 30 )

The size property will set the font size to 20 pixels. The font property
changes the font of the text field together with the font size. For now only the
size property will be used to our App. Changing the font size wont change the
height of the text field, if you want to make the text field to resize and fit the
font size just call the following method.
inputText:resizeHeightToFitFont()

We can also change the inputType of the text field by changing the value of
the inputType property of the text field.
inputText.inputType = "default"

Values supported are:


"default" the default keyboard, supporting general text, numbers and
punctuation.
" number" a numeric keypad.
" phone" a keypad for entering phone numbers.
" url" a keyboard for entering website URLs.
" email" a keyboard for entering email addresses.

Button Widget
Now we have an object to get an input from the user, what we need next is
an object that will process the input value and will output a message. This time
we will create a button widget. We already required the widget API so all we
have to do now is to display and create a button.
submitBtn = widget.newButton( {
label = "Submit",
> emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = _W-50,
height = 60,
cornerRadius = 5,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})

Let me discuss the above code line by line. The first line is the creation of
the submit button. The function widget.newButton accepts a table as argument.
1. label is the label or text for the button.
2. onRelease is an event listener that is triggered when the user released his
finger from the screen. We will create a function for that later.
3. emboss Boolean value. Makes the label embossed or not.

The next few properties are for visual options.


4. shape is for the shape that we want to use as button. Values can be
circle, polygon, rect and roundedRect.
5. width and height accepts any positive integer value. Width is set to the
screen width 50 pixels and height of 60 pixels.
6. cornerRadius accepts an integer value from 0 to half of which has the
minimum width or height. Available for rounded rect button shapes only.
7. labelColor is the color of the label text in the button, it accepts a table with
2 properties default for the default color of the text and over for the color of
the text when clicked or active.
8. fillColor this is the color of the shape. Like labelColor, this property also
accepts a table with 2 properties, the default and over state of the button.

For more information about widget buttons, please visit Coronalabs


documentation and go to API Reference-> press ctrl+f and type in
newButton. Click the highlighted link.
Set the x coordinates of the button to the center and set the y coordinates
below the text field.
submitBtn.x = centerX
submitBtn.y = inputText.contentBounds.yMax + (submitBtn.height * 0.5) + padding

We only displayed a button and it does nothing until we create a function


for it. Go ahead and create a function above the submitBtn. Type local function
and press enter. The autocomplete function of Sublime Text will write the rest
of the syntax for you. Write onRelease as the function name, press tab and enter
self, e. Remember that in passing a function to an event listener always
include the keyword self.
local function onRelease( self, e )
native.setKeyboardFocus( nil )
if (inputText.text:len() > 0) then
native.showAlert( "Simple App", "Hi "..inputText.text.."!", {"Ok"} )
end
end

The native.setKeyboardFocus() function is to set the focus of the keyboard to


a text field. Pass the text field handler to set the focus to that text field and pass
nil to hide the keyboard from the screen or removing the focus of the text field.
The if condition set inside the function is to show the alert only if the text
field is not empty. The method len() is a method for strings. It returns the
number of character a string have. The text property contains the string entered
into the inputText (text field).

Native Alerts
Lastly is showing an alert or dialog to the user. The native.showAlert accepts the
following arguments:
1. title the title of the alert.
2. message the message of the alert.
3. buttonLabels table of string for the corresponding button labels. Example:
{Ok,Cancel}.
4. listener the function listener that to be called when the user taps a button
from the alert. The listener can be either a function listener or a table
listener and the event dispatched to the listener will have the following
additional properties:
1. event.action represents how the alert was dismissed: "cancelled"
indicates that native.cancelAlert() was called to close the alert, while
"clicked" indicates that the user clicked on a button to close the alert.
2. event.index is the index of the button pressed. It corresponds to the index
in the buttonLabels parameter. First button from the left is 1 and the next
button is 2 and so on.

Note that in the message argument ("Hi "..inputText.text.."!"), the two dots (..)
represents concatenation in Lua. Identifiers or handlers in Lua accepts any
value including functions except for nil and automatically converts the value
when being processed. For example:
local a = 1
local b = "2"
local c = a + b
print( c )

The variable b has a value of a string 2 but used in an arithmetic


statement and resulting no error. But if the variable b has a value of s and
used in an arithmetic statement, this will now result an error.
local a = 1
local b = "s"
local c = a + b
print( c ) -- error (a string value)

Here is our complete code so far.


display.setDefault( "background", 1, 1, 1 ) -- white

-- include widget API


local widget = require ("widget")
-- constants
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight
-- reference names
local label
local inputText
local submitBtn
local padding = 20
-- label
label = display.newText( "Name:", 0, 0, native.systemFont, 20 )
label:setFillColor( 0.2 )
label.anchorX = 0
label.x = 10
label.y = centerY - 80

-- text field
inputText = native.newTextField( centerX, 0, _W-50, 60 )
inputText.y = label.contentBounds.yMax + (inputText.height * 0.5)
inputText.placeholder = "Enter your name:"
inputText.inputType = "default"
inputText.size = 20
inputText:resizeHeightToFitFont()

local function onRelease( self, e )


native.setKeyboardFocus( nil )
if (inputText.text:len() > 0) then
native.showAlert( "Simple App", "Hi "..inputText.text.."!", {"Ok"} )
end
end
-- submit button
submitBtn = widget.newButton( {
label = "Submit",
> emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = _W-50,
height = 60,
cornerRadius = 5,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
submitBtn.x = centerX
submitBtn.y = inputText.contentBounds.yMax + (submitBtn.height * 0.5) + padding

Now, test the App and make experiments like odd or even or leap year.
CHAPTER 10: SIMPLE APP USING COMPOSER API
In this chapter we will learn how to create scenes using Composer API.

Scenes
Scenes are like pages in a book, scenes in a story or levels in a game. In
some cases there are some scenes that are overlaying another scene like
dialogs. These scenes are called overlay scenes. They are temporarily
overlaying the current scene to give information or another task to the user.
Composer API is a scene creation and management library that helps you
organize objects in a scene. However, Composer only allows one overlay
scene at a time. Corona also provided a template for using Composer Scenes.
Composer Scenes are individual Lua files that can be called by
composer.gotoScene or composer.showOverlay function. In displaying the initial
scene you need to initialize the composer API from the main.lua and go to
initial scene by using composer.gotoScene function. Scene name is the scene
filename without .lua file extension.
Example:
local composer = require( "composer" )
composer.gotoScene( "menu" )

Assuming that menu.lua file exists and contains the Composer Scene
Template. Note that I wont discuss all of the Composer APIs functions but you
can read it all at Coronalabs documentation. What Im going to show you is
how to create a Simple App using Composer API and help you understand
Composer in actual development and on how you can use the parent scene
custom methods on your overlay scenes.
1. Create a copy of your Template and rename it to Scene App or create a
new Project.
2. Go to the simulator Sample Apps. Click help from menu and click Sample
Projects -> Select Interface and open Composer project.
3. Go to File-> Show Project Files.

4. Copy the scenetemplate.lua file and paste it to your project.


5. Create 1 more copy and rename them to menu.lua and view.lua.
6. Go back to the main.lua file and write the following code:
display.setStatusBar( display.HiddenStatusBar )
local composer = require("composer")
composer.gotoScene( "menu" )

The first line hides the status bar. The second line requires the Composer
Library to our code. The last line moves the scene to menu. The main.lua
is not a scene, this is where we will initialize the composer. Now look at
the output through live build or run your code to the simulator by pressing
ctrl+bor +f10. Error sometimes wont appear on live builds so run
it also to your simulator just in case that you cant see the errors from the
live built App.
7. Open the menu.lua file and at the upper part of the code require widget API.
local widget = require( "widget" )

8. Declare handle bg and button after the require statements. The reason why
we declare it outside the methods is that we need them to be accessible
throughout the entire code.
local composer = require( "composer" )
local widget = require( "widget" )
local scene = composer.newScene()

local bg, button -- handles

9. Inside the scene:create method is where you will display or initialize the
scene. Write the following code:
bg = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight )
bg:setFillColor( 0.8, 0.2, 0.2 )

This is our simple background for the menu scene. It is positioned to the
center of the screen. We set its color to Red.
10. Below the bg initialize a widget button that will bring us to the view scene
later. We will create a simple rounded rectangle and position it to the center
of the screen. Dont forget to insert the objects to the sceneGroup. The
sceneGroup will hold all of the display objects inside the scene so if you
forgot to insert the objects they will float at the surface of the screen.

button = widget.newButton( {
label = "Go to View Scene >>",
( self, e )
composer.gotoScene( "view", {effect = "slideLeft", time = 200} )
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)

The additional parameters added to the gotoScene function are the effect and
time of the transition. You can view the full information about effects for
scenes go to Coronalabs Documentation -> API Reference -> press ctrl+f
enter gotoScene and click the highlighted link.
11. Before we go to the next scene. Remember to remove the display objects if
you dont need them anymore. You can do this inside the scene:destroy
method. The method object:removeSelf() removes the display object from the
screen but the memory is not yet released. To release used memory assign
nil to the handler.
print(menu destroyed)
bg:removeSelf( ); bg = nil;
button:removeSelf( ); button = nil;

Note that scene:destroy is only called when the composer.removeScene function


is called. For us to know if the scene was successfully destroyed, we will
print something for that.
12. Lastly, you can remove the methods that you didnt use like show and hide
methods along with their scene:addEventListener.
Here is our complete code for menu.lua file:
local composer = require( "composer" )
local widget = require( "widget" )
local scene = composer.newScene()

local bg, button


---------------------------------------------------------------------------------
function scene:create( event )
local sceneGroup = self.view

bg = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY,


display.contentWidth, display.contentHeight )
bg:setFillColor( 0.8, 0.2, 0.2 )

button = widget.newButton( {
label = "Go to View Scene >>",
( self, e )
composer.gotoScene( "view", {effect = "slideLeft", time = 200} )
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)
end

function scene:destroy( event )


local sceneGroup = self.view
print(menu destroyed)
bg:removeSelf( ); bg = nil;
button:removeSelf( ); button = nil;

end

---------------------------------------------------------------------------------
-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "destroy", scene )
---------------------------------------------------------------------------------
return scene

13. Open the view.lua file and just like menu.lua we will require the widget API
and declare handlers bg and button.
14. We will initialize the bg and button the same manner we did in menu.lua file.
The difference is the bgs fill color which we will set to blue (0.2, 0.2, 0.8)
and the function composer.gotoScene arguments inside the onRelease function
of button.
button = widget.newButton( {
label = "<<Go to Menu Scene",
( self, e )
composer.gotoScene( "menu", {effect = "slideRight", time = 200} )-- <<
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)

In menu.lua file, we passed an argument view which is the scene name


or the view.lua file without .lua extension. Now try to tap the button
from the simulator or device.
15. Inside the scene:show method, insert the following code inside the did
phase.
composer.removeScene( menu )

The function composer.removeScene removes a scene including its objects.


This time when the scene goes to view scene, your terminal will print
menu destroyed. This means that the menu scene is destroyed.
16. Remove the methods that you did not use.
Overlay Scene
Lets create another scene that will overlay our menu scene. Just like what
we did before, you need to create a copy of the composer template and rename
it to overlay.lua. We will display the same objects but this time we will
create a dim background and shorten the main background.
1. Open overlay.lua and require widget API and declare bg, dim and button
handlers.
2. Inside the scene:create method, write the following codes:
dim = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight )
dim:setFillColor( 0 )
dim.alpha = 0

bg = display.newRect( sceneGroup, display.contentCenterX, display.contentCenterY, 300,


300 )
bg:setFillColor( 0.2, 0.2, 0.8 )

Dim is a background that darkens the screen when the overlay fully
displayed on the screen. We will transition it later on scene:show method.
The property alpha is the opacity of the object. Setting it to 0 will make
the object invisible. The bgs width and height is set to 300 so we can
see the dim and the current scene behind it.
3. Inside the scene:show under the phase did, insert the following code:
transition.to( dim, {alpha = 0.5, time = 200} )

This will show the dim within 200 milliseconds.


4. Lets go back to the menu.lua file and change the button label and its
onRelease function.
label = "Show overlay",
( self, e )
composer.showOverlay( "overlay", {isModal = true, effect = "zoomOutInFade",
time = 200} )
end,

The function composer.showOverlay shows a scene as an overlay. Any


scene can be an overlay by calling this function. The parameter isModal if
set to true disables the current scene from getting touch events. The
effect parameter is the transition effect and time is the time of the
transition.
5. We already have the overlay working. We just need a button that will
hide the overlay.
button = widget.newButton( {
label = "Hide Overlay",
( self, e )
transition.cancel( dim )
dim.alpha = 0
composer.hideOverlay( "zoomOutInFade", 200 )
end,
emboss = false,
-- Properties for a rounded rectangle button
shape = "roundedRect",
width = 300,
height = 80,
cornerRadius = 5,
x = bg.x,
y = bg.y,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
sceneGroup:insert(button)

Inside the onRelease function, we cancel the transition of the dim since the
user may tap or hide the overlay while the transition is still running. We
also set its alpha to 0 and call for the function composer.hideOverlay. It
will hide the overlay with transition effect zoomOutInFade with time 200
milliseconds. If you want to just hide the overlay without transitioning,
just omit the effect and time.

Calling a Parent Scene Method from an


Overlay
A parent scene is the current scene where the overlay scene is overlaying.
Parent Scene Method is a custom method that can be accessible by an
overlay scene inside the method scene:show and scene:hide. For example you
want to show an overlay with a list of names and when the user selects a name
and tapped the ok button the current scene will display the name and process it
whatever you want it to be. You can do this by accessing a parent method.
1. Go to menu.lua and create a simple custom method outside of scene
methods.
function scene:changeButtonLabel( )
button:setLabel( "Label Changed" )
end

This method will change the label of the button in the menu.lua.
2. Open overlay.lua and go to scene:hide method and write inside the did
phase:
if (parent) then
parent:changeButtonLabel()
end

3. The widgets button in the menu will change into Label changed after
hiding the overlay.

Wrapping Up
The Composer API must be initialized in the main.lua file and set the initial
scene to show using composer.gotoScene function. Composer scenes when
called for the first time calls the create method to initialize the scene view.
After creating the scene view the Composer Scene will now call for the
show method which has two phases, the will and did phase. The will
phase is when the scene is still off-screen and currently transitioning while the
did phase is when the scene is already onscreen. The did phase is where
you can start your animations, timers and music.
Before the current scene will go to the next scene, the hide method of the
current scene will be called first. This method is where you can cancel
transition, timers and remove event listeners. Like show method, this also has
two phases, the will and did phase. The will phase is when the scene is
still onscreen and the did phase is when the scene is completely removed
from the stage or now off-screen.
Lastly, the destroy method of the scene is called when composer.removeScene
is called. This method is where you want to put the removal of objects.
Parent methods are methods created outside the scene methods. This
custom methods are accessible by overlay scenes show and hide methods.
CHAPTER 11: CREATING A SIMPLE MOVIE LIST
APP
In this chapter we will learn about how to use a widget table view to create a
list of movie titles and display its details by the help of composer API. Create
a copy of the Template Project folder and rename it to Movie List App.

The interface will be simple. The main menu view will have a simple App
bar at the top of the screen and a table view as the content. The detail view
will have a simple App bar and text objects for the details of the movie
selected.
Movie List Module
A module is a part of a program that does a specific task. In Lua, modules
are simply table objects. Create a new file and save it as movies.lua. Open
the file and write the following.

local M = {}

M[1] = {
title = "Transformers",
description = "Science Fiction Movie",
year = "2016",
}
M[2] = {
title = "The Avengers Age of Ultron",
description = "Science Fiction",
year = "2016",
}
M[3] = {
title = "Batman",
description = "Fiction, Action",
year = "2016",
}
M[4] = {
title = "Superman the Dawn of Justice",
description = "Fiction, Action",
year = "2016",
}
M[5] = {
title = "The Suicide Squad",
description = "Fiction, Action",
year = "2016",
}

return M

In creating modules, always remember to write the return statement at


very last line of the code. This will return our table M which is the entire
movie list.

Open the main.lua file and configure the first scene to display including the
background color.
display.setStatusBar( display.HiddenStatusBar )
display.setDefault( "background", 0.9, 0.9, 0.9 ) -- light grey
local composer = require("composer")
composer.gotoScene( "menu" )

Menu Scene Interface


Copy and paste the scenetemplate.lua file for composer template and
rename it to menu.lua. Do the same with the details view and name it
view.lua. Open the menu.lua file and require the needed modules and APIs.
-- require needed modules and APIs
local widget = require( "widget" )
local movieList = require( "movies" )-- movies list module

In requiring a module to your code, simply use the require function and pass
the directory of the module without the .lua extension. If your module is inside
a subfolder, use a dot (.) to separate the folder names from the filename. For
example:
local movieList = require( "lib.movies" )

The movies.lua file is inside a subfolder lib.

Next is to declare handles.


-- declare reference
local appBar, title, tableView

We will need the 3 handlers that will hold the objects such as the App Bar,
App title, and the table view.
Next is to declare constant variables. Localizing variables is much faster
compared to non-local variables. We will declare local constants for the
screen dimensions.
-- declare constans
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight

Now we will display our App Bar and the Title of the App. Write the
following codes inside the create method of the scene.
appBar = display.newRect( sceneGroup, centerX, 0, _W, 56 )
appBar.anchorY = 0

title = display.newText( sceneGroup, "Movie List", centerX, (appBar.height * 0.5),


native.systemFont, 18 )
title:setFillColor( 0.2 )

This will display a white bar at the top of the screen and Title text in the
middle of the App Bar. Note that sceneGroup holds the entire scene objects.

We will now create a table view widget where we will display the movie
titles. Write the following code below the title object code.
tableView = widget.newTableView( {
width = _W,
height = _H - appBar.contentBounds.yMax,
> > hideBackground = true,
isBounceEnabled = false,
rowTouchDelay = 10,
x = centerX,
y = appBar.contentBounds.yMax + 3,
})
tableView.anchorY = 0
sceneGroup:insert(tableView)

Syntax: widget.newTableView( options )


The table view widget accepts a single argument options which is a table.
We will discuss about the parameters that we used.
width, height (optional)
- The width and height of the table view
onRowRender (optional)
- A function used to render rows. This function is called when row is
added via object:insertRow() or re-rendered using object:reloadData().
onRowTouch(optional)
- Function used for touch/tap events. In this listener function, the
event.phase values include "tap", "press", "release", "swipeLeft", and
"swipeRight". In addition, event.target is a reference to the row that was
interacted with and event.target.index is the index number of that row.
hideBackground (optional)
- If true, the background of the table view will be hidden, but still
receives touches.
isBounceEnabled (optional)
- If set to false, the table view will simply stop scrolling when it
reaches the upper or lower limit. The default value is true.
rowTouchDelay (optional)
- Specifies the delay, in milliseconds, until the row touch event is
propagated. Default is 110 milliseconds.
x, y (optional)
- The x and y coordinates of the widget.

Nothing will happen to the interface yet until we add rows to our table
view widget. Lets insert row base on the number of movies we have. Note
that # denotes the length of a table.
for i=1, #movieList do
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.9, 0.9, 0.9}, over={0.2, 0.2, 0.2, 0.5} },
})
end

The method tableView:insertRow() accepts a table with the following parameters:


id (optional)
- An optional identification to assign to the row.
rowHeight (optional)
- The height of the row.
rowColor (optional)
- A table of two states (default and over state) of the row in RGB+A
color settings.
Example: rowColor = { default={ 1, 1, 1 }, over={ 1, 0.5, 0, 0.2 } }
lineColor (optional)
- A table of RGB+A color settings for the line.
Example: lineColor = { 0.5, 0.5, 0.5 }
isCategory (optional)
- If true, the row will be rendered as a category row. Category rows
"stick" to the top of the table view as the user scrolls, indicating that
the rows underneath are part of that category.
params (optional)
- A table which can contain information pertaining to the specific
row. This information can then be accessed (read) in the row
rendering function via event.row.params and in the row touch listener
via event.target.params.
This will calls the onRowRender function. Right now you are looking at an
empty table. Lets declare onRowRender. Write the following code before the
tableView declaration.
local function onRowRender( e )
local row = e.row
local contentWidth = row.width
local contentHeight = row.height
local index = row.index

local movieTitle = display.newText( row, movieList[index].title, 20, contentHeight * 0.5,


native.systemFont, 14 )
movieTitle.anchorX = 0
movieTitle:setFillColor( 0.2 )
end

The e.row is the parent group that holds all the objects in the row. The
contentWidth and contentHeight are the cache width and height of the row. The
index is the current index of the row. The movieTitle is the title of the movie.
You can now see the list of movies but you cant tap them yet since we didnt
declare the onRowTouch function yet. Below the onRowRender function, write the
following codes.
local function onRowTouch( e )
local phase = e.phase
local index = e.target.index
if (phase == "release") then
composer.gotoScene( "view", {effect = "slideLeft", time = 200, params = {id = index}} )
end
return true
end

This function will be called when the user taps the row. The e.phase is the
phase of the touch event and the index is the row index. Just like what we
discussed before, this function has the following phases:
tap the user taps the row.
press the user press the row (the finger is on the screen).
release the user releases the row (removes the finger from the
screen).
swipeLeft the user swipes the row from right to left.
swipeRight the user swipes the row from left to right.
In our case, the scene will go to Detail scene when the user releases its
touch from the row passing an optional table with property or parameter id as
custom data. We will use this custom data later to select the movie details
from the movie list.

Detail Scene Interface


If you run the project, you can now select titles to view but the Detail Scene
is still blank. To be able to display the details, we will need the index of the
selected movie and use that to get the details from the movie list. Lets set up
first the Detail Scene. In the same manner, require the widget API and movies
module.
local widget = require( "widget" )
local movieList = require( "movies" )

Declare some reference names that will hold our objects, constant and non-
constant variables.

local appBar, title, backBtn


local movieTitle
local movieDescription
local movieYear
local labelTitle
local labelDescription
local labelYear
-- constants
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight
local padding = 20

We have the appBar, title and the backBtn for basic App interface. The
movieTitle, movieDescription, and movieYear are the holder for movie details
which are text objects. The labelTitle, labelDescription, and labelYear are the
holder for the description labels.
The next identifiers are constant variables used for screen dimensions
reference. Lets create the interface. Just like the menu, we will create the
appBar and title in the same manner inside the create scene method. We will
also create a widget button to return us to the menu.
appBar = display.newRect( sceneGroup, centerX, 0, _W, 56 )
appBar.anchorY = 0

title = display.newText( sceneGroup, "Details", centerX, (appBar.height * 0.5), native.systemFont,


18 )
title:setFillColor( 0.2 )

backBtn = widget.newButton( {
label = "Back",
fontSize = 18,
font = native.systemFont,
( self, e )
composer.gotoScene( "menu", {effect = "slideRight", time = 200} )
end,
width = 32,
height = 32,
x = padding,
y = appBar.height * 0.5,
labelColor = {default={0.2, 0.2, 0.2}, over={0.8, 0.8, 0.8}},
})
backBtn.anchorX = 0
sceneGroup:insert(backBtn)

Run the project and you can now navigate from the menu to Detail Scene.
Lets display the title label. Write the following below the backBtn.
labelTitle = display.newText( sceneGroup, "Title", padding, appBar.contentBounds.yMax,
native.systemFont, 14 )
labelTitle.y = labelTitle.y + (labelTitle.height * 0.5) + padding
labelTitle.anchorX = 0
labelTitle:setFillColor( 0.1 )

This will display a text object below the appBar with font size of 14. Next
we will display the title of the movie.
movieTitle = display.newText( {
parent = sceneGroup,
text = movieList[id].title,
x = padding,
y = labelTitle.contentBounds.yMax,
font = native.systemFont,
fontSize = 20,
width = _W - (padding * 2)
}
)
movieTitle.y = movieTitle.y + (movieTitle.height * 0.5) + padding
movieTitle.anchorX = 0
movieTitle:setFillColor( 0.2 )

The display.newText function we used here is the new syntax for text objects,
it accepts a table with the following parameters.
1. parent (optional)
the parent group to insert the object.
2. text (required)
the text to display.
3. x, y (required)
the x and y coordinates for the object.
4. width, height (optional)
the width and height of the object.
5. font (optional)
the font style of the object which can be a constant, string or userdata.
1. The font family name (typeface name). You may obtain an array of
available font names via native.getFontNames().
2. Name of the font file in the Corona project's main resource
directory (alongside main.lua).
3. A font object returned by native.newFont().
4. A font constant such as native.systemFont or native.systemFontBold.
6. fontSize (optional)
the size of the text object in Corona content points.
7. align (optional)
This specifies the alignment of the text when the width is known,
meaning it either contains a newline or the width parameter is supplied.
Default value is "left". Valid values are "left", "center", or "right".
Note that align params is only available for the display.newText new syntax.

Before we run the project again, we need to add an additional code to be


able to get the details of the selected movie from the menu. Write the following
code after the initialization of sceneGroup.
------------------------------------------
function scene:create( event )
local sceneGroup = self.view
-- write it below here
local id = event.params and event.params.id or 1
The id is the passed custom data from the menu. The statement here used a
Lua ternary idiom. The statement goes like this:
If the event.params (custom data) exist and event.params.id (data parameter) exist then
Id gets the value of event.params.id
Else Id gets 1

The event.params that we are talking about here is the params table passed
after the user taps a row from the menu (inside onRowTouch function). The
event.params.id is the data passed which have the value of index.
composer.gotoScene( "view", {effect = "slideLeft", time = 200, params = {id = index}} )

We use the id to get the descriptions from the movie list that is declared
inside our movies module. For example, the user taps the 3rd row and the
custom data passed will be 3. That data will be passed to id and we will use it
to access the movie description. This will result to the following.
title = "Batman",
description = "Fiction, Action",
year = "2016",

We can access the title, description and year by using the dot operator:
movieList[id].title

Try to run the project and tap the 3rd row. The title should display
Batman.

Lets complete the details. Write the following codes:


labelDescription = display.newText( sceneGroup, "Description", padding,
movieTitle.contentBounds.yMax, native.systemFont, 14 )
labelDescription.y = labelDescription.y + (labelDescription.height * 0.5) + padding
labelDescription.anchorX = 0
labelDescription:setFillColor( 0.1 )

movieDescription = display.newText( {
parent = sceneGroup,
text = movieList[id].description,
x = padding,
y = labelDescription.contentBounds.yMax,
font = native.systemFont,
fontSize = 20,
width = _W - (padding * 2)
}
)
movieDescription.y = movieDescription.y + (movieDescription.height * 0.5) + padding
movieDescription.anchorX = 0
movieDescription:setFillColor( 0.2 )

Try to code the movieYear and labelYear by yourself the same manner we did
above and run the project.

If you notice, selecting a movie and going back to the menu, the next
selected movie wont display the correct details. This is because the Detail
Scene is already created so the displayed text objects are unchanged unless
you will destroy the scene and create the scene again. Lets do this by calling
composer.removeScene function inside the scene:show method at did phase of
menu scene. Go back to menu and write the following codes.
local prevScene = composer.getSceneName( "previous" )
if (prevScene) then
composer.removeScene( prevScene )
end

The composer.getSceneName function returns the name of a certain scene. This


function accepts one of the following string values:
1. previous the previous scene.
2. current the current scene.
3. overlay the currently overlaying scene.
We will only remove the scene if the previous scene exist. If we dont do
this, this will cause an error because initially the composer starts with menu
and the previous scene is nil.

Lastly, we will remove the objects and nil out their handlers to free its
memory. Write the code inside the scene:destroy method of Detail Scene.
appBar:removeSelf( ); appBar = nil;
title:removeSelf( ); title = nil;
backBtn:removeSelf( ); backBtn = nil;
movieTitle:removeSelf( ); movieTitle = nil;
movieDescription:removeSelf( ); movieDescription = nil;
movieYear:removeSelf( ); movieYear = nil;
The scene:destroy method will be called when the user returns to the menu
scene.
CHAPTER 12: USING SQLITE3
SQLite3 is a local database that is used to store data in the device. Corona
supports SQLite databases on all platforms. In this chapter we will learn about
how to use SQLite database in our App.

Creating and Connecting a Database


Create a new project or create a copy of Android Template and rename it to
SQLite_1. Open the main.lua file and require the SQLite3 library and open
the database named data.db. If the file doesnt exist, it will be created.
local sqlite3 = require( "sqlite3" )

local path = system.pathForFile( "data.db", system.DocumentsDirectory )


local db = sqlite3.open( path )

Note that in opening a database, you should always use the


system.pathForFile function to locate the file. Entering the plain filename string
doesnt always work.

Executing SQL Command


To execute a SQL command, use file:exec(sql_command). This is used for
creating a table, updating and deleting, inserting, appending and retrieving data
from a database. In case of error, this method will return a numerical code.
Lets use it for creating our table.
-- Set up the table if it doesn't exist
local tablesetup = [[CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, content1,
content2);]]
print( tablesetup )
db:exec( tablesetup )

This will create a table named test with columns id, content1 and
content2. The file will be created in the devices Documents Directory which
is a path for storing and retrieving files that need to persist between
application sessions. In the Corona Simulator, this will be in a sandboxed
folder on a per-application basis. You can view the directories/files via File
Show Project Sandbox.
To insert values, we will still use the same method.
-- Add rows with an auto index in 'id'. You don't need to specify a set of values because we're
populating all of them.
local testvalue = {}
testvalue[1] = "Hello"
testvalue[2] = "World"
testvalue[3] = "Lua"

local tablefill = [[INSERT INTO test VALUES (NULL, ']]..testvalue[1]..[[',']]..testvalue[2]..[['); ]]


local tablefill2 = [[INSERT INTO test VALUES (NULL, ']]..testvalue[2]..[[',']]..testvalue[1]..[[');
]]
local tablefill3 = [[INSERT INTO test VALUES (NULL, ']]..testvalue[1]..[[',']]..testvalue[3]..[[');
]]

db:exec( tablefill )
db:exec( tablefill2 )
db:exec( tablefill3 )

To be able for us to see the result, we will use file:nrows(sql_command) which


returns successive rows from the SQL statement. Each call to the iterator
returns a table in which the named fields correspond to the columns in the
database.
-- Print the table contents
for row in db:nrows("SELECT * FROM test") do
local text = row.content1 .. " " .. row.content2
local t = display.newText( text, 50, 30*row.id, nil, 16 )
t:setFillColor( 1, 0, 1 )
end

You can see the results to the terminal or build panel of Sublime Text. In
getting the current SQLite version use the function sqlite.version().

Closing the Connection


Lastly, closing the connection if you dont need it anymore. Use the
file:close() method. To make sure the connection is closed everytime the user
close your App, we will handle it by the use of a system event.
-- Handle the "applicationExit" event to close the database
local function onSystemEvent( event )
if ( event.type == "applicationExit" ) then
db:close()
end
end

-- Setup the event listener to catch "applicationExit"


Runtime:addEventListener( "system", onSystemEvent )
CHAPTER 13: A SIMPLE APP WITH DATABASE
Now that you know how to create and use SQLite database, we will now
start to create a simple App with Database. We will use a simple interface
which includes a native textfield, tableview and a button widget. All the objects
used in the interface are codes copied from the previous chapters. If you have
any question or problem related into it, please refer to the previous chapters.
This chapter is putting all of the things we have learned so far. Lets start with
creating a new project.

Setting up The Database


Open the simulator and create a new project and name it SQLite_2. Set
default background color to white and require needed libraries.
display.setDefault( "background", 1 ) -- white background

-- require needed libraries


local sqlite3 = require( "sqlite3" )
local widget = require("widget")

Declare needed handlers for text field, table view and submit button.
-- handlers
local field1
local tableView
local submitBtn

Declare constants for screen dimensions.


-- constants
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local _W = display.contentWidth
local _H = display.contentHeight

First lets create functions for database SQL commands like insert, delete
and retrieving data. Open a database file named data.db. It will created if
doesnt exist.
-- Open "data.db". If the file doesn't exist, it will be created
local path = system.pathForFile( "data.db", system.DocumentsDirectory )
local db = sqlite3.open( path )

Set up database for its first use.


-- Set up the table if it doesn't exist
local sql_cmd = [[CREATE TABLE IF NOT EXISTS list (id INTEGER PRIMARY KEY, content);]]
db:exec( sql_cmd ) -- execute sql command
db:close() -- close connection

We have a database named data.db which have a table list with columns id
and content. Lets create a function for inserting data to our database.
-- insert new row
local function insertData( value )
local db = sqlite3.open( path ) -- open connection
local sql_cmd = [[INSERT INTO list VALUES (NULL, ']]..value..[['); ]]
db:exec( sql_cmd ) -- execute sql command
db:close() -- close connection
end

We open the connection by calling the function sqlite3.open() which returns


the database file. The next line is the SQL command for inserting the new data.
The db:exec() method is the execution of the SQL command. Lastly, we close the
connection.
Next, we create a function for deleting a certain data from the database.
-- delete a certain row
local function deleteData( index )
local db = sqlite3.open( path ) -- open connection
local sql_cmd = [[DELETE FROM list where id = ]]..index..[[; ]]
db:exec( sql_cmd ) -- execute sql command
db:close() -- close connection
end

Just like inserting data to the database, the SQL command is the only
difference in this function and the argument passed into it. In the SQL command
we will only delete the data from list which id is the current row tapped by the
user.
Next, is retrieving data from database.
-- retrieve data from database
local function getData( )
local db = sqlite3.open( path ) -- open connection
local data = {}
local counter = 1
for row in db:nrows("SELECT * FROM list") do
data[counter] = {}
data[counter].content = row.content
data[counter].id = row.id
counter = counter + 1
end
db:close() -- close connection
return data
end

This function will return a table of data that we retrieved from the database.
The method db:nrows(sql_command) returns a successive row from the database
based on the SQL SELECT command. We can pass the data to a table and use
the . dot operator to select the column of a certain data row. Example,
appData[1].content for the content of the first row.

Interface

We are done with the database functions. Next we will create the interface
for our App. We only need 3 objects in this App. The text field, table view and
a button.
field1 = native.newTextField( centerX, 100, _W-50, 80 )
field1.placeholder = "Enter any word"
field1.inputType = "default"
field1.size = 20
field1:resizeHeightToFitFont()

First object is the text field. We position it to the center of the screen and
100 pixels from the top. Dont forget to call the method
textField:resizeHeightToFitFont() to resize the text field to its font size. This will
be our source for data.
Next is the submit button where will be positioned below the text field.
submitBtn = widget.newButton(
{
label = "Submit",
> emboss = false,
shape = "roundedRect",
width = _W-50,
height = 40,
cornerRadius = 5,
labelColor = {default={0.2, 0.2, 0.2}, over={1, 1, 1}},
fillColor = { default={0, 0.9, 0.9}, over={0, 0.6, 0.5, 0.8} },
})
submitBtn.x = centerX
submitBtn.y = field1.contentBounds.yMax + submitBtn.height

The onRelease function will be coded later.


tableView = widget.newTableView( {
width = _W,
height = _H - submitBtn.contentBounds.yMax - 20,
> hideBackground = true,
rowTouchDelay = 10,
x = centerX,
y = submitBtn.contentBounds.yMax + 20,
})
tableView.anchorY = 0

Below the submit button is the table view. This will display the data fetched
from our database later.

The Process
The table view initially doesnt have data yet but once the database is
populated, we would want to display them immediately. Below the handler
declarations, insert the following:
local appData = {}
local dataCounter = 1

These variables will be used for the entire code. The appData will handle
the data retrieved from the database. The dataCounter will be the counter for
the number of data retrieved.
-- show list
appData = getData() -- retrieve data from database
local totalData = #appData -- total number of data retrieved
-- insert rows
for i=1, totalData do
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.2, 0.2, 0.2}, over={0.2, 0.2, 0.2, 0.5} },
})
end

Insert the above code to the bottom most part of the code. The second line
retrieves data from the database. The next line gets the total number of data
retrieved. The next few more lines is the rendering or inserting of rows to the
table view. Moving on, we will declare the needed functions for our code such
as the onRelease function of the button and onRowRender for the table view.
Insert the following code above the text field code.
-- onRelease function for submit button
local function onRelease( self, e )
insertData(field1.text) -- insert data to database
appData = getData() -- retrieve current data from database
-- insert rows
tableView:insertRow({
rowHeight = 48,
rowColor = { default={0.2, 0.2, 0.2}, over={0.2, 0.2, 0.2, 0.5} },
})
-- reset text field
field1.text = "" -- clear text field
native.setKeyboardFocus( nil ) -- remove softkeyboard from the screen
end

The code above inserts the data to our database using the value of the text
field. The appData gets the data from the database. The sixth line is the method
for inserting new row to the table view. The remaining codes resets the text
field. The native.setKeyboardFocus sets the focus of the soft keyboard for actual
devices. It accepts text field and text box handlers. If nil is passed then the
keyboard will be dismissed from the screen. If you run the project, the table
view inserts a new row but no content yet. We will work on that.
local function onRowRender( e )
-- cache variables
local row = e.row
local index = row.index
local contentWidth = row.width
local contentHeight = row.height
-- cache data from appData
local ID = appData[dataCounter].id
local content = appData[dataCounter].content

-- data from the database


local text = display.newText( row, content , 10, contentHeight * 0.5, native.systemFont, 20 )
text.anchorX = 0

-- delete button "x"


local delete = display.newText( row, "X", contentWidth - 10, text.y, native.systemFont, 20 )
delete.anchorX = 1

-- delete action
function delete:touch( e )
if (e.phase == "began") then

deleteData(ID) -- delete the selected row


tableView:deleteRow( index ) -- remove row

-- decrement data counter


dataCounter = dataCounter - 1;
end
return true
end
delete:addEventListener( "touch", delete )

-- increment data counter


dataCounter = dataCounter + 1;
end

Its important to cache the variables since data may be different from one
row to another. The text object text displays the content from database and
delete displays an x to delete the row and data from the database. The touch
event listener calls for the function deleteData for the database and the method
tableView:deleteRow() method to delete an array or single row from the table
view and then decrement the total number of data which the dataCounter holds.
Outside the deletes touch method is the increment of the dataCounter, knowing
that the onRowRender is called not only once but multiple times every time the
App starts and when the user inserts new data to the database.
Run and test the project. You can do a lot of things from this Project for
example, to do list App, a simple registration App, Login-logout App and so
on.
ABOUT T HE AUTHOR
Aj Sotelo is a Mobile Game Developer since 2015 and have been using
Corona SDK for almost two years in his mobile development. He is a
freelance for almost 1 year and developed several Games and Apps for his
clients and able to developed one game for his own and able to publish it to
Google Play Store. He loves playing games, playing the guitar, learning new
things and travel different places.
Now, he is trying to walk through the path of being an online entrepreneur.
He will start his own blog soon for sharing his experience, thoughts and
knowledge about mobile development. If you have something to say to him
please leave him a message and help us improve. We will be waiting for your
feedbacks, comments and suggestions. Thank you and God bless.

You might also like