You are on page 1of 182

User's Guide

Last update : 2014.06.12




Copyright: 2012, 2013, 2014 Anywhere Software Edition 1.4
Table of contents 2 Basic4Android User's Guide

1 General information.................................................................................................................5
2 Conditional compilation..........................................................................................................6
2.1 Build configurations........................................................................................................6
2.1.1 Built-in symbols...........................................................................................................6
2.2 Code Exclusion................................................................................................................7
2.2.1 Example from the forum..............................................................................................7
2.3 Unsupported structure....................................................................................................10
3 Libraries................................................................................................................................11
3.1 IME Input Methods Editor...........................................................................................11
3.1.1 Handling the screen size changed event......................................................................13
3.1.2 Showing and hiding the keyboard..............................................................................14
3.1.3 Handle the action button............................................................................................14
3.1.4 Custom filters............................................................................................................15
3.2 #AdditionalJar attribute..................................................................................................16
4 SQLite Database....................................................................................................................20
4.1 SQLite Database basics..................................................................................................20
4.2 First steps......................................................................................................................24
4.3 SQLite Viewer...............................................................................................................25
4.4 SQLite Database first simple example program..............................................................26
4.5 SQLite Database second simple example program.........................................................32
4.6 SQLite Database third simple example program.............................................................37
4.7 SQLite Database fourth example program......................................................................38
4.7.1 Editing.......................................................................................................................40
4.7.2 Filtering.....................................................................................................................41
4.7.3 Code..........................................................................................................................42
4.7.3.1 Main Activity.....................................................................................................43
4.7.3.2 Edit activity........................................................................................................45
4.7.3.3 Filter Activity.....................................................................................................46
5 DBUtils.................................................................................................................................47
5.1 DBUtils functions..........................................................................................................48
5.2 Examples.......................................................................................................................50
5.2.1 Example program Main module................................................................................50
5.2.2 Show the table in a WebView....................................................................................52
5.2.3 Show FirstName and LastName in a ListView...........................................................56
5.2.4 Display database in Spinners......................................................................................58
5.2.5 Edit database..............................................................................................................60
6 GPS.......................................................................................................................................68
6.1 GPS Library...................................................................................................................68
6.1.1 GPS Object................................................................................................................68
6.1.2 GPS Satellite..............................................................................................................69
6.1.3 GPS Location.............................................................................................................69
6.2 GPS Program.................................................................................................................70
6.2.1 General explanations..................................................................................................73
6.2.2 Setup..........................................................................................................................74
6.2.3 GPS display...............................................................................................................76
6.2.4 Satellites....................................................................................................................77
6.2.5 Map display...............................................................................................................78
6.2.6 GPS path....................................................................................................................80
6.2.7 Save GPS path file / KML file....................................................................................83
6.3 GPS Program Code........................................................................................................84
6.3.1 Initialization of the GPS.............................................................................................85
6.3.2 Button with tooltip.....................................................................................................86
Table of contents 3 Basic4Android User's Guide
6.3.3 Button with tooltip and additional buttons..................................................................89
6.3.4 GPS Calculate distance scales....................................................................................92
6.3.5 Drawing GPS position...............................................................................................93
7 Widgets, home screen widgets...............................................................................................96
7.1 Widgets Part I ...............................................................................................................96
7.2 Widgets Part II..............................................................................................................99
8 Http / HttpUtils2..................................................................................................................102
8.1 HttpUtils2 Objects......................................................................................................102
8.2 HttpUtils2 Functions...................................................................................................102
8.3 HttpUtils Example1....................................................................................................104
8.4 HttpUtils Example2....................................................................................................105
8.5 The Flickr Viewer example..........................................................................................106
9 Network / AsyncStreams.....................................................................................................107
10 Advanced drawings.............................................................................................................111
10.1 View Drawables..........................................................................................................111
10.1.1 ColorDrawable.....................................................................................................111
10.1.2 GradientDrawable................................................................................................112
10.1.3 BitmapDrawable..................................................................................................113
10.1.4 StateListDrawable................................................................................................114
10.1.5 NinePatchDrawable.............................................................................................117
10.2 Layers with Panels / ImageViews / Images..................................................................119
10.2.1 Source code..........................................................................................................120
10.3 Diagrams / Charts........................................................................................................124
10.3.1 Diagrams / Graph example program...................................................................124
10.3.2 Second Graph program.........................................................................................133
10.3.3 Charts Framework................................................................................................134
10.3.3.1 Pie Chart......................................................................................................135
10.3.3.2 Bar Chart......................................................................................................138
10.3.3.3 Stacked Bar Chart.........................................................................................141
10.3.3.4 Lines Chart...................................................................................................143
10.4 Antialiasing filter.........................................................................................................148
11 Class modules......................................................................................................................149
11.1 Getting started.............................................................................................................149
11.1.1 Adding a class module.........................................................................................150
11.1.2 Classes structures.................................................................................................150
11.1.3 Polymorphism......................................................................................................151
11.1.4 Self reference.......................................................................................................152
11.1.5 Activity object......................................................................................................153
11.2 Classes from the forum................................................................................................154
11.3 First example Wheel selection.....................................................................................155
11.3.1 Simple example....................................................................................................155
11.3.2 Show the selected entry centred in the middle window.........................................159
11.3.3 Return the selected value......................................................................................161
11.3.4 Color properties...................................................................................................163
11.3.5 A more advanced example...................................................................................167
11.4 Second example LimitBar...........................................................................................168
11.5 Add properties to a class..............................................................................................173
11.6 Display a custom view in the Designer.........................................................................174
11.6.1 Example with the LimitBar..................................................................................177
11.7 Compile a class into a Library......................................................................................179
11.7.1 Example with the LimitBar class example............................................................181
11.7.2 Using the library in a program..............................................................................182

Table of contents 4 Basic4Android User's Guide
Main contributors : Erel Uziel (Erel), Klaus Christl (klaus)
1 General information 5 Basic4Android User's Guide
1 General information

This guide is dedicated for more advanced users and treats more specific topics.

It covers Basic4Android version 3.80.

All the source code and files needed (layouts, images etc) of the example projects in this guide are
included in the SourceCode folder.

Beginners should first read the Beginner's Guide.

2 Conditional Compilation 6 Basic4Android User's Guide
2 Conditional compilation

In computer programming, conditional compilation is compilation implementing methods which
allow the compiler to produce differences in the executable produced controlled by parameters that
are provided during compilation.

2.1 Buil d confi gurati ons

The build configurations dialog is available in the IDE menu under
Project ->Build Configurations (Ctrl +B).



This dialog allows you to edit or add new configurations and to choose the current active
configuration.
A build configuration is made of a package name and a set of conditional symbols.
The package name replaces the previously global package field. This means that you can produce
APKs with different package names from the same project. Note that multiple configurations can
share the same package name.

The conditional symbols define the active compiler symbols. This allows you to exclude parts of the
code based on the chosen build configuration.
You can set multiple symbols separated with commas.

2.1.1 Built-in symbols

There are several built-in symbols:
For B4A:
B4A, DEBUG and RELEASE.
Either DEBUG or RELEASE will be active based on the deployment mode.

For B4J:
B4J, DEBUG, RELEASE, UI or NON_UI (based on the app type)

2 Conditional Compilation 7 Basic4Android User's Guide
2.2 Code Excl usi on

With the conditional compilation feature you can exclude any code you like from the code editor,
manifest editor and designer script (any text can be excluded, including complete subs and
attributes).
Excluded code will not be parsed and will be effectively removed before it reaches the compiler.

The code exclusion syntax:



Each build configuration holds a set of symbols. Multiple configurations can share all or some of
the symbols. This makes it possible to include or exclude code in several different configurations.

There is no support for #Else (it is related to the code editor lexer implementation). You can
however achieve the same result by adding the same symbol to all other build configurations.

2.2.1 Example from the forum

The example code is in the ConditionalCompiling project in the SourceCode folder.

Lets create three configurations:
FREE
PAID
AMAZON

In the IDE menu click on
Project / Build
Configuration.


Fill the in the fields.



Click on to
confirm.
2 Conditional Compilation 8 Basic4Android User's Guide
Select Project / Build Configuration again youll see this.
In the drop down list Default is replaced by FREE.



Click on to create a new configuration.



Fill in the new values.



Click on to create the third configuration.
Replace PAID by AMAZON and click to finish.

2 Conditional Compilation 9 Basic4Android User's Guide
Enter the code below:
We see that the code after IF AMAZON is colored because the last selected configuration is
AMAZON.

Sub Gl obal s
#I f FREE
Di msRel ease As St r i ng = "( Fr ee) "
Di msDi st As St r i ng = ""
#End I f
#I f PAI D
Di msRel ease As St r i ng = "( Pai d) "
Di msDi st As St r i ng = ""
#End I f
#I f AMAZON
Di msRel ease As St r i ng = "( Fr ee) "
Di msDi st As St r i ng = "Amazon"
#End I f
End Sub

Now select PAID in the BuildConfigurations window:


We see now the three configurations
in the list.


Sub Gl obal s
#I f FREE
Di msRel ease As St r i ng = "( Fr ee) "
Di msDi st As St r i ng = ""
#End I f
#I f PAI D
Di msRel ease As St r i ng = "( Pai d) "
Di msDi st As St r i ng = ""
#End I f
#I f AMAZON
Di msRel ease As St r i ng = "( Fr ee) "
Di msDi st As St r i ng = "Amazon"
#End I f
End Sub

Note that now the code after IF PAID is colored showing that this code will be executed and the
other code will not be executed.

If you have a code like this, where the code for FREE and AMAZON is the same:

#I f FREE
#Appl i cat i onLabel : Yaht zee! ( Fr ee)
#Ver si onCode: 119
#Ver si onName: 11. 9
#End I f
#I f AMAZON
#Appl i cat i onLabel : Yaht zee! ( Fr ee)
#Ver si onCode: 119
#Ver si onName: 11. 9
#End I f
#I f PAI D
#Appl i cat i onLabel : Yaht zee! ( Pai d)
#Ver si onCode: 89
#Ver si onName: 8. 9
#End I f
2 Conditional Compilation 10 Basic4Android User's Guide
You could add a new configuration FreeOrAmazon like this:



In Conditional Symbols we need to add also FREE and AMAZON to allow alse these
configurations.

In this case we need to add the FreeOrAmazon configuration to both FREE and AMAZON
configurations.

And replace the code by:

#I f Fr eeOr Amazon
#Appl i cat i onLabel : Yaht zee! ( Fr ee)
#Ver si onCode: 119
#Ver si onName: 11. 9
#End I f
#I f PAI D
#Appl i cat i onLabel : Yaht zee! ( Fr ee)
#Ver si onCode: 119
#Ver si onName: 11. 9
#End I f

2.3 Unsupported structure

This structure is not supported, no Else nor Else If.

#I f XXX
#El se
#End I f






3 Libraries 11 Basic4Android User's Guide
3 Libraries

In this chapter we will study some specific libraries.

3.1 IME Input Methods Editor

The IME library allows to modify the soft keyboard behaviour.

The library can be found here IME library.

The most part of this chapter has been taken over from Erels' IME Tutorial.
The example code has been changed a little bit.

Android has very good support for custom input method editors (IMEs).
The downside for this powerful feature is that interacting with the soft keyboard can be sometimes
quite complicated.

This library includes several utilities that will help you better handle the soft keyboard.

The methods are :
AddHandleActionEvent (EditText As EditText)
Adds the HandleAction event to the given EditText.

AddHeightChangedEvent
Enables the HeightChanged event.
This event is raised when the soft keyboard state changes.
You can use this event to resize other views to fit the new screen size.
Note that this event will not be raised in full screen activities (an Android limitation

HideKeyboard
Hides the soft keyboard if it is visible.

Initialize (EventName As String)
Initializes the object and sets the subs that will handle the events.

SetCustomFilter (EditText As EditText, DefaultInputType As Int, AcceptedCharacters As
String)
Sets a custom filter.
EditText - The target EditText.
DefaultInputType - Sets the keyboard mode.
AcceptedCharacters - The accepted characters.

Example: Create a filter that will accept IP addresses (numbers with multiple dots)
I ME. Set Cust omFi l t er ( Edi t Text 1, Edi t Text 1. I NPUT_TYPE_NUMBERS, "0123456789. ")

ShowKeyboard (View As View)
Sets the focus to the given view and opens the soft keyboard.
The keyboard will only show if the view has received the focus.

3 Libraries 12 Basic4Android User's Guide
The events are :
HandleAction As Boolean

HeightChanged (NewHeight As Int, OldHeight As Int)
Raised when the keyboard has changed, but only if the event has been activated with the
AddHei ght ChangedEvent method

The attached example demonstrates the available methods.
The example is an extended example of Erels' project from the IME library.

Note that the IME object should be initialized before it can be used.
I ME. I ni t i al i ze( Event Name As St r i ng)

I ME1. I ni t i al i ze( "I ME1")



Shows the keyboard

Must start with 'a'


limited to an IP address


limited to an hex number

limited to an octal number


hides the keyboard



3 Libraries 13 Basic4Android User's Guide
3.1.1 Handling the screen size changed event

When the keyboard opens the available screen size becomes much shorter. By default if the
EditText is located near the bottom of the screen, Android will "push" the whole activity and make
the EditText visible. This mode is named "adjustPan" mode.

By calling I ME1. AddHei ght ChangedEvent you are changing the activity to "adjustSize" mode.
In this mode the activity will not be pushed automatically. Instead the HeightChanged event will be
raised when the keyboard is shown or hidden.
For example the following code makes sure that the button at the bottom is always visible and sets
the large EditText height to match the available height:





When the keyboard is displayed the left EditText views height is
adapted according to the keyboard size.

The Hide keyboard button is moved above the keyboard.










The code:

Sub I ME1_Hei ght Changed( NewHei ght As I nt , Ol dHei ght As I nt )
bt nHi deKeyboar d. Top = NewHei ght - bt nHi deKeyboar d. Hei ght
edt Test . Hei ght = bt nHi deKeyboar d. Top - edt Test . Top
End Sub

Note that this method will not work if the activity is in full screen mode (Issue 5497 - android -
adjustResize windowSoftInputMode breaks when activity is fullscreen - Android).

3 Libraries 14 Basic4Android User's Guide
3.1.2 Showing and hiding the keyboard

IME1.ShowKeyboard(EditText) - Sets the focus to the given view and opens the soft keyboard.

Sub bt nShowKeyboar d_Cl i ck
I ME1. ShowKeyboar d( edt St ar t Wi t hA)
End Sub

IME1.HideKeyboard - Hides the keyboard (this method is the same as Phone.HideKeyboard).

Sub bt nHi deKeyboar d_Cl i ck
I ME1. Hi deKeyboar d
End Sub

3.1.3 Handle the action button
By calling I ME1. AddHandl eAct i onEvent you can override the default behaviour of the action
button (the button that shows Next or Done).
This event is similar to EditText_EnterPressed event. However it is more powerful. It also allows
you to handle the Next button and also to consume the message (and keep the keyboard opened and
the focus on the current EditText).

This can be useful in several cases.
For example in a chat application you can send the message when the user presses on the done
button and keep the keyboard open by consuming the message.

You can also use it to validate the input before jumping to the next view by pressing on the Next
button (note that the user will still be able to manually move to the next field).

You can use the Sender keyword to get the EditText that raised the event.

Sub I ME1_Handl eAct i on As Bool ean
Di medt As Edi t Text

edt = Sender

Sel ect edt . Tag
Case "edt St ar t Wi t hA"
I f edt . Text . St ar t sWi t h( "a") = Fal se Then
Toast MessageShow( "Text must st ar t wi t h ' a' . ", Tr ue)
' Consume t he event .
' The keyboar d wi l l not be cl osed
Ret ur n Tr ue
El se
Ret ur n Fal se ' wi l l cl ose t he keyboar d
End I f
End Sel ect
End Sub

3 Libraries 15 Basic4Android User's Guide
3.1.4 Custom filters
EditText.InputType allows you to set the keyboard mode and the allowed input.
However there are situations where you need to use a custom filter. For example if you want to
accept IP addresses (ex: 192.168.0.1). In this case none of the built-in types will work. Setting the
input type to INPUT_TYPE_DECIMAL_NUMBERS will get you close but it will not allow the
user to write more than a single dot.
I ME1. Set Cust omFi l t er allows you to both set the keyboard mode and also to set the accepted
characters.
In this case we will need a code such as:

IP address :

I ME1. Set Cust omFi l t er ( edt I PAddr ess, edt I PAddr ess. I NPUT_TYPE_NUMBERS, " 0123456789. " )

edt I PAddr ess is the given EditText view
edt I PAddr ess. I NPUT_TYPE_NUMBERS is the keyboard type
"0123456789. " are the allowed characters, in our case we accept not only numbers as
with INPUT_TYPE_NUMBERS but we accept also dots.

Note that this is only a simple filter. It will accept the following input ...999 (which is not a valid IP
address):

Hex number input :

' 0x0080000 i s t he f l ag of NO_SUGGESTI ONS.
I ME1. Set Cust omFi l t er ( edt HexNumber , Bi t . Or ( edt HexNumber . I NPUT_TYPE_TEXT, _
0x00080000) , "01234567890abcdef ")

0x00080000 is the flag for NO_SUGGESTION
Bi t . Or ( edt HexNumber . I NPUT_TYPE_TEXT, 0x00080000)
combines the INPUT_TYPE_TEXT flag with the _SUGGESTION flag

Octal number input :

I ME1. Set Cust omFi l t er ( edt Oct al Number , Bi t . Or ( edt Oct al Number . I NPUT_TYPE_NUMBERS, _
0x00080000) , "01234567")

Note: With these filters the default keyboards is displayed but only the defined characters are
authorized all the other keys are disabled but still visible.

3 Libraries 16 Basic4Android User's Guide
3.2 #AdditionalJar attribute

This is a copy of Erels tutorial in the forum.

The #AdditionalJ ar module attribute (introduced in B4A v3.80) allows us to reference external jars.
With the help of JavaObject it is now possible to integrate third party jars without a wrapper.

This solution is good for "simple" libraries. If the API is complicated with many interfaces then it
will be easier to create a wrapper.

As an example we will use Picasso image downloader to download images:
http://square.github.io/picasso/



The first step is to download the third party jar and put it in the additional libraries folder.
We then use #AdditionalJar to tell the compiler to add a reference to this jar:

#Addi t i onal J ar : pi casso- 2. 2. 0

Note that the jar extension is omitted. You can call #AdditionalJ ar multiple times if multiple jars are
required.

3 Libraries 17 Basic4Android User's Guide
The following two subs will usually be required. They allow you to get the "context" (it will be an
android.app.Activity when called from an Activity module).

This code should be added to an activity or service directly.

Sub Get Cont ext As J avaObj ect
Ret ur n Get BA. Get Fi el d( "cont ext ")
End Sub

Sub Get BA As J avaObj ect
Di mj o As J avaObj ect
Di mcl s As St r i ng = Me
cl s = cl s. SubSt r i ng( "cl ass ". Lengt h)
j o. I ni t i al i zeSt at i c( cl s)
Ret ur n j o. Get Fi el dJ O( "pr ocessBA")
End Sub



As you can see in their examples we always start by calling Picasso static method 'with'. It is more
clear in the JavaDocs page:
http://square.github.io/picasso/javadoc/com/squareup/picasso/Picasso.html

This sub will call the static method:

Sub Get Pi casso As J avaObj ect
Di mj o As J avaObj ect
' com. squar eup. pi casso. Pi casso. wi t h( cont ext )
Ret ur n j o. I ni t i al i zeSt at i c( "com. squar eup. pi casso. Pi casso") . RunMet hod( "wi t h", _
Ar r ay( Get Cont ext ) )
End Sub
Now we will implement the above Java code:

Get Pi casso. RunMet hodJ O( "l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "i nt o", Ar r ay( i mg1) )

In the second example we call a more complex API:

' second exampl e: Pi casso. wi t h( cont ext ) . l oad( ur l ) . r esi ze( 50, 50) . cent er Cr op( ) . i nt o( I mageVi
ew)
Get Pi casso. RunMet hodJ O( " l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "r esi ze" , Ar r ay( 50, 50) ) _
. RunMet hodJ O( "cent er Cr op" , Nul l ) . RunMet hodJ O( " i nt o", Ar r ay( i mg2) )

The third example is more interesting. We download an image with a callback event that is raised
when download completes.

The first step it to create the interface. This is done with J avaObject.CreateEvent (or
CreateEventFromUI).
In this case we are implementing com.squareup.picasso.Callback:
http://square.github.io/picasso/javadoc/com/squareup/picasso/Callback.html

Di mcal l back As Obj ect = j o. Cr eat eEvent ( "com. squar eup. pi casso. Cal l back", _
"Cal l back", Nul l )

3 Libraries 18 Basic4Android User's Guide
The last parameter is the default return value. This value will be used if the event cannot be raised
(activity is paused for example). In this case we return Null.
The event sub:

Sub Cal l back_Event ( Met hodName As St r i ng, Ar gs( ) As Obj ect ) As Obj ect
I f Met hodName = "onSuccess" Then
Toast MessageShow( "Success! ! ! ", Tr ue)
El se I f Met hodName = "onEr r or " Then
Toast MessageShow( "Er r or downl oadi ng i mage. ", Tr ue)
End I f
Ret ur n Nul l
End Sub

MethodName - The interface method name (onSuccess or onError in this case).
Args - An array of parameters passed to this method. In this case there are no parameters.
All this information is from Picasso JavaDocs:
http://square.github.io/picasso/javadoc/index.html?com/squareup/picasso/Callback.html

The last step is to call the method that expects the callback:

Get Pi casso. RunMet hodJ O( "l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "i nt o", Ar r ay( i mg1, _
cal l back) )

As this library requires the INTERNET permission we need to manually add it to the manifest
editor:

AddPer mi ssi on( andr oi d. per mi ssi on. I NTERNET)

The complete code:

#Regi on Pr oj ect At t r i but es
#Appl i cat i onLabel : B4A Exampl e
#Ver si onCode: 1
#Ver si onName:
' Suppor t edOr i ent at i ons possi bl e val ues: unspeci f i ed, l andscape or por t r ai t .
#Suppor t edOr i ent at i ons: unspeci f i ed
#CanI nst al l ToExt er nal St or age: Fal se
#End Regi on

#Regi on Act i vi t y At t r i but es
#Ful l Scr een: Fal se
#I ncl udeTi t l e: Tr ue
#End Regi on

#Addi t i onal J ar : pi casso- 2. 2. 0

Sub Pr ocess_Gl obal s

End Sub

Sub Gl obal s
Di mi mg1, i mg2 As I mageVi ew
End Sub

3 Libraries 19 Basic4Android User's Guide
Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
i mg1. I ni t i al i ze( "")
Act i vi t y. AddVi ew( i mg1, 0, 0, 100%x, 50%y)
i mg2. I ni t i al i ze( "")
Act i vi t y. AddVi ew( i mg2, 0, 50%y, 100%x, 50%y)
Di mur l As St r i ng = "ht t p: / / i . i mgur . com/ Dvpvkl R. png"
' f i r st exampl e: Pi casso. wi t h( cont ext ) . l oad( ur l ) . i nt o( i mageVi ew) ;
Get Pi casso. RunMet hodJ O( "l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "i nt o", Ar r ay( i mg1) )

' second exampl e: Pi casso. wi t h( cont ext ) . l oad( ur l ) . r esi ze( 50, 50) . cent er Cr op( ) .
i nt o( I mageVi ew)
Get Pi casso. RunMet hodJ O( "l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "r esi ze", Ar r ay( 50, 50
) ) _
. RunMet hodJ O( "cent er Cr op", Nul l ) . RunMet hodJ O( "i nt o", Ar r ay( i mg2) )

' t hi r d exampl e: downl oad i mage wi t h cal l back
Di mj o As J avaObj ect = Get Pi casso
Di mcal l back As Obj ect = j o. Cr eat eEvent ( "com. squar eup. pi casso. Cal l back", "Cal
l back", Nul l )
Get Pi casso. RunMet hodJ O( "l oad", Ar r ay( ur l ) ) . RunMet hodJ O( "i nt o", Ar r ay( i mg1, ca
l l back) )
End Sub

Sub Cal l back_Event ( Met hodName As St r i ng, Ar gs( ) As Obj ect ) As Obj ect
I f Met hodName = "onSuccess" Then
Toast MessageShow( "Success! ! ! ", Tr ue)
El se I f Met hodName = "onEr r or " Then
Toast MessageShow( "Er r or downl oadi ng i mage. ", Tr ue)
End I f
Ret ur n Nul l
End Sub

Sub Get Pi casso As J avaObj ect
Di mj o As J avaObj ect
' com. squar eup. pi casso. Pi casso. wi t h( cont ext )
Ret ur n j o. I ni t i al i zeSt at i c( "com. squar eup. pi casso. Pi casso") . RunMet hod( "wi t h",
Ar r ay( Get Cont ext ) )
End Sub

Sub Get Cont ext As J avaObj ect
Ret ur n Get BA. Get Fi el d( "cont ext ")
End Sub

Sub Get BA As J avaObj ect
Di mj o As J avaObj ect
Di mcl s As St r i ng = Me
cl s = cl s. SubSt r i ng( "cl ass ". Lengt h)
j o. I ni t i al i zeSt at i c( cl s)
Ret ur n j o. Get Fi el dJ O( "pr ocessBA")
End Sub

Sub Act i vi t y_Resume

End Sub

Sub Act i vi t y_Pause ( User Cl osed As Bool ean)

End Sub


4 SQLite Database 20 Basic4Android User's Guide
4 SQLite Database

What is a database (source Wikipedia Database):
A database is an organized collection of data for one or more purposes, usually in digital form. The
data are typically organized to model relevant aspects of reality (for example, the availability of
rooms in hotels), in a way that supports processes requiring this information (for example, finding a
hotel with vacancies). The term "database" refers both to the way its users view it, and to the logical
and physical materialization of its data, content, in files, computer memory, and computer data
storage. This definition is very general, and is independent of the technology used. However, not
every collection of data is a database; the term database implies that the data is managed to some
level of quality (measured in terms of accuracy, availability, usability, and resilience) and this in
turn often implies the use of a general-purpose Database management system(DBMS). A general-
purpose DBMS is typically a complex software system that meets many usage requirements, and
the databases that it maintains are often large and complex.

The standard database system in Android is SQLite.

The interface between your program and the database is a the SQL language.
The data is stored in tables, each table has a certain number of columns and rows.
Each row contains a data set and the different data of a given set are stored in the columns.

If you add a default database to your project in the files Tab it is located in the DirAssets
folder. Databases cannot be accessed in DirAssets even if it's only for reading.
Therefore you must copy it to another folder for example DirInternal or DirRootExternal.
With DirRootExternal you can also add a subdirectory.
For example: Di r Root Ext er nal & "/ MyDat abase"
Don't forget to create the subdirectory : Fi l e. MakeDi r ( Fi l e. Di r Root Ext er nal , "MyDat abase")

Example code in Act i vi t y_Cr eat e :
I f Fi r st Ti me Then
I f Fi l e. Exi st s( Fi l e. Di r Root Ext er nal , "Dat abase. db") = Fal se Then
Fi l e. Copy( Fi l e. Di r Asset s, "Dat abase", Fi l e. Di r Root Ext er nal , "Dat abase. db")
End I f
SQL1. I ni t i al i ze( Fi l e. Di r Root Ext er nal , "Dat abase. db", Tr ue)
End I f

4.1 SQLi te Database basi cs

Some simple SQL instructions.

Here you find the SQLite site : SQLite
Here you find the SQLite syntax : SQLite syntax
A very intersting website to learn SQL is this one : W3Schools SQL.

Database initialisation:
SQL1.Initialize(DBDirName, DBFileName, True)
DBDirName =Directory name of the database.
DBFileName =Database file name.
True =Create if necessary False don't create
4 SQLite Database 21 Basic4Android User's Guide
Table creation:

CREATE TABLE TableName ( ID INTEGER PRIMARY KEY, Col1 TEXT, Col2 REAL )
Creates a table with the name 'TableName' and three columns:
Column Index Name Variable Type
1 ID INTEGER PRIMARY KEY
2 Col1 TEXT
3 Col2 REAL

Different available data types:
INTEGER PRIMARY KEY is a special variable type used for identifiers ID's. It is a long integer
value beginning with 1 and it is incremented by one each time a new data set, with a NULL
parameter for this column, is added to the database.
INTEGER is a 64-bit signed integer number.
REAL is a 64-bit IEEE floating point number.
TEXT is a string.
BLOB Binary Large OBject, the value is stored exactly as it was input.
NULL

SQL1. ExecNonQuer y( "CREATE TABLE Tabl eName( I D I NTEGER PRI MARY KEY, Col 1 TEXT,
Col 2 REAL")

Adding data:

INSERT INTO TableName VALUES ( NULL, 'Val1', Val2 )

SQL1. ExecNonQuer y( "I NSERT I NTO Tabl eName VALUES ( NULL, ' Val 1' , Val 2")
Text variable must be between two quotes 'Val1', numbers not Val2.

Updating data:

UPDATE TableName Set Col1 ='Val1', Col2 =Val2 WHERE ID =idVal

SQL1. ExecNonQuer y( "UPDATE Tabl eName Set Col 1 = ' Val 1' , Col 2 = Val 2 WHERE I D =
i dVal ")

Reading data:

The whole database:
SELECT * FROM TableName
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName")

The whole database and ordering according to a given column:
SELECT * FROM TableName ORDER BY Col1 ASC ascending
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName ORDER BY Col 1 ASC")

SELECT * FROM TableName ORDER BY 2 DESC descending
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName ORDER BY 2 DESC")

The column to order can be given either by its name Col1 or its number 2.
The column numbering begins with 1.

4 SQLite Database 22 Basic4Android User's Guide
Filtering
SELECT * FROM TableName WHERE Col1 LIKE 'abc' AND Col2 LIKE 123
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName" WHERE Col 1 LI KE ' abc%'
AND Col 2 LI KE 123 ")
The % character can be used as a wildcard:
abc means the exact sequence
%abc means beginning with any characters and ending with abc
abc% means beginning with abc and ending with any characters
%abc% means abc anywhere in the string

A single column
SELECT Col1 FROM TableName
Cur sor 1 = SQL1. ExecQuer y( "SELECT Col 1 FROM Tabl eName")

Distinct values from a column, no duplicate values
SELECT DISTINCT Col1 FROM TableName
Cur sor 1 = SQL1. ExecQuer y( "SELECT DI STI NCT Col 1 FROM Tabl eName")

Single entry (value)
SELECT Col1 FROM TableName WHERE ID =idVal
Val ue = SQL1. ExecQuer ySi ngl eResul t ( "SELECT Col 1 FROM Tabl eName WHERE I D =
i dVal ")

Single row, where the ID has a given value
SELECT * FROM TableName WHERE ID =idVal
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName WHERE I D = i dVal ")

Max / min value in a column, in the examples the max and min values of the given column.
SELECT max(Col1) FROM TableName
SELECT min(Col1) FROM TableName
Max = SQL1. ExecQuer ySi ngl eResul t ( "SELECT max( Col 1) FROM Tabl eName")
Mi n = SQL1. ExecQuer ySi ngl eResul t ( "SELECT mi n( Col 1) FROM Tabl eName")

Get the max length of the data in a column
For a string, the returned value is the number of characters.
For a number, the returned value is the number of characters of its string representation.
For a blob, the returned value is the number of bytes.
SELECT max(length(Col1)) FROM TableName
MaxChar s = SQL1. ExecQuer ySi ngl eResul t ( "SELECT max( l engt h( Col 1) ) FROM
Tabl eName")

Get the total number of rows
SELECT count() FROM TableName
Number Of Rows = SQL1. ExecQuer ySi ngl eResul t ( "SELECT count ( ) FROM Tabl eName")

Get the tables in the database
SELECT name FROM sqlite_master WHERE Type='table'
Cur sor 1 = SQL1. ExecQuer y( " SELECT name FROM sql i t e_mast er Wher e Type=' t abl e' ")

4 SQLite Database 23 Basic4Android User's Guide
Get the column names of a table.
SELECT * FROM TableName
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM Tabl eName")
For i = 0 t o Cur sor 1. Col umnCount - 1
Col umnName( i ) = Cur sor 1. Get Col umnName( i )
Next

Get the number of database rows that were changed or inserted or deleted by the most
recently completed INSERT, DELETE, or UPDATE.
SELECT changes() FROM TableName
NbChanges = SQL1. ExecQuer ySi ngl eResul t ( "SELECT changes( ) FROM Tabl eName")

Get the PRIMARY KEYs from a table and save them in a List, rowid is a reserved column
name. This is valid even if there is no column defined with PRIMARY KEY.
SELECT rowid FROM TableName
Di mI DLi st As Li st

I DLi st . I ni t i al i ze
Cur sor 1 = SQL1. ExecQuer y( "SELECT r owi d FROM Tabl eName")
For i = 0 To Cur sor 1. RowCount - 1
Cur sor 1. Posi t i on = i
I DLi st . Add( Cur sor 1. Get Long2( 0) )
Next

Get Table information
It uses a special query PRAGMA.
This query returns one row per column with following data :
Column index name Explanation
0 ci d column index
1 name column name
2 t ype data type
3 df l t _val ue default value
4 not nul l null if the database acccepts null values
5 pk primary key =1 if the column is a PRIMARY KEY otherwise =0
This is valid only if a column with a primary key was created.

Cur sor 1 = SQL1. ExecQuer y( "PRAGMA t abl e_i nf o ( Tabl eName) ")
For i = 0 To Cur sor 1. RowCount - 1
Cur sor 1. Posi t i on = i
For j = 0 To Cur sor 1. Col umnCount - 1
Log( i & " / " & j & " : " & Cur sor 1. Get St r i ng2( j ) )
Next
Log( " ")
Next
Or this code:
Cur sor 1 = SQL1. ExecQuer y( "PRAGMA t abl e_i nf o ( Tabl eName) ")
For i = 0 To Cur sor 1. RowCount - 1
Cur sor 1. Posi t i on = i
Log( "I D : " & Cur sor 1. Get St r i ng( "ci d") )
Log( "Name : " & Cur sor 1. Get St r i ng( "name") )
Log( "Type : " & Cur sor 1. Get St r i ng( "t ype") )
Log( "Def aul t val ue : " & Cur sor 1. Get St r i ng( "df l t _val ue") )
Log( "Not nul l : " & Cur sor 1. Get St r i ng( "not nul l ") )
Log( "Pr i mat y key : " & Cur sor 1. Get St r i ng( "pk") )
Log( " ")
Next

4 SQLite Database 24 Basic4Android User's Guide
Deleting data:
DELETE FROM TableName WHERE ID =idVal
SQL1. ExecNonQuer y( "DELETE FROM Tabl eName WHERE I D = i dVal ")

Rename a table:
Renames a given table.
ALTER TABLE TableName RENAME TO NewTableName)
SQL1. ExecNonQuer y( "ALTER TABLE Tabl eName RENAME TO NewTabl eName")

Add a column:
Add a new column to the database.
ALTER TABLE TableName ADD COLUMN Colname ColType)
SQL1. ExecNonQuer y( "ALTER TABLE Tabl eName ADD COLUMN Col N TEXT")

Update the database:
Update the database after having added a new column.
Sets the values of all rows in the new column to an empty string.
UPDATE TableName SET ColName =''
SQL1. ExecNonQuer y( "UPDATE Tabl eName SET Col N = ' ' ")

Sets the values of the rows in a column to a given new value where the value is another old
value.
UPDATE TableName SET ColName ='ValueNew' WHERE ColName ='ValueOld'
SQL1. ExecNonQuer y( " UPDATE Tabl eName SET Col N = ' Val ueNew' WHERE Col N = ' Val ueOl d' " )


4.2 First steps

To use a database, we must :

- First reference the SQL library in the Libs Tab in the lower right corner in the IDE.



- Declare it with a Dim in the Process_Global routine.

Sub Pr ocess_Gl obal s

Di mSQL1 As SQL



4 SQLite Database 25 Basic4Android User's Guide
4.3 SQLi te Vi ewer

There is a SQLiteViewer program in the forum, that allows you to load and display databases.
The program uses the DBUtils module and the table is shown in a WebView view.
The usage of the DBUtils module is explained in chapter 4 DBUtils.




4 SQLite Database 26 Basic4Android User's Guide
4.4 SQLi te Database first simpl e exampl e program

This example program is a very simple project with a very simple user interface.

The source code of this project is located in the SourceCode\SQL\SQLiteLight1 folder.

The database name, the table name and the column names are hard coded, to make the code better
readable. The user interface is kept very simple.

At the first run the database is empty and the user must add entries.



Following functions are implemented:
Add an entry
Edit an entry
Update an entry
Delete an entry
Display next and previous entry












Source code
It is selfexplaining.

Program initialization:

Process_Globals

We dim the process global variables.

Sub Pr ocess_Gl obal s
Di mSQL1 As SQL

Di mCur r ent I ndex = - 1 As I nt ' i ndex of t he cur r ent ent r y
Di mRowNumber = 0 As I nt ' number of r ows

Di mI DLi st As Li st ' l i st cont ai ni ng t he I Ds of t he dat abase
' we need i t because t he I Ds can be di f f er ent f r omt he l i st i ndexes
' i f we del et e an ent r y i t s I D i s l ost
End Sub

4 SQLite Database 27 Basic4Android User's Guide
Globals

We dim all the views of the layout.

Sub Gl obal s
Di medt I D, edt Fi r st Name, edt Last Name, edt Ci t y As Edi t Text
Di mbt nAdd, bt nDel et e, bt nUpdat e, bt nPr evi ous, bt nNext As But t on
End Sub

Activity_Create

We check if the database already exists, initialize it, load it and show the first entry.

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
I f Fi r st Ti me Then
' Fi l e. Del et e( Fi l e. Di r I nt er nal , "per sons. db") ' onl y f or t est i ng, r emoves
t he dat abase

' check i f t he dat abase al r eady exi st s
I f Fi l e. Exi st s( Fi l e. Di r I nt er nal , "per sons. db") = Fal se Then
' i f not , i ni t i al i ze i t
SQL1. I ni t i al i ze( Fi l e. Di r I nt er nal , "per sons. db", Tr ue)
' and cr eat e i t
Cr eat eDat aBase
End I f
End I f

Act i vi t y. LoadLayout ( "Mai n")
End Sub

Activity_Resume

If the database is not initialized we initialize it, initialize the IDList list, read the database and show
the first entry.

Sub Act i vi t y_Resume
' I f t he dat abase i s not i ni t i al i zed we i ni t i al i ze i t
I f SQL1. I sI ni t i al i zed = Fal se Then
SQL1. I ni t i al i ze( Fi l e. Di r I nt er nal , "per sons. db", Tr ue)
End I f

I DLi st . I ni t i al i ze ' i ni t i al i ze t he I D l i st
ReadDat aBase ' r ead t he dat abase
ShowEnt r y( 0) ' show t he f i r st ent r y
End Sub

Program closing :

Activity_Pause

If the program is closed by the user we close the database.

Sub Act i vi t y_Pause ( User Cl osed As Bool ean)
I f User Cl osed Then
SQL1. Cl ose ' i f t he user cl oses t he pr ogr amwe cl ose t he dat abase
End I f
End Sub

4 SQLite Database 28 Basic4Android User's Guide
Database handling :

Create the database

We create the database with the four following columns :
ID INTEGER PRIMARY KEY the ID of the entry.
We use the INTEGER PRIMARY KEY data type, which is automatically invremented
when we add a new entry.
FirstName the persons first name with TEXT data type.
LastName the persons last name with TEXT data type.
City the city where the person is living with TEXT data type.

Sub Cr eat eDat aBase
Di mQuer y As St r i ng

Quer y = "CREATE TABLE per sons ( I D I NTEGER PRI MARY KEY, Fi r st Name TEXT,
Last Name TEXT, Ci t y TEXT) "
SQL1. ExecNonQuer y( Quer y)
End Sub

ReadDataBase

We
- Define a Cursor and read IDs from the databse.
- Check if there database is not empty.
- Fill IDList with the IDs of all entries.
- Set the current index to 0
- Close the cursor

Why do we use a List with the IDs ?
We use for the ID the INTEGER PRIMARY KEY data type which is unique.
If we delete an entry its ID is lost, which means that the ID numbers are not simply the row indexes
but there can be holes in the list.

Sub ReadDat aBase
Di mRow As I nt
Di mCur sor 1 As Cur sor

' We r ead onl y t he I D col umn and put t hemi n a Li st
Cur sor 1 = SQL1. ExecQuer y( "SELECT I D FROM per sons")
I f Cur sor 1. RowCount > 0 Then ' check i f ent r i es exi st
RowNumber = Cur sor 1. RowCount ' set t he r ow count var i abl e
I DLi st . I ni t i al i ze ' i ni t i al i ze t he I D l i st
For Row = 0 To RowNumber - 1
Cur sor 1. Posi t i on = Row ' set t he Cur sor t o each r ow
I DLi st . Add( Cur sor 1. Get I nt ( "I D") ) ' add t he I D' s t o t he I D l i st
Next
Cur r ent I ndex = 0 ' set t he cur r ent i ndex t o 0
End I f
Cur sor 1. Cl ose ' cl ose t he cur sor , we don' t need i t anymor e
End Sub


4 SQLite Database 29 Basic4Android User's Guide
ShowEntry

We get the selected entrys ID from IDList, read the entry from the database, fill the EditText views
and close the Cursor.

Sub ShowEnt r y( Ent r yI ndex As I nt )
Di mCur sor 1 As Cur sor
Di mI D As I nt

I f I DLi st . Si ze = 0 Then ' check i f t he dat abase i s empt y
Ret ur n ' i f yes l eave t he r out i ne
End I f

I D = I DLi st . Get ( Ent r yI ndex) ' get t he I D f or t he gi ven ent r y i ndex
' r ead t he ent r y wi t h t he gi ven I D
Cur sor 1 = SQL1. ExecQuer y( "SELECT * FROM per sons WHERE I D = " & I D)
edt I D. Text = I D ' di spl ay t he I D
Cur sor 1. Posi t i on = 0 ' set t he cur sor
edt Fi r st Name. Text = Cur sor 1. Get St r i ng( "Fi r st Name") ' r ead t he Fi r st Name col umn
edt Last Name. Text = Cur sor 1. Get St r i ng( "Last Name") ' r ead t he Lasst Name col umn
edt Ci t y. Text = Cur sor 1. Get St r i ng( "Ci t y") ' r ead t he val ue of t he Ci t y col umn
Cur sor 1. Cl ose ' cl ose t he cur sor , we don' t i t anymor e
End Sub

4 SQLite Database 30 Basic4Android User's Guide
AddEntry

We first check if an entry with the same data already exists.
If yes, we display a message.
If not, we add the new entry.
Display the new entrys ID.
Close the cursor.
We use ExecQuery2 instead of ExecQuery, its easier because we dont need to take care of the data
type, the routine converts the data to the correct type.
The ? sign is a placeholder for the data which must be given in the array.

Sub AddEnt r y
Di mQuer y As St r i ng
Di mCur sor 1 As Cur sor
Di mI D As I nt

' f i r st we check i f t he ent r y al r eady does exi st
Quer y = "SELECT * FROM per sons WHERE Fi r st Name = ? AND Last Name = ? AND Ci t y = ?"
Cur sor 1 = SQL1. ExecQuer y2( Quer y, Ar r ay As St r i ng ( edt Fi r st Name. Text , edt Last Name. Text ,
edt Ci t y. Text ) )

I f Cur sor 1. RowCount > 0 Then
' i f i t exi st s show a message and do not hi ng el se
Toast MessageShow( " Thi s ent r y al r eady exi st s" , Fal se)
El se
' i f not , add t he ent r y
' a NULL f or t he I D col umn i ncr ement s t he pr i mar y key aut omat i cal l y by one
' we use ExecNonQuer y2 because i t ' s easi er , we don' t need t o t ake car e of t he dat a
t ypes
Quer y = "I NSERT I NTO per sons VALUES ( NULL, ?, ?, ?) "
SQL1. ExecNonQuer y2( Quer y, Ar r ay As St r i ng( edt Fi r st Name. Text , edt Last Name. Text ,
edt Ci t y. Text ) )

Toast MessageShow( " Ent r y added" , Fal se) ' conf i r mat i on f or t he user

' t o di spl ay t he I D of t he l ast ent r y we r ead t he max val ue of t he I D col umn
I D = SQL1. ExecQuer ySi ngl eResul t ( "SELECT max( I D) FROM per sons")
RowNumber = RowNumber + 1 ' i ncr ease t he r ow count
I DLi st . Add( I D) ' add t he l ast I D t o t he l i st
Cur r ent I ndex = I DLi st . Si ze - 1 ' set t he cur r ent i ndex t o t he l ast one
edt I D. Text = I D ' di spl ay t he l ast i ndex
End I f
Cur sor 1. Cl ose ' cl ose t he cur sor , we don' t i t anymor e
End Sub



4 SQLite Database 31 Basic4Android User's Guide
DeleteEntry

We ask the user if he really wants to delete the selected entry.
If the answer is yes then we delete it.
And set the new CurrentIndex.

Sub Del et eEnt r y
Di mQuer y As St r i ng
Di mAnsw As I nt

' ask t he user f or conf i r mat i on
Answ = Msgbox2( "Do you r eal l y want t o del et e " & edt Fi r st Name. Text & " " &
edt Last Name. Text , "Del et e ent r y", "Yes", "", "No", Nul l )

I f Answ = Di al ogResponse. POSI TI VE Then ' i f yes, del et e t he ent r y
Quer y = "DELETE FROM per sons WHERE I D = " & I DLi st . Get ( Cur r ent I ndex)
SQL1. ExecNonQuer y( Quer y) ' del et e t he ent r y
I DLi st . RemoveAt ( Cur r ent I ndex) ' r emove t he I D f r omt he l i st
I f Cur r ent I ndex = RowNumber - 1 Then ' i f t he cur r ent i ndex i s t he l ast one
Cur r ent I ndex = Cur r ent I ndex - 1 ' decr ement i t by 1
End I f
RowNumber = RowNumber - 1 ' decr ement t he r ow count by 1
ShowEnt r y( Cur r ent I ndex) ' show t he next ent r y
Toast MessageShow( "Ent r y del et ed", Fal se) ' conf i r mat i on f or t he user
End I f
End Sub


UpdateEntry

We use ExecNonQuery2 instead of ExecNonQuery because its easier, we dont need to take care
of the data type.
The ? sign is a placeholder for the data which must be given in the array.

Sub Updat eEnt r y
Di mQuer y As St r i ng

Quer y = "UPDATE per sons Set Fi r st Name = ?, Last Name = ?, Ci t y = ? _
WHERE I D = " & I DLi st . Get ( Cur r ent I ndex)
SQL1. ExecNonQuer y2( Quer y, Ar r ay As St r i ng( edt Fi r st Name. Text , _
edt Last Name. Text , edt Ci t y. Text ) )
Toast MessageShow( "Ent r y updat ed", Fal se)
End Sub


4 SQLite Database 32 Basic4Android User's Guide
4.5 SQLi te Database second simpl e example program

This example program is an evolution of the SQLiteLight1 project.

The source code of this project is located in the SourceCode\SQL\SQLiteLight2 folder.

The program generates a default database if there is none available.

Added an Activity displaying the database in a table, using a WebView.



Main screen Edit screen Filter screen


Following functions are implemented:
Add an entry
Edit an entry
o Update an entry
o Delete an entry
o Go to First, Prev, Next and Last entry
Filter
o AND / OR Boolean operator
o Filter


4 SQLite Database 33 Basic4Android User's Guide
Parts of the source code

Not all the code will be explained here, only some more specific parts.

Main Activity

Declaration of the Global variables.

Sub Gl obal s
Di mwbvTabl e As WebVi ew
Di mbt nAdd, bt nEdi t , bt nFi l t er , bt nSet Fi l t er As But t on
Di ml bl Sel ect edI t emAs Label

' used i n Execut eHTML
Di mHt ml CSS As St r i ng
Ht ml CSS = "t abl e {wi dt h: 100%; bor der : 1px sol i d #cef ; t ext - al i gn: l ef t ; }" _
& " t h { f ont - wei ght : bol d; backgr ound- col or : #acf ; bor der - bot t om: 1px
sol i d #cef ; }" _
& "t d, t h { paddi ng: 4px 5px; }" _
& ". odd {backgr ound- col or : #def ; } . odd t d {bor der - bot t om: 1px sol i d #cef ;
}" _
& "a { t ext - decor at i on: none; col or : #000; }"
End Sub

Ht ml CSS is the string for the html call.

Show the database in a WebView.

We define the SQL query.
Depending if the filter is active we add the filter query and change the filter button text.
We load the databse query result in a WebView and read the database IDs.

' Shows t he dat abase i n a t abl e i n a WebVi ew
Sub ShowTabl e
Di mQuer y As St r i ng

Quer y = "SELECT I D, Fi r st Name As [ Fi r st name] , Last Name As [ Last name] , Ci t y
FROM per sons"
' dependi ng i f t he f i l t er i s act i ve or not we add t he f i l t er quer y at t he end
of t he quer y
' t he f i l t er quer y i s def i ned i n t he Fi l t er Act i vi t y
I f Fi l t er . f l agFi l t er Act i ve = Fal se Then
bt nFi l t er . Text = "Fi l t er " ' change t he t ext i n t he Fi l t er but t on
El se
Quer y = Quer y & Fi l t er . Quer y
bt nFi l t er . Text = "UnFi l t er " ' change t he t ext i n t he Fi l t er but t on
End I f
' di spl ays t he dat abase i n a t abl e
wbvTabl e. LoadHt ml ( Execut eHt ml ( SQL1, Quer y, Nul l , 0, Tr ue) )
ReadDat aBaseI Ds
End Sub

4 SQLite Database 34 Basic4Android User's Guide
Generate the html string used in wbvTable.LoadHtml.

' Thi s r out i ne i s ext r act ed f r omt he DBUt i l s code modul e
' Cr eat es a ht ml t ext t hat di spl ays t he dat a i n a t abl e.
' The st yl e of t he t abl e can be changed by modi f yi ng Ht ml CSS var i abl e.
Sub Execut eHt ml ( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng, Li mi t As
I nt , Cl i ckabl e As Bool ean) As St r i ng
Di mcur As Cur sor
I f St r i ngAr gs <> Nul l Then
cur = SQL. ExecQuer y2( Quer y, St r i ngAr gs)
El se
cur = SQL. ExecQuer y( Quer y)
End I f
Log( "Execut eHt ml : " & Quer y)
I f Li mi t > 0 Then Li mi t = Mi n( Li mi t , cur . RowCount ) El se Li mi t = cur . RowCount
Di msb As St r i ngBui l der
sb. I ni t i al i ze
sb. Append( "<ht ml ><body>") . Append( CRLF)
sb. Append( "<st yl e
t ype=' t ext / css' >") . Append( Ht ml CSS) . Append( "</ st yl e>") . Append( CRLF)
sb. Append( "<t abl e><t r >") . Append( CRLF)
For i = 0 To cur . Col umnCount - 1
sb. Append( "<t h>") . Append( cur . Get Col umnName( i ) ) . Append( "</ t h>")
Next

sb. Append( "</ t r >") . Append( CRLF)
For r ow = 0 To Li mi t - 1
cur . Posi t i on = r ow
I f r ow Mod 2 = 0 Then
sb. Append( "<t r >")
El se
sb. Append( "<t r cl ass=' odd' >")
End I f
For i = 0 To cur . Col umnCount - 1
sb. Append( "<t d>")
I f Cl i ckabl e Then
sb. Append( "<a hr ef =' ht t p: / / ") . Append( i ) . Append( ". ")
sb. Append( r ow)
sb. Append( ". com' >") . Append( cur . Get St r i ng2( i ) ) . Append( "</ a>")
El se
sb. Append( cur . Get St r i ng2( i ) )
End I f
sb. Append( "</ t d>")
Next
sb. Append( "</ t r >") . Append( CRLF)
Next
cur . Cl ose
sb. Append( "</ t abl e></ body></ ht ml >")
Ret ur n sb. ToSt r i ng
End Sub





4 SQLite Database 35 Basic4Android User's Guide
Event handling of the WebView.

This routine is taken from the DBUtils module.
The URL variable hold the return value from the WebView event.
It could look like this ht t p/ / 2. 7. com/ where 2 is the col index and 7 is the row index.
The col and row values are extracted in val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
values(0) holds the col value
values(1) holds the row value
values(2) holds the end of the string

' Rout i ne f r omt he DBUt i l s demo pr ogr am
Sub wbvTabl e_Over r i deUr l ( Ur l As St r i ng) As Bool ean
' par se t he r ow and col umn number s f r omt he URL
Di mval ues( ) As St r i ng
val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
Di mcol , r ow As I nt
col = val ues( 0)
r ow = val ues( 1)
Cur r ent I ndex = r ow
Updat eSel ect edI t em
Ret ur n Tr ue ' Don' t t r y t o navi gat e t o t hi s URL
End Sub

Edit Activity.

In the Edit acrivity there is nothing really special.

Filter Activity.

Process Global variables declaration.

Most of the code is self explanatory.

The Query valiable is used in the Main activity to add the filter query.

Sub Pr ocess_Gl obal s
' var i abl e f or t he f i l t er quer y,
' def i ned i n t he bt nFi l t er _Cl i ck r out i ne
' and wi l l be used I n t he DBWebVi ew ShowTabl e r out i ne
Di mQuer y = "" As St r i ng

' f l ag f or t he f i l t er act i ve or i nact i ve
Di mf l agFi l t er Act i ve = Fal se As Bool ean

' Bool ean oper at or used i n t he f i l t er
' can be OR or AND
Di mBool eanOper at or = "OR " As St r i ng

' Var i abl es used t o hol d t he sel ect ed i ndexes of t he Spi nner s
Di mSel ect edFi r st Name = 0 As I nt
Di mSel ect edLast Name = 0 As I nt
Di mSel ect edCi t y = 0 As I nt
End Sub

4 SQLite Database 36 Basic4Android User's Guide
For the data selection in the filter we use Spinners, these are filled with the data from the database.
But as there can be multiple entries with the same data we fill them with distinct data, one name is
shown only once.

The code is shown for one Spinner only, the principle is the same for the others.

' I ni t i al i ze t he Spi nner s
Sub I ni t Spi nner s
Di mi As I nt
Di mQuer y1 As St r i ng
Di mCur s As Cur sor

' We execut e a quer y f or each col umn and f i l l t he Spi nner
' We use SELECT DI STI NCT t o have each exi st i ng f i r st name i n t he dat abase onl y
once
' Quer y1 = "SELECT DI STI NCT Fi r st Name FROM per sons"
Quer y1 = "SELECT DI STI NCT Fi r st Name FROM per sons ORDER BY Fi r st Name ASC"
Cur s = Mai n. SQL1. ExecQuer y( Quer y1)
' we add ' no f i l t er ' as no sel ect i on
spnFi r st Name. Add( "no f i l t er ")
' we f i l l t he Spi nner wi t h t he dat a f r omt he dat abase
For i = 0 To Cur s. RowCount - 1
Cur s. Posi t i on = i
spnFi r st Name. Add( Cur s. Get St r i ng( "Fi r st Name") )
Next



4 SQLite Database 37 Basic4Android User's Guide
4.6 SQLi te Database third simple example program

A third example program is in the SourceCode\SQL\SQLiteLight3 folder.

This program is almost the same as SQLiteLight2, all functions are the same.
The differences are the database path, database name, table name, columb number, column names,
column alias names and column data types are variables instead beeing hard coded.

It allows also to generate a new database by:
- changing in Globals the values of the variables listed above
- in Activity_Create
-- comment this line : 'File.Copy(File.DirAssets, SQLDateBaseName, SQLDataBasePath,
SQLDateBaseName)
-- uncomment this line : CreateDataBase

The code has comments and is, I hope, self explanatory.

One example to show the difference:

For the query to show the table.

In SQLiteLight2 the names are hard coded:

Sub ShowTabl e
Di mi As I nt
Di mQuer y As St r i ng
Quer y = "SELECT I D, Fi r st Name As [ Fi r st name] , Last Name As [ Last name] , _
Ci t y FROM per sons"

In SQLiteLight3 the names are varaibles defined in Globals:

Sub ShowTabl e
Di mi As I nt
Di mQuer y As St r i ng

Quer y = "SELECT "
For i = 0 To Col Number - 1
I f i < Col Number - 1 Then
Quer y = Quer y & Col Names( i ) & " As [ " & Col Al i asNames( i ) & "] , "
El se
Quer y = Quer y & Col Names( i ) & " As [ " & Col Al i asNames( i ) & "] "
End I f
Next
Quer y = Quer y & " FROM " & SQLTabel Name

4 SQLite Database 38 Basic4Android User's Guide
4.7 SQLi te Database fourth exampl e program

This SQLite example program is a more elaborated application with a small database with persons,
with First name, Last name, Address and City as the persons parameters.

The source code of this example is in the SourceCode\SQL\SQLExample project.



Database view Edit activity Filter activity

The layouts in the ScrollViews of the Edit and Filter activities are created automatically.




4 SQLite Database 39 Basic4Android User's Guide
What we can do:

Ordering according to a given column

Clicking on a header sorts the database according to this column in ASC ascending mode.

Default or click on Click on




Click on to delete the current data set.

Click on to filter the database.

Click on to show the Filter activity.

Click on to edit the data set.


4 SQLite Database 40 Basic4Android User's Guide
4.7.1 Editing

Select a data set in the main activity and click on to display the Editor screen below.




Here we can: - Change values

Move to the previous data set

Move to the next data set.

Add the data set to the database.

Modify the current data set.

Go back to the main screen.
4 SQLite Database 41 Basic4Android User's Guide
4.7.2 Filtering

In the main view:



A click on filters the database according to the filter parameters.

A click on resets the database to unfiltered.

A click on displays the Filter activity.

What can we do :

Enter different filtering parameters.
Select for example:
- FirstName John
- City London

Filtering AND function, green active function.

Filtering OR function.

Clear all parameters.

Filters the database.

Go back to the main screen.



There exist only one person
with the first name John AND living in London.



4 SQLite Database 42 Basic4Android User's Guide


Click on to change the AND parameter to OR and
click on .

The active logical operator is displayed in green.

There are three persons with the first name of John
OR living in London.








4.7.3 Code

Not all the code is explained in detail, only some parts needing a more detailed explanation.
The code is, at least I hope so, well documented

The program has been updated taking advantage of recent features of Basic4Android.
Examaple: Usage of anchors^in the layouts.

Let us define a simple database with persons. Each person has a certain number of parameters,
called a data set or a database entry.
Person:
First name
Last name
Address
City

It is good practice to add an additional column, called 'ID' with a unique number to differentiate the
data sets.
So the columns are: ID, FirstName, LastName, Address, City

Each column must be given a variable type: INTEGER, TEXT, REAL, BLOB .
In our database example we have following types:
ID INTEGER PRIMARY KEY
FirstName TEXT
LastName TEXT
Address TEXT
City TEXT
4 SQLite Database 43 Basic4Android User's Guide
4.7.3.1 Main Activity

In Process_Globals
We define the variables below:
Di mCol umnName( Number Of Col umns) As St r i ng ' names of t he col umns
Col umnName( 0) = "I D"
Col umnName( 1) = "Fi r st Name"
Col umnName( 2) = "Last Name"
Col umnName( 3) = "Addr ess"
Col umnName( 4) = "Ci t y"
Di mCol umnAl i asName( Number Of Col umns) As St r i ng ' al i as names of t he
col umns
Col umnAl i asName( 0) = "I D"
Col umnAl i asName( 1) = "Fi r st name"
Col umnAl i asName( 2) = "Last name"
Col umnAl i asName( 3) = "Addr ess"
Col umnAl i asName( 4) = "Ci t y"

ColumName is obvious, the ColumnAliasNames ase used to display the table headers, this is useful
to give more meaningful names or to chage the name in multilangage programs.

In Activity_Create
We initialize the RowID List which holds the IDs of the datasets of each row.

' i ni t i al i ze t he RowI D
I f RowI D. I sI ni t i al i zed = Fal se Then
RowI D. I ni t i al i ze
End I f

In Activity_Resume
This code reads the table name of the database.
' get s t he t abl e name of t he dat abase
Di mcur s As Cur sor
cur s = SQL1. ExecQuer y( "SELECT name FROM sql i t e_mast er WHERE Type=' t abl e' ")
cur s. Posi t i on = 0
DBTabl eName = cur s. Get St r i ng( "name")
cur s. Cl ose


4 SQLite Database 44 Basic4Android User's Guide
The column widths are calculated in this routine:

' Cal cul at es t he wi dt h of t he gi ven col umn
Sub Cal cul at eCol umnWi dt h( Header Name As St r i ng, Col umName As St r i ng) As I nt
Di mCur s As Cur sor
Di mr ow, MaxNumber Of Char s As I nt

' r eads t he max number of char act er s i n t he col umn
MaxNumber Of Char s = SQL1. ExecQuer ySi ngl eResul t ( "SELECT max( l engt h( " & _
Col umName & ") ) FROM " & DBTabl eName)
' get s al l r ows wi t h t he max number of char act er s
Cur s = SQL1. ExecQuer y( "SELECT " & Col umName & " FROM " & DBTabl eName & " _
WHERE l engt h( " & Col umName & ") = " & MaxNumber Of Char s)
Cur s. Posi t i on = 0
Di mText MaxWi dt h As I nt
' measur es t he t ext wi dt h i n pi xel s of t he header name
Text MaxWi dt h = cvs. Measur eSt r i ngWi dt h( Header Name, Typef ace. DEFAULT, Font Si ze)
For r ow = 0 To Cur s. RowCount - 1
Cur s. Posi t i on = r ow
' get s t he max t ext wi dt h of t he t ext
Text MaxWi dt h = Max( Text MaxWi dt h, _
cvs. Measur eSt r i ngWi dt h( Cur s. Get St r i ng( Col umName) , Typef ace. DEFAULT, Font Si ze) )
Next
Cur s. Cl ose
' r et ur ns t he max t ext wi dt h + 10di p as mar gi n
Ret ur n Text MaxWi dt h + 10di p
End Sub

We :
Read the maximum character of the data in each column.
Read the rows with the longest content for each column.
Calculate the width of header text.
Calculate the width of the long column texts.
Keep the maximum width value.
Add a margin of 10dip.


4 SQLite Database 45 Basic4Android User's Guide
4.7.3.2 Edit activity

Almost all the code is explained in the source file.

In the EditDispItem
We have this code:
' set s t he Text pr oper t i es
For col = 0 To Mai n. Number Of Col umns - 1
Di medt As Edi t Text
edt = scvEdi t . Panel . Get Vi ew( col * 2 + 1)
edt . Text = Cur sor 1. Get St r i ng( Mai n. Col umnName( edt . Tag) )
Next

What does this edt = scvEdi t . Panel . Get Vi ew( col * 2 + 1) mean ?
We want to get the view with the given index ( col * 2 + 1) from the
ScrollView.Panel scvEdi t . Panel

In the ScrollView.Panel we have a Label and an EditText view per column.
The view index begins with 0 and is incremented by one each time we add a view.
So :
View Column Index
Label0 0 0
EditText0 0 1
Label1 1 2
EditText1 1 3
Label2 2 4
EditText2 2 5
Label3 3 6
EditText3 3 7

If we want to get the EditText view for column 3.
We calculate col * 2 +1 = 3 * 2 +1 =7 which is the index of the EditText view for column 3.
Therefore :
edt = scvEdi t . Panel . Get Vi ew( col * 2 + 1)



4 SQLite Database 46 Basic4Android User's Guide
4.7.3.3 Filter Activity

Almost all the code is explained in the source file.

For the Filter we use a Spinner for each column except for the first one, the ID column.
The Spinners are filled with all DISTICT values from each column.

The query looks like this:
SELECT DI STI NCT Col umnName FROM Tabl eName ORDER BY Col umnName ASC

And the code filling the Spinners:
' We get al l DI STI NCT val ues f or each col umn
' and f i l l t he Spi nner s wi t h t hese val ues
Di mt xt As St r i ng
t xt = "SELECT DI STI NCT " & Mai n. Col umnName( col ) & " FROM " & _
Mai n. DBTabl eName & " ORDER BY " & Mai n. Col umnName( col ) & " ASC"
Cur s = Mai n. SQL1. ExecQuer y( t xt )
spn. Cl ear
spn. Add( "ALL")
For r ow = 0 To Cur s. RowCount - 1
Cur s. Posi t i on = r ow
spn. Add( Cur s. Get St r i ng( Mai n. Col umnName( col ) ) )
Next


Another approach could have been to use EditText views, instead of the Spinners, to enter texts and
check if there exist data with the given text or containing the given text in the given column.




5 DBUtils 47 Basic4Android User's Guide
5 DBUtils

For those who are not familiar with SQLite, Erel has written the DBUtils code module that should
make things easier.

Note: DBUtils is a code module and not a library!
To use it, you must load the file DBUtils .bas to your project in the IDE menu Project / Add
Existing Module. This will add the module to your project.






5 DBUtils 48 Basic4Android User's Guide
5.1 DBUtil s functions

CopyDBFromAssets( Fi l eName As St r i ng) As St r i ng
Copies a database file that was added in the Files tab. The database must be copied to a
writable location because it is not possible to access a database located in File.DirAssets.
This method copies the database to the storage card Fi l e. Di r Def aul t Ext er nal . If the
storage card is not available the file is copied to the internal folder Fi l e. Di r I nt er nal .
The target folder is returned. If the database file already exists then no copying is done.

CreateTable( SQL As SQL, Tabl eName As St r i ng, Fi el dsAndTypes As Map,
Pr i mar yKey As St r i ng)
Creates a new table with the given name.
Fi el dsAndTypes - A map with the fields names as keys and the types as values.
You can use the DB_... constants for the types.
Pr i mar yKey - The column that will be the primary key. Pass empty string if not needed.

DropTable( SQL As SQL, Tabl eName As St r i ng)
Deletes the given table.

InsertMaps( SQL As SQL, Tabl eName As St r i ng, Li st Of Maps As Li st )
Inserts the data to the table.
Li st Of Maps - A list with maps as items. Each map represents a record where the map keys
are the columns names and the maps values are the values.
Note that you should create a new map for each record (this can be done by calling Dim to
redim the map).

UpdateRecord( SQL As SQL, Tabl eName As St r i ng, Fi el d As St r i ng, NewVal ue As
Obj ect , Wher eFi el dEqual s As Map)
Updates a record in the database.
Fi el d - Column name
NewVal ue - new value
Wher eFi el dEqual s - Map where the map keys are the column names and the map values
the values to look for.

ExecuteMemoryTable( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng,
Li mi t As I nt ) As Li st
Executes the query and returns the result as a list of arrays.
Each item in the list is a strings array.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
Li mi t - Limits the results. Pass 0 for all results.

5 DBUtils 49 Basic4Android User's Guide
ExecuteMap( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng) As Map
Executes the query and returns a Map with the column names as the keys and the first record
values As the entries values.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
The keys are lower cased.
Returns Null if no results found.

ExecuteSpinner( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng, Li mi t
As I nt , Spi nner 1 As Spi nner )
Executes the query and fills the Spinner with the values in the first column.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
Li mi t - Limits the results. Pass 0 for all results.

ExecuteListView( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng, Li mi t
As I nt , Li st Vi ew1 As Li st Vi ew, TwoLi nes As Bool ean)
Executes the query and fills the ListView with the value.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
Li mi t - Limits the results. Pass 0 for all results.
If TwoLi nes is true then the first column is mapped to the first line and the second column is
mapped to the second line.
In both cases the value set to the row is the array with all the records values.

ExecuteJSON( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng, Li mi t As
I nt , DBTypes As Li st ) As Map
Executes the given query and creates a Map that you can pass to JSONGenerator and
generate JSON text.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
Li mi t - Limits the results. Pass 0 for all results.
DBTypes - Lists the type of each column in the result set.
Usage example: (don't forget to add a reference to the JSON library)
Dim gen As JSONGenerator
gen.Initialize(DBUtils.ExecuteJSON(SQL, "SELECT Id, Birthday FROM Students",
Null, 0, Array As String(DBUtils.DB_TEXT, DBUtils.DB_INTEGER)))
Dim JSONString As String
JSONString =gen.ToPrettyString(4)
Msgbox(JSONString, "")

ExecuteHtml( SQL As SQL, Quer y As St r i ng, St r i ngAr gs( ) As St r i ng, Li mi t As
I nt , Cl i ckabl e As Bool ean) As St r i ng
Creates a html text that displays the data in a table.
The style of the table can be changed by modifying HtmlCSS variable.
St r i ngAr gs( ) - Values to replace question marks in the query. Pass Null if not needed.
Li mi t - Limits the results. Pass 0 for all results.

GetDBVersion( SQL As SQL) As I nt
Gets the current version of the database.
If the DBVersion table does not exist it is created and the current version is set to version 1.

SetDBVersion( SQL As SQL, Ver si on As I nt )
Sets the database version to the given version number.


5 DBUtils Example program 50 Basic4Android User's Guide
5.2 Exampl es

You find Erels' example in the Forum under DBUtils - Android databases are now simple.
This example will not be explained in this chapter.

5.2.1 Example program Main modul e

The example program in this chapter shows small examples of the DBUtils basics.
The database used is persons.db from the SQLExample in the previous chapter.

The project, SQLDBUtils, is in the SourceCode folder.

The program has different activities showing each some of the DBUtils functions.

DBUtils function used :
DBUt i l s. CopyDBFr omAsset s




Show the table in a WebView

Show the FirstName and LastName in a ListView

Show the table in Spinners

Edit the database









The code:

Definition of the process global variables : there are no global variables

Sub Pr ocess_Gl obal s
Di mDBFi l eName As St r i ng : DBFi l eName = "per sons. db"
Di mDBFi l eDi r As St r i ng ' : DBFi l eDi r = Fi l e. Di r Def aul t Ext er nal
Di mDBTabl eName As St r i ng : DBTabl eName = "per sons"

Di mSQL1 As SQL
End Sub

Sub Gl obal s

End Sub

5 DBUtils Example program 51 Basic4Android User's Guide
Activity_Create routine :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
I f Fi r st Ti me Then
' Fi l e. Del et e( Fi l e. Di r Def aul t Ext er nal , DBFi l eName) ' f or t est i ng

I f Fi l e. Exi st s( Fi l e. Di r Def aul t Ext er nal , DBFi l eName) = Fal se Then
DBFi l eDi r = DBUt i l s. CopyDBFr omAsset s( DBFi l eName)
End I f
SQL1. I ni t i al i ze( DBFi l eDi r , DBFi l eName, Tr ue)
End I f

Act i vi t y. LoadLayout ( "mai n")
End Sub

If FirstTime =True, then we copy the database from the File.DirAssets directory to another
folder if it doesn't already exist.
For testing you could uncomment the line File.Delete... to delete the current database and
replace it by the original one.
By default, DBUtils tries to copy the database to File.DirDefaultExternal if this one is
writable, if not then the database is copied to File.DirInternal.
If the database already exists in the other folder nothing happens.
Initialize the database.
Load the mai n layout file for the main Activity.

btnSelect routine :

Sub bt nSel ect _Cl i ck
Di mbt n As But t on

bt n = Sender

St ar t Act i vi t y( bt n. Tag)
End Sub

All the Buttons have the same EventName bt nSel ect defined in the Designer.
The Button.Tag property, bt n. Tag in the example, is the name of the Activity we want to start, also
defined in the Designer.
The advantage is that we can add a new button to call a new Activity without the need to modify the
code of the main module.


5 DBUtils Example program 52 Basic4Android User's Guide
5.2.2 Show the table in a WebView

This example is the minimum needed to display a database, extracted from Erels' code.

DBUtils function used :
DBUt i l s. Execut eHt ml

Two different displays are shown:
First and last name in a same column with Name as column name.
First and last name in two separate columns.



The code:

Definition of the global variables : There are no process global variables.

Sub Gl obal s
Di mWebVi ew1 As WebVi ew
Di mr bt Fi r st Last Name, r bt Fi r st NameLast Name As Radi oBut t on
End Sub

Activity_Create routine :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Act i vi t y. LoadLayout ( "webvi ew")

WebVi ew1. Hei ght =100%y- ( r bt Fi r st NameLast Name. Top+ r bt Fi r st NameLast Name. Hei ght )
ShowTabl eI nWebVi ew( 0)
End Sub

We
Load the activity layout.
Set the WebView height, adapts for different height/width ratios.
Display the database in the WebView.

5 DBUtils Example program 53 Basic4Android User's Guide
ShowTableInWebView routine :

Sub ShowTabl eI nWebVi ew( Mode As I nt )
Di mQuer y As St r i ng

I f Mode = 0 Then
Quer y = "SELECT I D, [ Fi r st Name] | | ' ' | | [ Last Name] As Name, Addr ess, Ci t y
FROM " & Mai n. DBTabl eName
El se
Quer y = "SELECT I D, Fi r st Name As [ Fi r st name] , Last Name As [ Last name] ,
Addr ess, Ci t y FROM " & Mai n. DBTabl eName
End I f
WebVi ew1. LoadHt ml ( DBUt i l s. Execut eHt ml ( Mai n. SQL1, Quer y, Nul l , 0, Tr ue) )
End Sub

This routine shows the database in a table in a WebView.
Mode defines the display mode,
0 =FirstName and LastName in one column.
1 =FirstName and LastName in two separate columns.

The query texts need some explanations (second Query):
SELECT SQL query keyword
I D is the DB column name and the same column name is used in the header
Fi r st Name As [ Fi r st name]
Fi r st Name is the DB column name
As for alias, header name different from the column name
[ Fi r st name] is the header name, the [ ] are needed because of the space between
First and name
Last Name As [ Last name]
Last Name DB column name
As for alias, header name different from the column name
[ Last name] header name
Addr ess DB column name and header name
Ci t y DB column name and header name
FROM SQL query keyword
DBTabl eName table name, in this case a variable

Several DB columns can be combined to one table column, this is shown in this line :
t xt = "SELECT I D, [ Fi r st Name] | | ' ' | | [ Last Name] As Name, Addr ess As Addr ess,
Ci t y As Ci t y FROM " & DBTabl eName

[ Fi r st Name] | | ' ' | | [ Last Name] As Name combines the values of the [ Fi r st Name] column
with the value of the [ Last Name] column with a space ' ' between them and Name as the header
name.



Fist and last name in a same column. Fist and last name in two separate columns.

5 DBUtils Example program 54 Basic4Android User's Guide
The call of the WebView :

WebVi ew1. LoadHt ml ( DBUt i l s. Execut eHt ml ( SQL1, Quer y, Nul l , 0, Tr ue) )

Where we call DBUt i l s. Execut eHt ml with :
SQL1 SQL object
Quer y the SQL query
Nul l no array
0 no limit
Tr ue WebView clickable, if True the WebVi ew1_Over r i deUr l event will be raised.

The WebView event routine :

This routine is called when a cell in the table is selected and returns a ToastMessage with the row
and column index.

Sub WebVi ew1_Over r i deUr l ( Ur l As St r i ng) As Bool ean
' par se t he r ow and col umn number s f r omt he URL
Di mval ues( ) As St r i ng
val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
Di mcol , r ow As I nt
col = val ues( 0)
r ow = val ues( 1)
Toast MessageShow( "User pr essed on col umn: " & col & " and r ow: " & r ow,
Fal se)
Ret ur n Tr ue ' Don' t t r y t o navi gat e t o t hi s URL
End Sub

The returned value of Utl = ht t p: / / col. row. com/ Example : ht t p: / / 1. 3. com/

We :
Dim a string array values
Split the Url string with val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
Ur l . SubSt r i ng( 7) =1. 3. com/ substring beginning with the 7th character till the end.
Dim col and r ow as Integers
col = val ues( 0) and r ow = val ues( 1)
Display a ToastMessage with the two values.
Return Tr ue to consume the event, to not transmit it to the operating system.


5 DBUtils Example program 55 Basic4Android User's Guide
RadioButton CheckedChange event routine :

Sub r bt Sel ect Mode_CheckedChange( Checked As Bool ean)
Di mr bt As Radi oBut t on

I f Checked Then
r bt = Sender
ShowTabl eI nWebVi ew( r bt . Tag)
End I f
End Sub

The two RadioButtons have the same EventName r bt Sel ect Mode defined in the Designer.
The Tag properties are :
0 for First and last name in the same column.
1 for First and last name in two separate columns.

We :
Dim r bt as a local RadioButton.
If Checked =True then we :
Set r bt = Sender , the RadioButton that raised the event.
Display the table according the selected display mode.






5 DBUtils Example program 56 Basic4Android User's Guide
5.2.3 Show FirstName and LastName in a ListView

This activity shows how to display the content of two columns side by side in a ListView.
The 'specialty' is that the two Labels for each item are side by side and not one on top the other.

DBUtils function used :
DBUt i l s. Execut eLi st Vi ew



The code:

Definition of the global variables : There are no process global variables.

Sub Gl obal s
Di mLi st Vi ew1 As Li st Vi ew
End Sub


Activity_Create routine :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Act i vi t y. LoadLayout ( "l i st vi ew")

Li st Vi ew1. Hei ght = 100%y

Li st Vi ewI ni t
Li st Vi ewFi l l
End Sub

We
Load the activity layout.
Set the ListView height.
Initialize the ListView properties.
Fill the ListView.

5 DBUtils Example program 57 Basic4Android User's Guide
The ListViewInit routine :

Sub Li st Vi ewI ni t
Li st Vi ew1. TwoLi nesLayout . I t emHei ght = 40di p
Li st Vi ew1. TwoLi nesLayout . Label . Lef t = 0
Li st Vi ew1. TwoLi nesLayout . Label . Wi dt h = 50%x
Li st Vi ew1. TwoLi nesLayout . Label . Hei ght = 40di p
Li st Vi ew1. TwoLi nesLayout . Label . Gr avi t y = Gr avi t y. CENTER_VERTI CAL
Li st Vi ew1. TwoLi nesLayout . Label . Col or = Col or s. Red
Li st Vi ew1. TwoLi nesLayout . Label . Text Si ze = 18

Li st Vi ew1. TwoLi nesLayout . SecondLabel . Top = 0
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Lef t = 50%x
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Wi dt h = 50%x
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Hei ght = 40di p
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Gr avi t y = Gr avi t y. CENTER_VERTI CAL
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Col or = Col or s. Bl ue
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Text Col or = Col or s. Yel l ow
Li st Vi ew1. TwoLi nesLayout . SecondLabel . Text Si ze = 18
End Sub

We :
Set the I t emHei ght = 40di p
Set the Lef t , Wi dt h, Hei ght , Gr avi t y, Col or and Text Si ze
properties for the first Label.
Set the Top, Lef t , Wi dt h, Hei ght , Gr avi t y, Col or , Text Col or and Text Si ze
properties for the second Label.

The ListViewFill routine :

Sub Li st Vi ewFi l l
Di mQuer y As St r i ng

Quer y = "SELECT Fi r st Name, Last Name FROM " & Mai n. DBTabl eName

DBUt i l s. Execut eLi st Vi ew( Mai n. SQL1, Quer y, Nul l , 0, Li st Vi ew1, Tr ue)
End Sub

The Query :
SELECT SQL keyword.
Fi r st Name Last Name the two selected column names.
FROM SQL keyword.
Mai n. DBTabl eName the table name, in this case a process global variable

We call DBUt i l s. Execut eLi st Vi ew with
Mai n. SQL1 the database
Quer y the SQL query
Nul l no string array
0 no limit
Li st Vi ew1 the ListView view
Tr ue for two lines ListView (False =one line ListView)



5 DBUtils Example program 58 Basic4Android User's Guide
5.2.4 Display database in Spinners

In this activity we have one Spinner for each column.
Selecting an item in one of the Spinners sets the other Spinners to display the values of the same
record and shows all records with the same selected value.

DBUtils function used :
DBUt i l s. Execut eSpi nner
DBUt i l s. Execut eHt ml



SMITH selected. Las Vegas selected.

The code:

Definition of the global variables : There are no process global variables.

Sub Gl obal s
Di mspnFi r st Name, spnLast Name, spnAddr ess, spnCi t y As Spi nner
Di mWebVi ew1 As WebVi ew
End Sub

Activity_Create routine :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)

Act i vi t y. LoadLayout ( "Spi nner ")

WebVi ew1. Hei ght = 100%y - ( spnCi t y. Top + spnCi t y. Hei ght + 8di p)
Fi l l Spi nner s
End Sub

We
Load the activity layout.
Set the WebView height, adapts for different height/width ratios.
Fill the Spinners.
5 DBUtils Example program 59 Basic4Android User's Guide
The FillSpinners routine :

Sub Fi l l Spi nner s
Di mQuer y As St r i ng

Quer y = "SELECT Fi r st Name FROM " & Mai n. DBTabl eName
spnFi r st Name. Cl ear
DBUt i l s. Execut eSpi nner ( Mai n. SQL1, Quer y, Nul l , 0, spnFi r st Name)

Quer y = "SELECT Last Name FROM " & Mai n. DBTabl eName
spnLast Name. Cl ear
DBUt i l s. Execut eSpi nner ( Mai n. SQL1, Quer y, Nul l , 0, spnLast Name)

Quer y = "SELECT Addr ess FROM " & Mai n. DBTabl eName
spnAddr ess. Cl ear
DBUt i l s. Execut eSpi nner ( Mai n. SQL1, Quer y, Nul l , 0, spnAddr ess)

Quer y = "SELECT Ci t y FROM " & Mai n. DBTabl eName
spnCi t y. Cl ear
DBUt i l s. Execut eSpi nner ( Mai n. SQL1, Quer y, Nul l , 0, spnCi t y)
End Sub

We :
Dim the Quer y variable.
Define the Quer y for the spnFi r st Name Spinner.
Call the DBUt i l s. Execut eSpi nner routine.
Mai n. SQL1 the SQL database
Quer y the SQL query
Nul l no string array
0 no limit
spnFi r st Name the Spinner name

The Query for the FirstName Spinner :
SELECT SQL keyword.
Fi r st Name the column name to read.
FROM SQL keyword.
Mai n. DBTabl eName the table name, in this case a process global variable.

The same principle is used for the other Spinners, the only differences are the column names and
the Spinners.



5 DBUtils Example program 60 Basic4Android User's Guide
5.2.5 Edit database

In this Activity we can modify a record and update the database.

DBUtils function used :
DBUt i l s. Execut eHt ml
DBUt i l s. Updat eRecor d
DBUt i l s. Execut eMemor yTabl e
DBUt i l s. I nser t Maps
DBUt i l s. Del et eRecor d

We have four EditText views for the record values, a WebView to display the database and three
Buttons for updating, adding or deleting a record.

Following functions are available:
Select a record in the WebView, the EditText views are updated.
Update the selected record in the table with the new value in the EditText views.
Add a new record to the table with the values in the EditText views.
Delete the selected record.

Update a record



Select a record in the WebView in the example SMITH .
All the EditText views are updated.
Change the first name from John to John-John.
Click to update the database, a message box asks for confirmation.
The database in the WebView is updated.

5 DBUtils Example program 61 Basic4Android User's Guide
Add a new record



Select a line, the first one in this example
Enter the new values in the EditText views.
Click to add the new record.
The database in the WebView is updated.

Delete a record



Select a record in the WebView in the example SMITH .
Click to delete the record, a message box asks for confirmation.
The database in the WebView is updated.
The EditText views are empty.



5 DBUtils Example program 62 Basic4Android User's Guide
The code:

Definition of the global variables : There are no process global variables.

Sub Gl obal s
Di medt Fi r st Name, edt Last Name, edt Addr ess, edt Ci t y As Edi t Text
Di mbt nUpdat e As But t on
Di mWebVi ew1 As WebVi ew
Di ml st Tabl e As Li st
Di mpnl Tool Box As Panel

Di mcol , r ow, I D As I nt
End Sub

Activity_Create routine :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Act i vi t y. LoadLayout ( "edi t ")

pnl Tool Box. Top = 100%y - pnl Tool Box. Hei ght
WebVi ew1. Hei ght = pnl Tool Box. Top - ( edt Ci t y. Top + edt Ci t y. Hei ght + 4di p)

Fi l l WebVi ew
pnl Tool Box. Vi si bl e = Fal se
End Sub

We
Load the activity layout.
Set the btnUpdate Button Top property.
Set the WebView height, adapts for different height/width ratios.
Fill the WebView.
Hide the buttons, ToolBox.

The FillWebView routine :

Sub Fi l l WebVi ew
Di mQuer y As St r i ng

Quer y = "SELECT * FROM " & Mai n. DBTabl eName
' t he l i ne above does t he same as t he l i ne bel ow
' i n bot he cases t he WebVi ew col umn names ar e t he same as t he DB col umn names
' Quer y = "SELECT I D, Fi r st Name, Last Name, Addr ess, Ci t y FROM " &
Mai n. DBTabl eName

WebVi ew1. LoadHt ml ( DBUt i l s. Execut eHt ml ( Mai n. SQL1, Quer y, Nul l , 0, Tr ue) )
l st Tabl e = DBUt i l s. Execut eMemor yTabl e( Mai n. SQL1, Quer y, Nul l , 0)
End Sub

It's similar to the routine in chapter 4.2.2 Show the table in a WebView.

5 DBUtils Example program 63 Basic4Android User's Guide
The WebView event routine :

This routine is called when a cell in the table is selected and returns a ToastMessage with the row
and column index.

Sub WebVi ew1_Over r i deUr l ( Ur l As St r i ng) As Bool ean
' par se t he r ow and col umn number s f r omt he URL
Di mval ues( ) As St r i ng
val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
col = val ues( 0)
r ow = val ues( 1)

Di mval ( 5) As St r i ng
val = l st Tabl e. Get ( r ow)
I D = val ( 0)
edt Fi r st Name. Text = val ( 1)
edt Last Name. Text = val ( 2)
edt Addr ess. Text = val ( 3)
edt Ci t y. Text = val ( 4)
pnl Tool Box. Vi si bl e = Tr ue
Ret ur n Tr ue ' Don' t t r y t o navi gat e t o t hi s URL
End Sub

The returned value of Utl = ht t p: / / col. row. com/ Example : ht t p: / / 1. 3. com/

We :
Dim a string array values
Split the Url string with val ues = Regex. Spl i t ( "[ . ] ", Ur l . SubSt r i ng( 7) )
Ur l . SubSt r i ng( 7) =1. 3. com/ substring beginning with the 7th character till the end.
Dim col and r ow as Integers
col = val ues( 0) and r ow = val ues( 1)
Display a ToastMessage with the two values.
Return Tr ue to consume the event, to not transmit it to the operating system.

5 DBUtils Example program 64 Basic4Android User's Guide
The btnUpdate_Click routine :

Sub bt nUpdat e_Cl i ck
Di mAnsw As I nt

Answ = Msgbox2( " Do you r eal l y want t o updat e t hi s ent r y ?", " ATTENTI ON" , "Yes", " ",
" No" , Nul l )

I f Answ = Di al ogResponse. POSI TI VE Then
Di mmp As Map
mp. I ni t i al i ze
mp. Put ( " I D", I D)
DBUt i l s. Updat eRecor d( Mai n. SQL1, Mai n. DBTabl eName, " Fi r st Name" , edt Fi r st Name. Text ,
mp)
DBUt i l s. Updat eRecor d( Mai n. SQL1, Mai n. DBTabl eName, " Last Name", edt Last Name. Text , mp)
DBUt i l s. Updat eRecor d( Mai n. SQL1, Mai n. DBTabl eName, " Addr ess" , edt Addr ess. Text , mp)
DBUt i l s. Updat eRecor d( Mai n. SQL1, Mai n. DBTabl eName, " Ci t y", edt Ci t y. Text , mp)

Fi l l WebVi ew
End I f
End Sub

We :
Ask in a MessageBox if the user really wants to update the record.
If Yes, we Dim a Map to hold the ID of the record
Put the ID of the record into the Map
Update the FirstName field.
Update the LastName field.
Update the Address field.
Update the City field.
Update the WebView table

In the DBUtils.UpdateRecord we have :
Mai n. SQL1 the SQL reference of the database
Mai n. DBTabl eName the table name, a variable in our case
Fi r st Name the column name
edt Fi r st Name. Text the new field value
mp the Map representing theWHERE function of SQL,
in our case WHERE ID =ID



5 DBUtils Example program 65 Basic4Android User's Guide
The btnAddNew_Click routine :

Sub bt nAddNew_Cl i ck
' adds t he new r ecor d
I f Recor dExi st s = Fal se Then
Di mmaps As Li st
Di mmp As Map
maps. I ni t i al i ze
mp. I ni t i al i ze
mp. Put ( "I D", Nul l )
mp. Put ( "Fi r st Name", edt Fi r st Name. Text )
mp. Put ( "Last Name", edt Last Name. Text )
mp. Put ( "Addr ess", edt Addr ess. Text )
mp. Put ( "Ci t y", edt Ci t y. Text )
maps. Add( mp)
DBUt i l s. I nser t Maps( Mai n. SQL1, Mai n. DBTabl eName, maps)

Fi l l WebVi ew
End I f
End Sub

We :
Check if a record with the same data already exists.
If No, we Dim a List of Maps maps and a Map mp.
initialize maps and mp.
put Nul l for the I D column, Null for autoincrement of the primary key.
put edt Fi r st Name. Text in the Fi r st Name column.
Same for Last Name, Addr ess and Ci t y.
add the Map mp to the List maps.
insert the new record in the database.
update the WebView table.

5 DBUtils Example program 66 Basic4Android User's Guide
RecordExists routine :

Sub Recor dExi st s As Bool ean
Di mQuer y As St r i ng
Di mcur s As Cur sor

' checks i f t he r ecor d al r eady exi st s
Quer y = "SELECT * FROM " & Mai n. DBTabl eName & _
" WHERE Fi r st Name=' " & edt Fi r st Name. Text & _
"' AND Last Name=' " & edt Last Name. Text & _
"' AND Addr ess=' " & edt Addr ess. Text & _
"' AND Ci t y=' " & edt Ci t y. Text & "' "
cur s = Mai n. SQL1. ExecQuer y( Quer y)
I f cur s. RowCount > 0 Then
Msgbox( "Thi s r ecor d al r eady exi st s", "A T T E N T I O N")
Ret ur n Tr ue
El se
Ret ur n Fal se
End I f
End Sub

We :
Dim the Query and cursor variables.
Define the Query to check if the values in the four EditTexts already exist.
SELECT * FROM Table WHERE
FirstName ='edtFirstName.Text' if 'edtFirstName.Text' exist in column FirstName.
LastName ='edtLastName.Text' if 'edtLastName.Text' exist in column LastName.
etc.
Execute the query.
If the RowCount is heigher than 0 the record already exists and we Return True.
If the RowCount is equal to 0 the record doen't exist and we Return False.

5 DBUtils Example program 67 Basic4Android User's Guide
The btnDelete_Click routine :

Sub bt nDel et e_Cl i ck
Di mAnsw As I nt

Answ = Msgbox2( "Do you r eal l y want t o del et e t hi s r ecor d ?", "DELETE r ecor d",
"Yes", "", "No", Nul l )

I f Answ = Di al ogResponse. POSI TI VE Then
Di mmp As Map
Di mval ( 5) As St r i ng
mp. I ni t i al i ze
mp. Put ( "I D", I D)
val = l st Tabl e. Get ( r ow)
mp. Put ( "Fi r st Name", val ( 1) )
mp. Put ( "Last Name", val ( 2) )
mp. Put ( "Addr ess", val ( 3) )
mp. Put ( "Ci t y", val ( 4) )
DBUt i l s. Del et eRecor d( Mai n. SQL1, Mai n. DBTabl eName, mp)
Fi l l WebVi ew
edt Fi r st Name. Text = ""
edt Last Name. Text = ""
edt Addr ess. Text = ""
edt Ci t y. Text = ""
r ow = - 1
col = - 1
pnl Tool Box. Vi si bl e = Fal se
End I f
End Sub

We :
Dim the Answ variable
Ask the user if he really wants to delete the record.
If the answer is yes (Di al ogResponse. POSI TI VE) then :
Dim mp as a Map and val ( 5) as String.
Initialize the Map mp .
Put the ID value to the Map.
Set the values of the current row l st Tabl e. Get ( r ow) to val .
The content of the current row is the string array l st Tabl e. Get ( r ow) .
Put the values of the columns to the Map.
Execute the Query DBUt i l s. Del et eRecor d( Mai n. SQL1, Mai n. DBTabl eName, mp) .
Run the Fi l l WebVi ew routine to update the table.
Set the content of the EditText views to empty.
Set row and col to -1 no row nor column selected.
Hide the button toolbox, no function available.




6 GPS 68 Basic4Android User's Guide
6 GPS

The GPS library has three objects:
GPS
GPSSatellite
Location

The example program will show several functions of the GPS library and has following functions.
Connecting the GPS
Getting and displaying GPS information
Saving a GPS path
Display the available satellites
Showing Google maps
Show a GPS path on the map

6.1 GPS Li brary

The GPS LIbrary is part of the basic Basic4Android language.
6.1.1 GPS Obj ect

The GPS object has:
Members
o GPSEnabled as Boolean [read only]
Tests whether the user has enabled the GPS or not
o Initialize (EventName As String)
Initializes the GPS with its EventName
o LoacationSettingsIntent As android.contend.Intent [read only]
Returns the intent that is used to show the global location settings.

o Start(MinimumTime As Long, MinimumDistance As Float)
Starts listening for events.
MinimumTime The shortest period (in milliseconds) between events.
Pass 0 for highest frequency
MinimumDistance The shortest change in distance (in meters) for which to raise
events. Pass 0 for highest frequency.
o Stop
Stops listening to the GPS. You will usually want to call Stop inside Sub
Activity_Pause.
Events
o LocationChanged (Location1 As Location)
Raised when a new 'fix' is ready.
o UserEnabled (Enabled As Boolean)
o GpsStatus (Satellites As List)


6 GPS 69 Basic4Android User's Guide
6.1.2 GPS Satellite

The GPSSatellite object holds various information about a GPS satellite. A List with the available
satellites is passed to the GpsSatus event.

Satellite data:
Azimuth 0 - 360 degrees
Elevation 0 - 90 degrees
Prn (Pseudo random number)
Snr (Signal / noise ratio)
UsedInFix True if the satellite is used to determine the current fix.


6.1.3 GPS Location

A Location object holds various information about a specific GPS fix (position).
In most cases you will work with locations that are passed to the GPS LocationChanged event.
The location object can also be used to calculate distance and bearing to other locations.

The most useful properties.
Location1.Latitude latitude of the fix in []
Location1.Longitude longitude of the fix in []
Location1.Altitude altitude of the fix in [m]
Location1.Bearing bearing of the fix in []
Location1.Speed speed of the fix in [m/s]
Location1.Time time of the fix in in [ticks]

The most useful methods.
Location1.Initialize
Initializes an empty location.

Location1.Initialize2 (Latitude As String, Longitude As String)
Initializes a location with the two given values, all the other properties are 0.

Location1.DistanceTo (TargetLocation As Location) in [m]
Locat i on1. Di st anceTo( Locat i on2)
calculates the distance between Location1 and Location2.

Location1.BearingTo (TargetLocation As Location) in []
Locat i on1. Bear i ngTo( Locat i on2)
calculates the bearing from Location1 to Location2.




6 GPS 70 Basic4Android User's Guide
6.2 GPS Program

The GPS example program shows several possibilities of the GPS library and has the following
functions :
Connect the GPS
Get and display GPS information
Save a GPS path
Display the available satellites
Display Google maps
Display a GPS path on the map

Google map functions, user settable :
Display zoom control
Display scale control
Display map type control
Display a path
Display markers
Move a marker
Display coordinates (touch the screen)
Move the map / Display coordinates (touch the screen and move)

It is designed for smartphones and works only in portrait mode.
It is only available for users who bought Basic4Android, the program takes advantage of libraries
which are not part of the trial version.
The source code of this program is available in the users forum in the GPSExample project.
It is not in the SourceCode directory of this guide to guarantee the latest version of the program.

Main screen Google Maps


6 GPS 71 Basic4Android User's Guide
GPS display GPS display plus map




Setup Satellites



6 GPS 72 Basic4Android User's Guide
GPS path data Map with GPS path


6 GPS 73 Basic4Android User's Guide

6.2.1 General explanations

Main screen buttons:




Displays Google maps centered on the default coordinates (defined in the setup).
If there is a GPS path, this one is displayed, centered and zoomed to show the whole path.


Displays the setup screen.


Activates the GPS and memorizes the fixes depending on the setup.


Shows the available satellites.


Displays the data of a GPS path.


For certain functions, the button color is red when they are activated .



Tooltips for the buttons.


When you touch a button the tooltip is displayed on top
of the screen.

When you release it, the tooltip is hidden.

The function is executed when you release the button
inside the buttons area.

If you release the button outsides its area the function is
not executed, this allows the user to look at the buttons
function without executing it.







6 GPS 74 Basic4Android User's Guide
6.2.2 Setup

The setup screen allows to define setup parameters for the program.

GPS
- min time between two fixes.
- min distance between two fixes.
Enable display of:
- Speed
- Bearing
- Windrose


GPS path units, for the display of the values.
- unit for Altitude m and ft
- unit for Speed m/s, km/h and mile/h
- unit for Distance m, km and mile


Map Default location
- Latitude
- Longitude
- Zoom level
- Draggable Checked means: the map can be moved
Unchecked means: show the coordinates.
GPS
- Show the current GPS location on the map.
- Save the GPS path when the GPS is stopped.
- Draw the
GPS path online (not yet implemented)

Map show different controls, marker/line properties
- Display center marker
- Display GPS path markers
- Display the GPS path polyline

- Scale control

- Type control, map ROADMAP or SATELLITE

- Zoom control DEFAULT, SMALL, LARGE

GPS Polyline properties
- Width in pixels
- Color
- Opacity 0 =transparent

GPS Marker
properties
5 GPS 75 Basic4Android User's Guide
- Marker clickable (not yet implemented)
- Marker draggable
6 GPS 76 Basic4Android User's Guide
6.2.3 GPS display

GPS display.

When activated, the GPS displays following parameters:
Latitude
Longitude
Altitude
Speed user selectable in the setup
Bearing user selectable in the setup
Windrose user selectable in the setup

The minimum time and minimum distance to raise a fix change can be set in the setup screen.
Values of 0 for both parameters give the fastest acquisition frequency.
The number of memorized fixes is displayed in the titlebar.



The map can be displayed at the same time with the current GPS location.

After stopping the GPS the user is asked to save the path giving a file name and a comment.


6 GPS 77 Basic4Android User's Guide
6.2.4 Satellites



The Satellites screen displays the information about the satellites currently received by the GPS.

The displayed data are:
Azimuth
Elevation
Used
Signal/Noise ratio




6 GPS 78 Basic4Android User's Guide
6.2.5 Map display

The Google map can be displayed on the main screen.



with markers without markers

The following elements can either be displayed or hidden, set in the Setup screen :
Type control MAP or SATELLITE
Scale control
Zoom control
GPS path (polyline)
Markers

6 GPS 79 Basic4Android User's Guide

The map can be zoomed with a 'double click'.
Or with the zoom button.

If the map is 'Draggable' then :
touching and moving (dragging) moves the
map.

If the map is NOT 'Draggable' then
touching the screen shows the coordinates of
that position.
touching and moving (dragging) shows the
coordinates








Changing settings directly when the map is displayed:

Touching the MAP button shows a second button on
top of it.
Moving up into the area of the second button, this one
becomes red, and releasing it changes the map mode
from draggable to coordinates and vice and versa.



Touching the PATH button shows three more
buttons on top of it.
Moving on one of these buttons allows to choose
either:
Polyline of the path with the
markers.
Polyline of the path without the
markers.
No polyline and no markers.








6 GPS 80 Basic4Android User's Guide
6.2.6 GPS path

The data from the GPS can be memorized and saved in files.

General data for the file:
The filename
The number of points in the file
A comment for the path

The variables of a GPS fix are:
Latitude the latitude of the fix []
Longitude the longitude of the fix []
Altitude the altitude of the fix [m]
Time the time when the fix was taken [tick]
Bearing the bearing from the previous fix []
Speed the speed between the two fixes [m/s]
Distance the distance between the two fixes [m]
Dist tot the total distance from the first fix [m]
Marker flag if a marker should be shown [-]

The GPS path screen shows the data of the selected GPS path.



The data can be scrolled vertically, normal ScrollView scrolling, and horizontally with the slider.
The left column with the ID remains always visible.

6 GPS 81 Basic4Android User's Guide
You can:


Delete the selected file.


Load a GPS path file.


Save the GPS path file.


Delete the selected row.


Filter a path









Clicking on a row selects it or unselects it.

When a row is selected :
it is highlighted in red.
a Delete button is displayed allowing to delete this fix.
When a fix is deleted the Speed, Bearing, Distance and Dist Tot values are updated.


Clicking on one of the headers below changes the unit of the displayed values.

Altitude Speed Distance / Dist tot
m ft m/s km/h mile/h m km mile

check / uncheck
Clicking on a marker cell changes between checked and unchecked. Marker
6 GPS 82 Basic4Android User's Guide
GPS path filtering.

When memorizing GPS paths it often happens that there are some point aligned along a straight
line. These points can be removed.
The principle of the program is the following.
The program looks at 3 successive points.
Calculates the distance of the midpoint out of the line between the the two outer points.
If this distance is higher than the predefined value the point is selected and can be deleted.










With the file added by default Test2.GPP you can test it
yourself.





In this example, Test2.GPP, the number of original
points is 78.
The number of points to filter (delete), with a
distance of 5 m, is 46.









before filtering after filtering

6 GPS 83 Basic4Android User's Guide
6.2.7 Save GPS path fil e / KML file

A GPS path can be save either :

in the program specific GPP format (GPS Path)
in the Google Earth KML format.







Enter the filename.
The program adds automatically the correct suffix.


Enter a comment.


Reminder of the number of points.


The drawback of the kml format is that you loose the
time and speed information for each fix.
The advantage is, you can display the path in Google
Earth.






KML documentation.
6 GPS 84 Basic4Android User's Guide
6.3 GPS Program Code

Not all the code of the program will be explained in this chapter but only some more special
features. Many functions are almost the same as explained in other examples.

The line numbers in the code snippets in this chapter can be somewhat different from the
latest project.

The program has following modules:
Main activity module
main screen, GPS screen and GoogleMaps screen.

Satellites activity module
display of the satellites data.

Setup activity module
setup screen using a ScrollView with a panel higher than the screen.

GPSPaths activity module
displays the GPS path data plus loading, saving and editing.

GPSSave activity module
screen for saving a GPS path file with file name and comment entry.

GPSModule code module
GPS code used in several activity modules

6 GPS 85 Basic4Android User's Guide
6.3.1 Initialization of the GPS

Android doesn't allow a program to start the GPS automatically for security reasons, only the user
can enable it.

If the GPS is disabled, the program must ask the user to enable it, this is done with the following
code (in the bt nGPS_Touch routine in the Main module) :

I f GPS1. GPSEnabl ed = Fal se Then
Toast MessageShow( " Pl ease enabl e t he GPS devi ce. " & CRLF & " And pr ess t he BACK
but t on", Tr ue)
St ar t Act i vi t y( GPS1. Locat i onSet t i ngsI nt ent )
End I f

Here we check if the GPS is enabled.
If no, we show a ToastMessage asking the user to enable it and activate the LocationSettings screen
where the user must check the GPS.



Then we can start the GPS with:

GPS1. St ar t ( GPSMi nTi me, GPSMi nDi st ance)

Where:
GPSMi nTi me = the minimum time before the next fix.
GPSMi nDi st ance = the minimum distance before the next fix.

To have the quickest sampling of the GPS enter zeros for both parameters : GPS1. St ar t ( 0, 0)



6 GPS 86 Basic4Android User's Guide
6.3.2 Button with tooltip

The buttons of the program show a tooltip on top of the screen when they are touched.
The views used for this are not Buttons but Panels, because Button don't have the Touch event and
Panels have it.

btnGPS button (panel), in the Main module:
This button acts as a toggle button, GPS ON or OFF with a color change.

Sub bt nGPS_Touch( Act i on As I nt , x As Fl oat , y As Fl oat )
Di mbmd As Bi t mapDr awabl e

Sel ect Act i on
Case Act i vi t y. ACTI ON_DOWN
I f GPS_On = Fal se Then
Tool Ti p( "Act i vat es t he GPS")
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngps1. png") )
El se
Tool Ti p( "St ops t he GPS")
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngps0. png") )
End I f
bt nGPS. Backgr ound = bmd

- First we dim a BitmapDrawable object that will contain the bitmap to display in the button.
- Select ACTION_DOWN,
- Check if GPS is OFF (GPS_On =False) or ON (GPS_On =True)
- Load the corresponding bitmap and set it to the buttons background.

Case Act i vi t y. ACTI ON_UP
I f x > 0 AND x < bt nGPS. Wi dt h AND y > 0 AND y < bt nGPS. Hei ght Then
GPS_On = Not ( GPS_On)
I f GPS_On = Fal se Then
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngps0. png") )
GPS1. St op
PhoneAwake. Rel easeKeepAl i ve
I f GPSPat h. Si ze > 0 Then
cvsMap. Dr awRect ( r ect MapPos, Col or s. Tr anspar ent , Tr ue, 1)
pnl Map. I nval i dat e2( r ect MapPos)

I f SaveGPSPat h = Tr ue Then
St ar t Act i vi t y( GPSSave)
End I f
El se
Msgbox( "Ther e ar e no waypoi nt s", "GPS pat h savi ng")
GPSModul e. LoadPat h
MapZoomLevel = MapZoomLevel Ol d
MapCent er = MapOl dCent er
MapShow
End I f


- Select ACTION_UP
- Check if the touch coordinates are within the button area. If yes we execute the function.
- Change the GPS_On variable
- Check if GPS_On =False (GPS disabled) we
- Load the corresponding bitmap (blue image)
- Stop the GPS
- Release the phone keep alive function
5 GPS 87 Basic4Android User's Guide
- Check if there are GPS path data GPSPath.Size >0
- Check if saving GPS pata data is selected
- Start the GPS path data saving Activity
- If not
- Display a MessageBox
- Load the previous GPS path
- Show the GoogleMap

El se
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngps1. png" ) )
I f GPS1. GPSEnabl ed = Fal se Then
Toast MessageShow( " Pl ease enabl e t he GPS devi ce. " & CRLF & " And pr ess t he
BACK but t on" , Tr ue)
St ar t Act i vi t y( GPS1. Locat i onSet t i ngsI nt ent )
End I f
GPSPat h. I ni t i al i ze
I f Map_On Then
MapZoomLevel Ol d = MapZoomLevel
MapOl dCent er = MapCent er
MapZoomLevel = MapDef aul t ZoomLevel
MapCent er . Lat i t ude = MapDef aul t Lat
MapCent er . Longi t ude = MapDef aul t Lng
MapShow
End I f
PhoneAwake. KeepAl i ve( Fal se)
l bl Lat i t ude. Text = " - - - "
l bl Longi t ude. Text = "- - - "
l bl Al t i t ude. Text = " - - - "
l bl Bear i ng. Text = "- - - "
l bl Speed. Text = "- - - "

GPS1. St ar t ( GPSMi nTi me, GPSMi nDi st ance)
End I f

- If GPS_On =True (GPS enabled) we
- Load the corresponding bitmap (red image)
- Check if the GPS is not enabled on the phone
- Display a ToastMessage inviting the user to enable the GPS
- Call the phone setup to let the user enable the GPS
- Initialize the GPSPath data list
- Check if the Map_On =True, map displayed
- Set the Zoom level, centre lat and long to the default values
- Update the map the new parameters
- Set the PhoneAwake function, the False parameter indicates no bright screen
- set the different display labels to "- - -", no value
- Start the GPS, GPSMinTime and GPSMinDistance are defined in the setup screen.
6 GPS 88 Basic4Android User's Guide
pnl Di spGPSLat Lng. Vi si bl e = GPS_On
pnl Di spGPSAl t i t ude. Vi si bl e = GPS_On
pnl Di spGPSSpeed. Vi si bl e = GPS_On AND GPSDi spSpeed
pnl Di spGPSBear i ng. Vi si bl e = GPS_On AND GPSDi spBear i ng
pnl Di spGPSWi ndr ose. Vi si bl e = GPS_On AND GPSDi spWi ndr ose
pnl Mai nBackgound. Vi si bl e = Not ( pnl Di spGPSWi ndr ose. Vi si bl e)
bt nGPS. Backgr ound = bmd
End I f
Tool Ti p( "")
End Sel ect
End Sub

- Then show the different display labels according to setup settings.
- Set the background image
- Hide the tooltip.


6 GPS 89 Basic4Android User's Guide
6.3.3 Button with tooltip and additional buttons

btnGPSPath button (panel), in the Main module:

This button starts the GPSPaths activity,
or if the map is displayed shows three more buttons that
allow to change the following map setup parameters:
Display the markers and the polyline of the GPS
path on the map
Display only the polyline, no markers, of the
GPS path on the map
Display only the map
The three upper buttons are on a Panel,
pnlGPSPathToolbox.


Sub bt nGPSPat h_Touch( Act i on As I nt , x As Fl oat , y As Fl oat )
Di mbmd, bmd1, bmd2, bmd3 As Bi t mapDr awabl e

Sel ect Act i on
Case Act i vi t y. ACTI ON_DOWN
Tool Ti p( "Shows t he GPS pat h poi nt s")
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngpspat h1. png") )
bt nGPSPat h. Backgr ound = bmd
I f Map_On = Tr ue Then
pnl GPSPat hTool box. Vi si bl e = Tr ue
End I f

- First we dim four BitmapDrawable objects for the background images.
- Select Activity ACTION_DOWN
- Show the tooltip
- Load the red image bitmap
- Set the button background image
- Check if the map is displayed
- If yes, we show the pnlGPSPathToolbox panel with the three supplementary buttons.





6 GPS 90 Basic4Android User's Guide
Case Act i vi t y. ACTI ON_MOVE
I f x > 0 AND x < bt nGPSPat h. Wi dt h AND y > - 3 * bt nGPSPat h. Hei ght AND y < - 2 *
bt nGPSPat h. Hei ght Then
bmd3. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hmar ker 1. png") )
bmd2. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hl i ne0. png") )
bmd1. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat h0. png") )
Tool Ti p( "Shows t he pol yl i ne and t he mar ker s")
El se I f x > 0 AND x < bt nGPSPat h. Wi dt h AND y > - 2 * bt nGPSPat h. Hei ght AND y < -
bt nGPSPat h. Hei ght Then
bmd3. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hmar ker 0. png") )
bmd2. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hl i ne1. png") )
bmd1. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat h0. png") )
Tool Ti p( "Shows t he pol yl i ne wi t hout t he mar ker s")
El se I f x > 0 AND x < bt nGPSPat h. Wi dt h AND y > - bt nGPSPat h. Hei ght AND y < 0 Then
bmd3. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hmar ker 0. png") )
bmd2. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hl i ne0. png") )
bmd1. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat h1. png") )
Tool Ti p( "Doesn' t shows t he pol yl i ne nor t he mar ker s")
El se
bmd3. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hmar ker 0. png") )
bmd2. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat hl i ne0. png") )
bmd1. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, " bt ngpspat h0. png") )
Tool Ti p( "Shows t he GPS pat h poi nt s")
End I f
bt nGPSPat h3. Backgr ound = bmd3
bt nGPSPat h2. Backgr ound = bmd2
bt nGPSPat h1. Backgr ound = bmd1

In this part we check if the move coordinates are in the area of a button and change the button
images, red in in the area and blue outsides.

- Select Activity ACTION_MOVE
- Check if the move coordinates are in the area of the top most button, if yes
- Load the corresponding images for the four buttons.
- Check if the move coordinates are in the area of the second button from top, if yes
- Load the corresponding images for the four buttons.
- Check if the move coordinates are in the area of the third button from top, if yes
- Load the corresponding images for the four buttons.
- Check if the move coordinates are in the area of the lower button, if yes
- Load the corresponding images for the four buttons.
- Set the images for the three top buttons



6 GPS 91 Basic4Android User's Guide
Case Act i vi t y. ACTI ON_UP
I f x > 0 AND x < bt nGPSPat h. Wi dt h Then
I f y > - 3 * bt nGPSPat h. Hei ght AND y < - 2 * bt nGPSPat h. Hei ght Then
Di spMapMar ker s = Tr ue
Di spMapPol yl ne = Tr ue
MapShow
El se I f y > - 2 * bt nGPSPat h. Hei ght AND y < - bt nGPSPat h. Hei ght Then
Di spMapMar ker s = Fal se
Di spMapPol yl ne = Tr ue
MapShow
El se I f y > - bt nGPSPat h. Hei ght AND y < 0 Then
Di spMapMar ker s = Fal se
Di spMapPol yl ne = Fal se
MapShow
El se I f y > 0 AND y < bt nGPSPat h. Hei ght Then
St ar t Act i vi t y( "GPSPat hs")
End I f
End I f
I f Di spMapMar ker s = Tr ue Then
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngpspat hmar ker 0. png") )
El se I f Di spMapPol yl ne = Tr ue Then
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngpspat hl i ne0. png") )
El se
bmd. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt ngpspat h0. png") )
End I f

Tool Ti p( "")
pnl GPSPat hTool box. Vi si bl e = Fal se
bt nGPSPat h. Backgr ound = bmd
End Sel ect
End Sub

In this part we check in what button area the UP coordinates are in and execute, or not, the
corresponding functions.

- Select Activity ACTION_UP
- Check if the move coordinates are in the area of the top most button, if yes
- Set the setup variables the given values, DispMapMarkers =True DispMapPolyline =True.
- Update the map.
- Check if the move coordinates are in the area of the second button from top, if yes
- Set DispMapMarkers =False DispMapPolyline =True.
- Update the map.
- Check if the move coordinates are in the area of the third button from top, if yes
- Set DispMapMarkers =False DispMapPolyline =False.
- Update the map.
- Check if the move coordinates are in the area of the lower button, if yes
- Start the GPSPaths activity.
- Depending on the setup variables we load the correct bitmap for the btnGPSPath button.
- Hide the tooltip.
- Hide the toolbox of the three upper buttons.
- Set the correct bitmap to btnGPSPath.


6 GPS 92 Basic4Android User's Guide
6.3.4 GPS Calculate di stance scal es

The two routines below calculate the latitude X and longitude Y coordinates, in km,
from coordinate 0, 0 (equator and Greenwich meridian) to the given lat and lng coordinates.
lat and lng are in degrees, we need to transform them to radians
with l ng / 180 * cPI and l at / 180 * cPI .
for Y (lat) we multiply the angle (in radians) by the earth radius (6371 km)
for X (lng) we multiply the angle (in radians) by the earth radius (6371 km)
and multiply by CosD( l at ) .

The EarthRadius variable is defined in the Process_Globals routine in the GPSPaths module.
The EarthRadius value used, 6371 km, is a mean value. In reality, the EarthRadius varies with the
latitude but for our calculations the assumption of a mean radius is enough accurate.

Sub GPSCal cX( l at As Doubl e) As Doubl e
' cal cul at es t he l ongi t ude di st ance i n kmf r omcoor di nat es 0, 0
Ret ur n l at * Ear t hRadi us / 180 * cPI
End Sub

It's 'simply' the Ear t hr adi us multiplied by the angle l at , but the angle is in degrees so we need
to transform it into radians.

Sub GPSCal cY( l at As Doubl e, l ng As Doubl e) As Doubl e
' cal cul at es t he l at i t ude di st ance i n kmf r omcoor di nat es 0, 0
Ret ur n l ng * Ear t hRadi us / 180 * cPI * CosD( l at )
End Sub

The calculation for the l ng coordinate is similar to the l at calculation.
But, the radius of a circle of latitude depends on the latitude,
so we need to multiply the result by the cosine of lat CosD( l at ) .
We use CosD because the angle is in degrees.

6 GPS 93 Basic4Android User's Guide
6.3.5 Drawing GPS position

The current GPS position is drawn on the map when:

the GPS is active,


a map is displayed.



'Show GPS on map' is selected in the setup.

The GoogleMap is drawn on the WebView MapVi ewer .

The position is drawn on the transparent panel pnl Map which is on top of the Activity and the
MapVi ewer WebView. The code below is in:

Sub GPS1_Locat i onChanged ( Locat i on1 As Locat i on)
.
.
I f ShowGPSOnMap = Tr ue Then
Di mxc, yc As Fl oat
xc = ( Locat i on1. Longi t ude - MapCent er . Longi t ude) / MapScal eLng + MapVi ewer . Wi dt h / 2
yc = ( MapCent er . Lat i t ude - Locat i on1. Lat i t ude) / MapScal eLat + MapVi ewer . Hei ght / 2
I f xc < 10%x OR xc > 90%x OR yc < 20%y OR yc > 80%y Then
MapCent er . Lat i t ude = Locat i on1. Lat i t ude
MapCent er . Longi t ude = Locat i on1. Longi t ude
MapShow
End I f
Dr awGPSPosi t i on( xc, yc)
End I f
End Sub

Where:
Locat i on1. Longi t ude, Locat i on1. Lat i t ude
are the current location coordinates in degrees.
MapCent er . Longi t ude, MapCent er . Lat i t ude
are the current map center coordinates in degrees
MapScal eLng, MapScal eLat are the scales, degrees/pixel, of the current map.
xc, yc are the coordinates of the current location in pixels.

Locat i on1. Longi t ude and Locat i on1. Lat i t ude, the coordinates of the current position, are
given by the GPS.
In the equation.
xc = ( Locat i on1. Longi t ude - MapCent er . Longi t ude) / MapScal eLng + MapVi ewer . Wi dt h / 2

( Locat i on1. Longi t ude - MapCent er . Longi t ude)
Is the x distance, in degrees, from the map center to the current location.

( Locat i on1. Longi t ude - MapCent er . Longi t ude) / MapScal eLng
Is the x distance, in pixels, from the the map center to the current location.

( Locat i on1. Longi t ude - MapCent er . Longi t ude) / MapScal eLng + MapVi ewer . Wi dt h / 2
Is the x distance, in pixels, from the left border to the current location.

The equation for yc is similar.
6 GPS 94 Basic4Android User's Guide
I f xc < 10%x OR xc > 90%x OR yc < 20%y OR yc > 80%y Then
MapCent er . Lat i t ude = Locat i on1. Lat i t ude
MapCent er . Longi t ude = Locat i on1. Longi t ude
MapShow
End I f

Here we check if the current location reaches one of the maps borders, and if true, we set the map
centre coordinates to the current location coordinates and redraw the map.

Dr awGPSPosi t i on( xc, yc) Draws the location on the map.

Complementary calculation routines:

CalcMapScales: calculates the map pixel scales

Sub Cal cMapScal es
' Cal cul at es t he map scal es
MapScal eLng = 360 / Power ( 2, MapZoomLevel ) / Ti l eSi ze
MapScal eLat = MapScal eLng * CosD( MapCent er . Lat i t ude)
End Sub

Where:
MapScal eLng = Longitude scale in degrees/pixel
MapZoomLevel = Current map zoom level
Ti l eSi ze = Map tile size in pixels
MapScal eLat = Latitude scale in degrees/pixel
MapCent er . Lat i t ude = Centre lat coordinate of the current map in degrees.

360 is the earth circumference in degrees.
Power ( 2, MapZoomLevel ) is the number of tiles for the given zoom level.
The default map tile size is 256 pixels defined in the Main module.

Di mTi l eSi ze As I nt : Ti l eSi ze = 256

But this tile size must be changed according to the device's density, because on different devices
with almost the same physical dimensions, but different densities, the size of the map is the same.
That means that the tile size is proportional to the device density.

Di ml v As Layout Val ues
l v = Get Devi ceLayout Val ues
Ti l eSi ze = Ti l eSi ze * l v. Scal e



6 GPS 95 Basic4Android User's Guide
Drawing of the GPS position on the map :



Sub Dr awGPSPosi t i on( xc As Fl oat , yc As Fl oat )
Di mx1, y1, x2, y2 As Fl oat
Di mdd1, dd2, r As Fl oat

cvsMap. Dr awRect ( r ect MapPos, Col or s. Tr anspar ent , Tr ue, 1)
pnl Map. I nval i dat e2( r ect MapPos)

dd1 = 20di p
dd2 = 20di p
r = 10di p
x1 = xc - dd1
y1 = yc - dd1
x2 = xc + dd2
y2 = yc + dd2
r ect MapPos. I ni t i al i ze( x1, y1, x2 + 1, y2 + 1)

cvsMap. Dr awLi ne( x1, yc, x2, yc, Col or s. Red, 1di p)
cvsMap. Dr awLi ne( xc, y1, xc, y2, Col or s. Red, 1di p)
cvsMap. Dr awCi r cl e( xc, yc, r , Col or s. Red, Fal se, 3di p)
pnl Map. I nval i dat e2( r ect MapPos)
End Sub

We
define local variables
draw a transparent rectangle to erase the previous position
update the drawing
set the variables for the drawing
define the new surrounding rectangle
draw a horizontal line
draw a vertical line
draw a circle
update the drawing



If there are code sections you would like to be developed here, please post the questions and
suggestions in the GPSExample thread on the users forum.

7 Widgets 96 Basic4Android User's Guide
7 Widgets, home screen widgets

This chapter is a copy of Erels' two tutorials in the users forum.
Android home screen widgets tutorial - part I
Android home screen widgets tutorial - part II

7.1 Widgets Part I

Basic4android v1.6 adds support for home screen widgets. This tutorial will explain how to
implement your own home screen widgets (also named App Widgets).

It is important to understand that the widgets are created and managed in another process, different
than the process that your application is running in. The home screen application is hosting your
widgets.
This means that it is not possible to directly access the widgets views. Instead we are using a special
object named RemoteViews which gives us indirect access to the widget views.

Widgets do not support all views types. The following views are supported:
Button (default drawable)
Label (ColorDrawable or GradientDrawable)
Panel (ColorDrawable or GradientDrawable)
ImageView
ProgressBar (both modes)

All views support the Click event and no other event.

The widget layout and configuration must be defined with XML files. During compilation
Basic4android reads the layout file created with the designer and generates the required XML files.

Each widget is tied to a Service module. The widget is created and updated through this module.

Creating a widget - step by step guide

Add a Service module. Note that the service module handling the widget is a standard
service.
Design the widget layout with the designer. First add a Panel and then add the other views to
this Panel.
The widget layout will be made from this panel.
Add code similar to the following code the service module:

7 Widgets 97 Basic4Android User's Guide
Sub Pr ocess_Gl obal s
Di mr v As Remot eVi ews
End Sub

Sub Ser vi ce_Cr eat e
r v = Conf i gur eHomeWi dget ( "Layout Fi l e", "r v", 0, "Wi dget Name")
End Sub

Sub Ser vi ce_St ar t ( St ar t i ngI nt ent As I nt ent )
I f r v. Handl eWi dget Event s( St ar t i ngI nt ent ) Then Ret ur n
End Sub

Sub r v_Request Updat e
r v. Updat eWi dget
End Sub

Sub r v_Di sabl ed
St opSer vi ce( "")
End Sub

Sub Ser vi ce_Dest r oy

End Sub

Compile and run your application. Go to the home screen, long press on the screen and you
will see your widget listed on the widgets list.

ConfigureHomeWidget is a special keyword. At runtime it creates the RemoteViews object from
the layout and sets the events. At compile time the compiler generates the required files based on
the arguments of this keyword.
The four parameters are: layout file, event name, update interval and the widget name.
Event name sets the subs that will handle the RequestUpdate and Disabled events.
The widget can be configured to update itself automatically. The interval, measured in minutes,
defines how often will the widget request to update itself. Set to 0 to disable automatic updates.
Updating the widget too often will have a bad impact on the battery. The minimum value is 30
minutes.
Widget name - the name that will appear in the widgets list.

As these arguments are read by the compiler, only strings or numbers are accepted.

Events:

Sub Ser vi ce_St ar t ( St ar t i ngI nt ent As I nt ent )
I f r v. Handl eWi dget Event s( St ar t i ngI nt ent ) Then Ret ur n
End Sub

The above code checks the Intent message that caused this service to start and is responsible for
raising the events related to the widget. It returns true if an event was raised.
The widget raises two events. RequestUpdate is raised when the widget needs to update itself. It
will fire after adding the widget to the screen, after the device has booted, based on the scheduled
updating interval (if set) or after the application was updated.
The Disabled event is raised when the last instance of our widget is removed from the screen.

7 Widgets 98 Basic4Android User's Guide
As mentioned above all views support the Click event. All that needs to be done in order to handle
the click event of a button named Button1 is to add a sub named Button1_Click (the sub name
should actually match the EventName property which is by default the same as the name).
For example if you want to show the main Activity when the user presses on Button1 you can use
this code:

Sub But t on1_Cl i ck
St ar t Act i vi t y( Mai n)
End Sub

Modifying the widget:
It is not possible to directly access the widget views. Instead we need to use one of the
RemoteView.Set methods.
If we want to change the text of a label named Label1 then we need to write the following code:

r v. Set Text ( "Label 1", "Thi s i s t he new t ext . ")
' do mor e changes i f needed
r v. Updat eWi dget

After writing all the changes we call rv.UpdateWidget to send the updates to the widget.

A simple example is available in the forum : HomeWidgets.

The example adds a simple widget. The widget doesn't do anything useful.




7 Widgets 99 Basic4Android User's Guide
7.2 Widgets Part II

In this part we will build a "quote of the day" widget.



We will start with the layout. The widget is made of a Label for the text and an ImageView for the
arrow button.

The layout in the designer:


You can see in the above picture that we use two panels. The base panel named pnlBase is a
transparent panel (Alpha=0). The base panel contains another panel which is the grey panel.
The purpose of the transparent panel is to add some padding to the other views. The widget size is
determined by the base panel. Without the transparent panel there will be no margin between the
visible widget and the screen left edge.
7 Widgets 100 Basic4Android User's Guide
We are setting the base panel size to 294x72. This is the recommended size for a 4x1 cells widget.
Tip: in some cases when you change the layout and there is already an existing widget in the device,
the widget doesn't get updated. Remove the widget and add it again to see the change.

Now for the program logic.
Once a day the program fetches 20 quotes from 5 feeds available from Famous Quotes at
BrainyQuote
Then the first quote is displayed. Each time the user presses on the arrow button the next quote is
displayed.
While getting the quotes the first quote of each feed is added to the beginning of the quotes list.
Only the first quote on each feed is new, and we want to start with the new quotes.
Downloading the feeds is done with HttpUtils and parsing them is done with XmlSax library. See
the code for more information.

The widget is configured to be updated automatically every 24 hours. This is done in this line:

' conf i gur e t he wi dget and set i t t o updat e ever y 24 hour s ( 1440 mi nut es) .
r v = Conf i gur eHomeWi dget ( "Wi dget Layout ", "r v", 1440, "Quot e of t he day")

After 24 hours or when the widget is first added or after a boot the RequestUpdate event is raised.

Sub r v_Request Updat e
quot es. Cl ear
cur r ent Quot e = - 1
Ht t pUt i l s. Downl oadLi st ( "Quot es", Ar r ay As
St r i ng( "ht t p: / / f eeds. f eedbur ner . com/ br ai nyquot e/ QUOTEBR", _
"ht t p: / / f eeds. f eedbur ner . com/ br ai nyquot e/ QUOTEAR",
"ht t p: / / f eeds. f eedbur ner . com/ br ai nyquot e/ QUOTEFU", _
"ht t p: / / f eeds. f eedbur ner . com/ br ai nyquot e/ QUOTELO",
"ht t p: / / f eeds. f eedbur ner . com/ br ai nyquot e/ QUOTENA") )
End Sub

First we clear the current quotes and then we fetch the new ones. Note that if the device was
sleeping at this time then the calls are likely to fail as most devices turn off the wifi while sleeping.
In this case new quotes will arrive when the user presses on the arrow button.
In cases like this you should not count on the automatic update to succeed and make sure that there
is an alternative way to update the widget.

Persisting the data. The process running our widget code will not stay alive forever. It will be
killed by the OS at some point.
Therefore we cannot rely on global variables to store our data.
All of the "state" variables must be written to a file.
RandomAccessFile.WriteObject and ReadObject are very useful for such tasks.
Each time that the widget sends a request to our application, Service Start is called.
Not much is done in this sub:

Sub Ser vi ce_St ar t ( St ar t i ngI nt ent As I nt ent )
I f r v. Handl eWi dget Event s( St ar t i ngI nt ent ) Then Ret ur n
End Sub




7 Widgets 101 Basic4Android User's Guide
However if our process is not alive yet then Service_Create will be called before. Service_Create is
an important point, as it allows us to read the previously saved state to memory:

Sub Ser vi ce_Cr eat e
' conf i gur e t he wi dget and set i t t o updat e ever y 24 hour s ( 1440 mi nut es) .
r v = Conf i gur eHomeWi dget ( "Wi dget Layout ", "r v", 1440, "Quot e of t he day")
Ht t pUt i l s. Cal l backAct i vi t y = "Wi dget Ser vi ce"
Ht t pUt i l s. Cal l backUr l DoneSub = "Ur l Done"
Ht t pUt i l s. Cal l backJ obDoneSub = "J obDone"
par ser . I ni t i al i ze

' Load pr evi ous dat a i f such i s avai l abl e.
' Thi s i s r el evant i n case our pr ocess was ki l l ed and now t he user pr essed on
t he wi dget .
I f Fi l e. Exi st s( Fi l e. Di r I nt er nal Cache, QUOTES_FI LE) Then
r af . I ni t i al i ze( Fi l e. Di r I nt er nal Cache, QUOTES_FI LE, Tr ue)
quot es = r af . ReadObj ect ( 0)
r af . Cl ose
El se
quot es. I ni t i al i ze
End I f
I f Fi l e. Exi st s( Fi l e. Di r I nt er nal Cache, CURRENTQUOTE_FI LE) Then
cur r ent Quot e = Fi l e. ReadSt r i ng( Fi l e. Di r I nt er nal Cache, CURRENTQUOTE_FI LE)
End I f
End Sub

The source code is available in the forum : Quotes.





7 Http / HttpUtils2 102 Basic4Android User's Guide
8 Http / HttpUtils2

HttpUtils2 is a standard library (since Basic4Android version 2.70) that helps with communicating
with web services (Http servers), before it was a HttpUtils2 Class.
8.1 HttpUti ls2 Objects

The HttpUtils2 contains one object : HttpJob.

How to define a job.
Example :
Di mJ ob1 As Ht t pJ ob
J ob1. I ni t i al i ze( "J ob1", Me)
J ob1. Downl oad( b4a)
8.2 HttpUti ls2 Functions

HttpUtils2 has following functions :
Complete( i d As SI nt )
Called by the service when job completes.

Download( Li nk As St r i ng)
Submits a HTTP GET request.
Consider using Download2 if the parameters should be escaped.

Download2( J obName As St r i ng, URLs As Li st )
Submits a HTTP GET request.
Encodes illegal parameter characters.
Example:
j ob. Downl oad2( "ht t p: / / www. exampl e. com", Ar r ay As St r i ng( "key1", _
"val ue1", "key2", "val ue2") )

GetBitmap As Bi t map
Returns the response as a bitmap

GetInputStream As I nput St r eam
Returns an InputStream

GetRequest As I nput St r eam
Returns a HttpUriRequest

GetString As St r i ng
Returns the response as a string encoded with UTF8.

GetString2 ( Encodi ng As St r i ng) As St r i ng
Returns the response as a string with the specified encoded.
Initialize ( Name As St r i ng, Tar get Modul e As Obj ect )
Initializes the Job.
Name - The job's name. Note that the name doesn't need to be unique.
Tar get Modul e - The activity or service that will handle the JobDone event.

7 Http / HttpUtils2 103 Basic4Android User's Guide
IsInitialized As Bool ean
Tests whether the object has been initialized.

JobName
Field containing the job name.
Example : I f j ob1. J obName = "J ob1") Then

Password
Field containing a string with the job password.
Example : I f j ob1. Passwor d = "PassWor d") Then

PostBytes( Li nk As St r i ng, Dat a As Byt es( ) )
Sends a POST request with the given string as the post data.

PostFile( Li nk As St r i ng, Di r As St r i ng, Fi l eName As St r i ng)
Sends a POST request with the given file as the post data.
This method doesn't work with assets files.

PostString( Li nk As St r i ng, Text As St r i ng)
Sends a POST request with the given string as the post data.

Release
Should be called to free resources held by this job.

Success
Field containing a Boolean.
Example : I f j ob1. Passwor d = "PassWor d") Then

Tag
Field containing the job Tag.
Example : I f j ob1. Tag = "somet hi ng") Then

UserName
Field containing a string with the job username.
Example : I f j ob1. User Name = "User Name") Then

The calling module must contain a JobDone routine where you handle the results of the different
jobs.
Example :
Sub J obDone( J ob As Ht t pJ ob)
I f J ob. Success = Tr ue Then
Di ms As St r i ng
s = J ob. Get St r i ng
Log( s)
End I f
End Sub

Look at Example2 for more than one job.

7 Http / HttpUtils2 104 Basic4Android User's Guide
8.3 HttpUti ls Example1

A simple example of downloading a page and returning the page as string:

Source code : HttpUtilsExample1.b4a

Sub Gl obal s
Di mb4a As St r i ng
b4a = "ht t p: / / www. basi c4ppc. com"
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Di mJ ob1 As Ht t pJ ob
J ob1. I ni t i al i ze( "J ob1", Me)
J ob1. Downl oad( b4a)
End Sub

Sub J obDone( J ob As Ht t pJ ob)
I f J ob. Success = Tr ue Then
Di ms As St r i ng
s = J ob. Get St r i ng
Log( s)
End I f
End Sub

First we initialize the job.
"J ob1" =job name
Me =current calling module

Then we call Job1.Download. This call submits a job request to HttpUtils.
HttpUtils raises an event Sub J obDone( J ob As Ht t pJ ob) when the job is finished.

We have four ways to access a downloaded resource:
HttpJob.GetString - Returns the resource as string
HttpJob.GetString2(Encoding As String) - Returns the resource as string with a specific
encoding.
HttpJob.GetBitmap - Returns the resource as bitmap
HttpJob.GetInputStream - Returns an InputStream which allows you to manually read the
downloaded resource.
These four methods should only be called in the J obDone routine.
Inside the J obDone event sub you should check J ob. Success = Tr ue to ensure that the job request
was successful.
7 Http / HttpUtils2 105 Basic4Android User's Guide
8.4 HttpUti ls Example2

Source code : HttpUtilsExamples\HttpUtilsExample2.b4a

In this example we first download an image and set it as the activity background. Then we
download another two Urls and print them as string.

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Di mj ob1, j ob2, j ob3 As Ht t pJ ob
j ob1. I ni t i al i ze( "J ob1", Me)

' Send a GET r equest
j ob1. Downl oad2( "ht t p: / / www. basi c4ppc. com/ pr i nt . php", _
Ar r ay As St r i ng( "f i r st key", "f i r st val ue : ) ", "second key", "val ue 2") )

' Send a POST r equest
j ob2. I ni t i al i ze( "J ob2", Me)
j ob2. Post St r i ng( "ht t p: / / www. basi c4ppc. com/ pr i nt . php", "f i r st key=f i r st
val ue&key2=val ue2")

' Send a GET r equest
j ob3. I ni t i al i ze( "J ob3", Me)
j ob3. Downl oad( "ht t p: / / www. basi c4ppc. com/ f or um/ i mages/ cat egor i es/ andr oi d. png")
End Sub

Sub J obDone ( J ob As Ht t pJ ob)
Log( "J obName = " & J ob. J obName & ", Success = " & J ob. Success)
I f J ob. Success = Tr ue Then
Sel ect J ob. J obName
Case "J ob1", "J ob2"
' pr i nt t he r esul t t o t he l ogs
Log( J ob. Get St r i ng)
Case "J ob3"
' show t he downl oaded i mage
Act i vi t y. Set Backgr oundI mage( J ob. Get Bi t map)
End Sel ect
El se
Log( "Er r or : " & J ob. Er r or Message)
Toast MessageShow( "Er r or : " & J ob. Er r or Message, Tr ue)
End I f
J ob. Rel ease
End Sub

In Activity_Create we :
Dim the three jobs.
send a Get request in job1
send a Post request in job2
send a Get request in job3

In JobDone we :
Test if the current job was sucessful
If yes, check the current job name and execute its code.
If no, display a ToastMessage

7 Http / HttpUtils2 106 Basic4Android User's Guide
8.5 The Flickr Viewer example

The FlickrViewer example was rewritten and uses the HttpUtils2 library instead of the HttpUtils2
Class. The original example can be found here.

Source code : HttpUtilsExamples\FickrViewer.b4a

In this example we first go to the "main" page of this site
http://www.flickr.com/explore/interesting/7days/.

In this page we find 9 links to 9 images. We submit a second job with all these links.

We show each image as soon as it is ready in the by calling ImagesJobDone from the JobDone
event.

Clicking on an image shows in a second activity as the background image.










9 Network / AsyncStreams 107 Basic4Android User's Guide
9 Network / AsyncStreams

The Network library allows you to communicate over TCP/IP with other computers or devices.
The Network library contains two objects. Socket and ServerSocket.
The Socket object is the communication endpoint. Reading and writing are done with
Socket.InputStream and Socket.OutputStream.

ServerSocket is an object that listens for incoming connections. Once a connection is established an
event is raised and a socket object is passed to the event sub. This socket will be used to handle the
new client.

Client application
Steps required:
- Create and initialize a Socket object.
- Call Socket.Connect with the server address.
- Connection is done in the background. The Connected event is raised when the connection is
ready or if it failed.
- Communicate with the other machine using Socket.InputStream to read data and
Socket.OutputStream to write data.

Server application
Steps required:
- Create and initialize a ServerSocket object.
- Call ServerSocket.Listen to listen for incoming connections. This happens in the background.
- Once a connection is established the NewConnection event is raised and a Socket object is passes.
- Call ServerSocket.Listen if you want to accept more connections.
- Using the Socket object received, communicate with the client.


9 Network / AsyncStreams 108 Basic4Android User's Guide
We will see two examples.
The first example connects to a time server and displays the current date and time as received from
the server.
Sub Pr ocess_Gl obal s
Di mSocket 1 As Socket
End Sub

Sub Gl obal s

End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Socket 1. I ni t i al i ze( "Socket 1")
Socket 1. Connect ( "ni st 1- ny. ust i mi ng. or g" , 13, 20000)
End Sub

Sub Socket 1_Connect ed ( Successf ul As Bool ean)
I f Successf ul = Fal se Then
Msgbox( Last Except i on. Message, "Er r or connect i ng")
Ret ur n
End I f
Di mt r As Text Reader
t r . I ni t i al i ze( Socket 1. I nput St r eam)
Di msb As St r i ngBui l der
sb. I ni t i al i ze
sb. Append( t r . ReadLi ne) ' r ead at l east one l i ne
Do Whi l e t r . Ready
sb. Append( CRLF) . Append( t r . ReadLi ne)
Loop
Msgbox( "Ti me r ecei ved: " & CRLF & sb. ToSt r i ng, "")
Socket 1. Cl ose
End Sub

We are creating a new socket and trying to connect to the server which is listening on port 13.
The next step is to wait for the Connected event.
If the connection is successful we create a TextReader object and initialize it with
Socket1.InputStream. In this case we want to read characters and not bytes so a TextReader is used.
Calling tr.ReadLine may block. However we want to read at least a single line so it is fine.
Then we read all the other available lines (tr.Ready means that there is data in the buffer).


9 Network / AsyncStreams 109 Basic4Android User's Guide

In the second application we will create a file transfer application, that will copy files from the
desktop to the device.
The device will use a ServerSocket to listen to incoming connections.
Once a connection has been made, we will enable a timer. This timer checks every 200ms whether
there is any data waiting to be read.

The file is sent in a specific protocol. First the file name is sent and then the actual file.
We are using a RandomAccessFile object to convert the bytes read to numeric values.
RandomAccessFile can work with files or arrays of bytes, we are using the later in this case.
RandomAccessFile can be set to use little endian byte order. This is important here as the desktop
uses this byte order as well.

The desktop example application was written with Basic4ppc.
Once connected the user selects a file and the file is sent to the device which saves it under
/sdcard/android.
Both applications are attached.

Some notes about the code:
- The server is set to listen on port 2222.
The server displays its IP when it starts. The desktop client should use this IP address when
connecting to a real device (this IP will not work with the emulator).
However if you work with the emulator or if your device is connected to the computer in debug
mode you can use 'adb' to forward a desktop localhost port to the device.
This is done by issuing "adb forward tcp:5007 tcp:2222"
Now in the client code we should connect to the localhost ip with port 5007.
Cl i ent . Connect ( "127. 0. 0. 1", 5007)

Again if you are testing this application in the emulator you must first run this adb command. Adb
is part of the Android SDK.

- Listening to connections :

Sub Act i vi t y_Resume
Ser ver Socket 1. Li st en
End Sub

Sub Act i vi t y_Pause ( User Cl osed As Bool ean)
I f User Cl osed Then
Ti mer 1. Enabl ed = Fal se
Socket 1. Cl ose
Ser ver Socket 1. Cl ose ' st op l i st eni ng
End I f
End Sub

Sub Ser ver Socket 1_NewConnect i on ( Successf ul As Bool ean, NewSocket As Socket )
Di mI nput St r eam1, Out put St r eam1 As AsyncSt r eams
I f Successf ul Then
Socket 1 = NewSocket
Ti mer 1. Enabl ed = Tr ue
I nput St r eam1 = Socket 1. I nput St r eam
Out put St r eam1 = Socket 1. Out put St r eam
Toast MessageShow( "Connect ed", Tr ue)
El se
Msgbox( Last Except i on. Message, "Er r or connect i ng")
End I f
Ser ver Socket 1. Li st en ' Cont i nue l i st eni ng t o new i ncomi ng connect i ons
End Sub
9 Network / AsyncStreams 110 Basic4Android User's Guide
In Sub Activity_Resume (which also called right after Activity_Create) we call ServerSocket.Listen
and start listening to connections. Note that you can call this method multiple times safely.
In Sub Activity_Pause we close the active connection (if there is such a connection) and also stop
listening. This only happens if the user pressed on the back key (UserClosed =True).
The ServerSocket will later be initialized in Activity_Create.

The server side application can handle new connections. It will just replace the previous connection
with the new one.
The desktop client example application doesn't handle broken connections. You will need to restart
it to reconnect.



10 Advanced drawings 111 Basic4Android User's Guide
10 Advanced drawings

Three main chapters for advanced drawing:
View Drawables

Layers with Panels / ImageViews / Images

Diagrams / Charts


10.1 View Drawables

The views have default backgrounds when they are defined either in the Designer or by code.
There do exist three other background objects.
ColorDrawables
GradientDrawables
BitmapDrawables
StateListDrawable

These can be defined in the Designer, but when we want to modify them in the code it needs some
code.

The source code is in the Background folder.

10.1.1 ColorDrawable

The ColorDrawable object has a solid single color, the corners can rounded or not.
The code below sets a ColorDrawable background to a panel.

Di mpnl Col or As Panel

pnl Col or . I ni t i al i ze( "")
Act i vi t y. AddVi ew( pnl Col or , 10%x, 40di p, 80%x, 80di p)
Di mcdwCol or As Col or Dr awabl e
cdwCol or . I ni t i al i ze( Col or s. Red, 5di p)
pnl Col or . Backgr ound = cdwCol or



cdwCol or . I ni t i al i ze( Col or s. Red, 5di p)

The Initialize method of the ColorDrawable object needs two properties :
Color Col or s. Red
CornerRadius 5di p


10 Advanced drawings 112 Basic4Android User's Guide
10.1.2 GradientDrawable

The GradientDrawable object has two colors with a gradient change from the first to the second
color.
The code below sets a GradientDrawable background to a panel.

Di mpnl Gr adi ent As Panel

pnl Gr adi ent . I ni t i al i ze( "")
Act i vi t y. AddVi ew( pnl Gr adi ent , 10%x, 140di p, 80%x, 80di p)
Di mgdwGr adi ent As Gr adi ent Dr awabl e
Di mCol s( 2) As I nt
Col s( 0) = Col or s. Bl ue
Col s( 1) = Col or s. Whi t e
gdwGr adi ent . I ni t i al i ze( "TOP_BOTTOM", Col s)
gdwGr adi ent . Cor ner Radi us = 10di p
pnl Gr adi ent . Backgr ound = gdwGr adi ent



gdwGr adi ent . I ni t i al i ze( "TOP_BOTTOM", Col s)

The GradientDrawable Initialize method needs two parameters :
a string with the orientation "TOP_BOTTOM"
a color array with two colors Col s

The possible orientations are:
TOP_BOTTOM
TR_BL (Top - Right to Bottom - Left)
RIGHT_LEFT
BR_TL (Bottom - Right to Top - Left
BOTTOM_TOP
BL_TR (Bottom - Left to Top - Left
LEFT_RIGHT
TL_BR (Top - Left to Bottom - Right)

The CornerRadius is another separate property.
gdwGr adi ent . Cor ner Radi us = 10di p

10 Advanced drawings 113 Basic4Android User's Guide
10.1.3 BitmapDrawable

The BitmapDrawable object has two properties a Bitmap and a Gravity property.

The BitmapDrawable object has no rounded corner property, if you want rounded corners these
must be part of the bitmap.

The code below sets a BitmapDrawable background to a panel.

Di mpnl Bi t map As Panel

pnl Bi t map. I ni t i al i ze( "")
Act i vi t y. AddVi ew( pnl Bi t map, 10%x, 250di p, 80%x, 80di p)
Di mbdwBi t map As Bi t mapDr awabl e
bdwBi t map. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "backgr ound. png") )
bdwBi t map. Gr avi t y = Gr avi t y. FI LL
pnl Bi t map. Backgr ound = bdwBi t map



Aletsch glacier, picture taken from the Jungfraujoch.



bdwBi t map. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "backgr ound. png")
Sets the bitmap property, in this case a file loaded from the File.DirAssets folder.
But it could be any bitmap.

It is also possible to draw onto the panels background with a Canvas which has this Panel as the
target. The Canvas.Bitmap property points to the bdwBi t map. Bi t map property.

bdwBi t map. Gr avi t y = Gr avi t y. FI LL
Sets the Gravity property.

The Gravity property values can be:
BOTTOM
CENTER
CENTER_HORIZONTAL
CENTER_VERTICAL
FILL
LEFT
NO_GRAVITY
BOTTOM
TOP
The Gravity property can be a combination of above values.
Examples : bdwBi t map. Gr avi t y = Gr avi t y. TOP + Gr avi t y. LEFT
bdwBi t map. Gr avi t y = Gr avi t y. BOTTOM + Gr avi t y. CENTER_HORI ZONTAL


In the Designer there are only three values available: Fill, Center and Top-Left.


10 Advanced drawings 114 Basic4Android User's Guide
10.1.4 StateListDrawable

The StateListDrawable is a drawable that holds other drawables and chooses the current one based
on the view's state.

The Background property of Buttons is a StatelistDrawable, it can be defined either in the Designer
(see chapter 3 in the Beginner's Guide) or in the code.

In the Designer there are two options:
DefaultDrawable default colors set by default
StatelistDrawable custom colors

The button StatelistDrawable has three states.
Enabled Drawable
Disabled Drawable
Pressed Drawable

Each state has its own Drawable, that could be one of the three ColorDrawable, GradientDrawable
or BitmapDrawable.

Example code for a Button with a ColorDrawable :

The source code is the in the ButtonStateDrawables folder.

bt nCol or . I ni t i al i ze( "bt nCol or ")
Act i vi t y. AddVi ew( bt nCol or , 20di p, 100di p, 100di p, 60di p)
bt nCol or . Text = "Col or "

' Def i ne a col or f or Enabl ed st at e
Di mcdwGr eenCol or Enabl ed As Col or Dr awabl e
cdwGr eenCol or Enabl ed. I ni t i al i ze( Col or s. Gr een, 10)

' Def i ne a col or f or Pessed st at e
Di mcdwGr eenCol or Pr essed As Col or Dr awabl e
cdwGr eenCol or Pr essed. I ni t i al i ze( Col or s. RGB( 255, 182, 18) , 10)

' Def i ne a St at eLi st Dr awabl e
Di mst dGr eenCol or As St at eLi st Dr awabl e
st dGr eenCol or . I ni t i al i ze
Di mst at es( 2) As I nt
st at es( 0) = st dGr eenCol or . st at e_enabl ed
st at es( 1) = - st dGr eenCol or . st at e_pr essed
st dGr eenCol or . addSt at e2( st at es, cdwGr eenCol or Enabl ed)
Di mst at es( 1) As I nt
st at es( 0) = st dGr eenCol or . st at e_pr essed
st dGr eenCol or . addSt at e2( st at es, cdwGr eenCol or Pr essed)

' Set st dGr eenCol or t o but t on backgr ound
bt nCol or . Backgr ound = st dGr eenCol or

10 Advanced drawings 115 Basic4Android User's Guide
Example code for a Button with a GradientDrawable :

bt nGr adi ent . I ni t i al i ze( "bt nGr adi ent ")
Act i vi t y. AddVi ew( bt nGr adi ent , 20di p, 180di p, 100di p, 60di p)
bt nGr adi ent . Text = "Gr adi ent "

' Def i ne t wo gr adi ent col or s f or Enabl ed st at e
Di mcol sEnabl ed( 2) As I nt
col sEnabl ed( 0) = Col or s. RGB( 255, 196, 196)
col sEnabl ed( 1) = Col or s. RGB( 255, 25, 25)
' Def i ne a Gr adi ent Dr awabl e f or Enabl ed st at e
Di mgdwEnabl ed As Gr adi ent Dr awabl e
gdwEnabl ed. I ni t i al i ze( "TOP_BOTTOM", col sEnabl ed)
gdwEnabl ed. Cor ner Radi us = 5
' Def i ne t wo gr adi ent col or s f or Pr essed st at e
Di mcol sPr essed( 2) As I nt
col sPr essed( 0) = Col or s. RGB( 25, 255, 25)
col sPr essed( 1) = Col or s. RGB( 255, 255, 255)
' Def i ne a Gr adi ent Dr awabl e f or Pr essed st at e
Di mgdwPr essed As Gr adi ent Dr awabl e
gdwPr essed. I ni t i al i ze( "TOP_BOTTOM", col sPr essed)
gdwPr essed. Cor ner Radi us = 5
' Def i ne a St at eLi st Dr awabl e
Di mst dGr adi ent As St at eLi st Dr awabl e
st dGr adi ent . I ni t i al i ze
Di mst at es( 2) As I nt
st at es( 0) = st dGr adi ent . st at e_enabl ed
st at es( 1) = - st dGr adi ent . st at e_pr essed
st dGr adi ent . addSt at e2( st at es, gdwEnabl ed)
Di mst at es( 1) As I nt
st at es( 0) = st dGr adi ent . st at e_pr essed
st dGr adi ent . addSt at e2( st at es, gdwPr essed)
' Set st dRedGr adi ent t o but t on backgr ound
bt nGr adi ent . Backgr ound = st dGr adi ent

10 Advanced drawings 116 Basic4Android User's Guide
Example code for a Button with a BitmapDrawable :

bt nBi t map. I ni t i al i ze( "bt nBi t map")
Act i vi t y. AddVi ew( bt nBi t map, 40di p, 260di p, 60di p, 60di p)

' Def i ne a bi t map f or Enabl ed st at e
Di mbdwEnabl ed As Bi t mapDr awabl e
bdwEnabl ed. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt nAr r owDown0. png") )
' Def i ne a bi t map f or Pr essed st at e
Di mbdwPr essed As Bi t mapDr awabl e
bdwPr essed. I ni t i al i ze( LoadBi t map( Fi l e. Di r Asset s, "bt nAr r owDown1. png") )
' Def i ne a St at eLi st Dr awabl e
Di mst dBi t map As St at eLi st Dr awabl e
st dBi t map. I ni t i al i ze
Di mst at es( 2) As I nt
st at es( 0) = st dBi t map. st at e_enabl ed
st at es( 1) = - st dBi t map. st at e_pr essed
st dBi t map. addSt at e2( st at es, bdwEnabl ed)
Di mst at es( 1) As I nt
st at es( 0) = st dBi t map. st at e_enabl ed
st dBi t map. addSt at e2( st at es, bdwPr essed)
' Set st dBi t map t o but t on bt nBi t map
bt nBi t map. Backgr ound = st dBi t map

10 Advanced drawings 117 Basic4Android User's Guide
10.1.5 NinePatchDrawable

This is a copy of Erel's tutorial in the forum.

The example code is NinePatchExample in the SourceCode folder.

Android supports a special format of PNG images that can be resized by replicating specific parts of
the image.
These images also include padding information.
These images are named nine-patch images.

You can read more about this format here: Canvas and Drawables | Android Developers


In the example three labels use the same background
nine-patch image and three button using another nine-
patch image.



Android SDK includes a tool named draw9patch.bat that
can help you with building and modifying such images.
This tool is available under: <android>\Tools
You can read more about it here :
Draw 9-patch | Android Developers










The following steps are required to use a nine patch image as a view background:
- Copy the image to <project folder>\Objects\res\drawable
- Set the image to be read-only (otherwise it will be deleted during compilation).
- Add the following sub to your code (requires Reflection library):

Sub Set Ni nePat chDr awabl e( Cont r ol As Vi ew, I mageName As St r i ng)
Di mr As Ref l ect or
Di mpackage As St r i ng
Di mi d As I nt
package = r . Get St at i cFi el d( "anywher esof t war e. b4a. BA", "packageName")
i d = r . Get St at i cFi el d( package & ". R$dr awabl e", I mageName)
r . Tar get = r . Get Cont ext
r . Tar get = r . RunMet hod( "get Resour ces")
Cont r ol . Backgr ound = r . RunMet hod2( "get Dr awabl e", i d, "j ava. l ang. i nt ")
End Sub

10 Advanced drawings 118 Basic4Android User's Guide
For buttons you should use this sub which creates a StateListDrawable from two nine-patch images:

Sub Set Ni nePat chBut t on( Bt n As But t on, Def aul t I mage As St r i ng, Pr essedI mage As St r i ng)
Di mr As Ref l ect or
Di mpackage As St r i ng
Di mi dDef aul t , i dPr essed As I nt
package = r . Get St at i cFi el d( " anywher esof t war e. b4a. BA", " packageName" )
i dDef aul t = r . Get St at i cFi el d( package & " . R$dr awabl e", Def aul t I mage)
i dPr essed = r . Get St at i cFi el d( package & " . R$dr awabl e", Pr essedI mage)
r . Tar get = r . Get Cont ext
r . Tar get = r . RunMet hod( " get Resour ces")
Di msd As St at eLi st Dr awabl e
sd. I ni t i al i ze
sd. AddSt at e( sd. St at e_Pr essed, r . RunMet hod2( " get Dr awabl e", i dPr essed, "j ava. l ang. i nt ") )
sd. AddCat chAl l St at e( r . RunMet hod2( "get Dr awabl e" , i dDef aul t , " j ava. l ang. i nt " ) )
Bt n. Backgr ound = sd
End Sub

Now you should use this sub to set the views backgrounds:

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Act i vi t y. LoadLayout ( "1")
Set Ni nePat chDr awabl e( Label 1, "l abel _bg")
Set Ni nePat chDr awabl e( Label 2, "l abel _bg")
Set Ni nePat chDr awabl e( Label 3, "l abel _bg")
End Sub

Tips
- Don't modify the image files located under res\drawable directly with the draw9patch tool. It
removes the read-only attribute and then the image will be deleted.
- The image name must be lower case (allowed characters a - z, 0 - 9, . , _ ).
- After adding a new image you should clean the project by choosing Tools - Clean Project. This
causes a generated file (R.java) to be recreated and include the new resources.



10 Advanced drawings 119 Basic4Android User's Guide
10.2 Layers with Panels / ImageVi ews / Images

Let's make an example with a movable background, and an image in the foreground.
The source code is in the Layers folder.
The background is a landscape and the foreground is galloping horse.





We use:
Two ImageViews, we could also have used Panels.
One with the background and the second transparent one for the galloping horse.
Two Timers.
One to move the background and one to move the horse image.
One image for the background.
Two sets of 8 images for the horse, one set for galloping to the right and the second set for
galloping to the left.



etc.



10 Advanced drawings 120 Basic4Android User's Guide
10.2.1 Source code

Definition of process global variables :

Sub Pr ocess_Gl obal s
Di mPr ogName As St r i ng : Pr ogName = "Layer s"
Di mPr ogVer si on As St r i ng : Pr ogVer si on = "V 1. 0"
Di mTi mer Hor se As Ti mer
Di mTi mer Backgr ound As Ti mer
Di mTi mer I nt er val As Long
End Sub

Definition of global variables :

Sub Gl obal s
Di mI mageI As I nt ' i ndex of t he cur r ent hor se i mage
Di mI mageDi r As I nt ' di r ect i on of t he hor se i mage
Di mI mageNumber As I nt ' number of hor se i mages
I mageNumber = 8
Di mi mgHor se( 2, I mageNumber ) As Bi t map ' ar r ay hor se i mage bi t maps
Di mi mvBackgr ound As I mageVi ew ' backgr ound I mageVi ew
Di mi mvFor egr ound As I mageVi ew ' f or egr ound I mageVi ew
Di mcvsFor egr ound As Canvas ' canvas f or t he f or egr ound i mage
Di mr ect Hor se As Rect ' r ect angl e of t he hor se i mage
Di mHor seWi dt h As I nt ' hor se i mage wi dt h
Di mHor seHei ght As I nt ' hor se i mage hei ght
Di mHor seTop As I nt ' hor se i mage t op
Di mHor seLef t As Fl oat ' cur r ent l ef t posi t i on of t he hor se i mage
Di mHor seDel t a As Fl oat ' hor se move per t i mer t i ck
Di mBackgr oundLef t As Fl oat ' cur r ent l ef t posi t i on of t he backgr ound
Di mBackgr oundDel t a As Fl oat ' backgr ound move per t i mer t i ck
Di mScal e As Fl oat ' devi ce scal e
End Sub

10 Advanced drawings 121 Basic4Android User's Guide
Initialization of the views and different variables :

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Di mi As I nt

' get t he devi ce scal e
Di ml v As Layout Val ues
l v = Get Devi ceLayout Val ues
Scal e = l v. Scal e

' l oad t he hor se i mages
' f i r st i ndex = 0 f or gal l opi ng t o t he r i ght
' f i r st i ndex = 1 f or gal l opi ng t o t he l ef t
For i = 0 To I mageNumber - 1
i mgHor se( 0, i ) . I ni t i al i ze( Fi l e. Di r Asset s, "hor se0" & i & ". png")
i mgHor se( 1, i ) . I ni t i al i ze( Fi l e. Di r Asset s, "hor se1" & i & ". png")
Next

' i ni t i al i ze var i abl es dependi ng on t he devi ce or i ent at i on
I f Act i vi t y. Wi dt h > Act i vi t y. Hei ght Then
Hor seDel t a = 4di p
Hor seHei ght = 40%y
Ti mer I nt er val = 50
El se
Hor seDel t a = 2di p
Hor seHei ght = 25%y
Ti mer I nt er val = 80
End I f

' i ni t i al i ze t he backgr ound t i mer
Ti mer Backgr ound. I ni t i al i ze( "Ti mer Backgr ound", Ti mer I nt er val )

' i ni t i al i ze t he hor se t i mer
' we use t wo t i mes t he backgr ound t i mer i nt er val
Ti mer Hor se. I ni t i al i ze( "Ti mer Hor se", Ti mer I nt er val * 2)

' cal cul at e t he hor se i mages si ze and t hei r ver t i cal posi t i on
Hor seWi dt h = Hor seHei ght / i mgHor se( 0, 0) . Hei ght * i mgHor se( 0, 0) . Wi dt h
Hor seTop = 65%y - Hor seHei ght / 2
r ect Hor se. I ni t i al i ze( 0, Hor seTop, Hor seWi dt h, Hor seTop + Hor seHei ght )

' i ni t i al i ze t he backgr ound
i mvBackgr ound. I ni t i al i ze( "")
Act i vi t y. AddVi ew( i mvBackgr ound, 0, 0, 400%y, 100%y)
i mvBackgr ound. Gr avi t y = Gr avi t y. FI LL
i mvBackgr ound. Bi t map = LoadBi t map( Fi l e. Di r Asset s, "Wyomi ng. j pg")
i mvBackgr ound. Lef t = 0

' cal cul at e Backgr oundDel t a
' t o have t he same number of st eps as f or t he hor se
i = ( 100%x - Hor seWi dt h) / Hor seDel t a
Backgr oundDel t a = - ( i mvBackgr ound. Wi dt h - 100%x) / 2 / i

' i ni t i al i ze t he f or egr ound
i mvFor egr ound. I ni t i al i ze( "")
Act i vi t y. AddVi ew( i mvFor egr ound, 0, 0, 100%x, 100%y)

' i ni t i al i ze t he f or egr ound canvas
cvsFor egr ound. I ni t i al i ze( i mvFor egr ound)

' set t he f or egr ound t o t r anspar ent
Di mr ect 1 As Rect
r ect 1. I ni t i al i ze( 0, 0, i mvFor egr ound. Wi dt h, i mvFor egr ound. Hei ght )
cvsFor egr ound. Dr awRect ( r ect 1, Col or s. Tr anspar ent , Tr ue, 1)
End Sub
10 Advanced drawings 122 Basic4Android User's Guide

Initialization of different variables :

Sub Act i vi t y_Resume
Act i vi t y. Ti t l e = Pr ogName & " " & Pr ogVer si on

' i ni t i al i ze t he t i mer s
Ti mer Hor se. Enabl ed = Tr ue
Ti mer Backgr ound. Enabl ed = Tr ue

' set t he i ni t i al val ues
Hor seLef t = 0
Backgr oundLef t = 0
I mageI = 0
I mageDi r = 0

' dr aw t he f i r st hor se i mage
Dr awHor se( I mageI , 10)
End Sub

Horse timer :

Sub Ti mer Hor se_Ti ck
' i ncr ease t he hor se l ef t posi t i on
Hor seLef t = Hor seLef t + Hor seDel t a

' t est i f t he hor se r eaches t he r i ght or l ef t bor der
I f Hor seLef t >= 100%x - Hor seWi dt h - Hor seDel t a OR Hor seLef t <= 0 Then
Backgr oundDel t a = - Backgr oundDel t a
Hor seDel t a = - Hor seDel t a
Hor seLef t = Hor seLef t + Hor seDel t a
I f I mageDi r = 0 Then
I mageDi r = 1
El se
I mageDi r = 0
i mvBackgr ound. Lef t = 0
End I f
End I f

' updat e t he hor se i mage i ndex
I mageI = I mageI + 1
' r eset t he i mage i ndex
I f I mageI = I mageNumber Then
I mageI = 0
End I f

' dr aw t he new hor se i mage
Dr awHor se( I mageI , Hor seLef t )
End Sub

Background timer :

Sub Ti mer Backgr ound_Ti ck
' set t he backgr ound l ef t posi t i on
Backgr oundLef t = Backgr oundLef t + Backgr oundDel t a
i mvBackgr ound. Lef t = Backgr oundLef t
End Sub

10 Advanced drawings 123 Basic4Android User's Guide
Drawing routine for the horse images :

Sub Dr awHor se( i As I nt , x As Fl oat )
' dr awi ng r out i ne f or t he hor se i mage

' er ase t he cur r ent hor se i mage, dr aw a t r anspar ent r ect angl e
cvsFor egr ound. Dr awRect ( r ect Hor se, Col or s. Tr anspar ent , Tr ue, 1)

' set t he new hor se i mage posi t i on
r ect Hor se. Lef t = x
r ect Hor se. Ri ght = x + Hor seWi dt h

' dr aw t he new hor se i mage
cvsFor egr ound. Dr awBi t map( i mgHor se( I mageDi r , i ) , Nul l , r ect Hor se)

' i nval i dat e ( updat e) t he f or egr ound i mage
i mvFor egr ound. I nval i dat e2( r ect Hor se)
End Sub

Stop of the timers when the Activity is paused :

Sub Act i vi t y_Pause ( User Cl osed As Bool ean)
' st op t he t i mer s
Ti mer Hor se. Enabl ed = Tr ue
Ti mer Backgr ound. Enabl ed = Tr ue
End Sub


10 Advanced drawings 124 Basic4Android User's Guide
10.3 Diagrams / Charts

In the first chapter we will draw diagrams to show curves.
In the second we analyze the Charts Framework.

One example program for
drawing curves can be found
in the forum : the
Oscilloscope project.













10.3.1 Diagrams / Graph example program

Two dimensional data can be drawn on a plane with a Cartesian coordinate system.

A Cartesian coordinate system in two dimensions (also called a rectangular coordinate system) is
defined by an ordered pair of perpendicular lines (axes), a single unit of length for both axes, and an
orientation for each axis. The point where the axes meet, is taken as the origin for both, thus turning
each axis into a number line.
In mathematical illustrations of two-dimensional Cartesian systems, the first coordinate
(traditionally called the abscissa or x - axis) is measured along a horizontal axis, oriented from left
to right. The second coordinate (the ordinate or y - axis) is then measured along a vertical axis,
usually oriented from bottom to top (source Wikipedia).

The source code of this example program, Graph, is joined in the SourceCode folder.

We use a Panel (we could also have used an ImageView) to draw the graphics, we call it the graph.
On the graph we have the grid, the surface where the curve is drawn.













6
5
4
3
2
1
0
0 1 2 3 4 5 6 7 8 9 10
Title
y - scale
x - scale
Grid
Graph
Curve
nb y divisions
nb x divisions
10 Advanced drawings 125 Basic4Android User's Guide
The panel can be of different sizes :



Full screen Smaller

Definition of the Graph variables :




Definition of the Grid variables :




GridX1
GridW
GridX0
G
r
i
d
Y
1

Grid
Graph
G
r
i
d
Y
0

G
r
i
d
H

GraphX1
GraphW
GraphX0
G
r
a
p
h
Y
1

Screen
Graph
G
r
a
p
h
Y
0

G
r
a
p
h
H

10 Advanced drawings 126 Basic4Android User's Guide
Source code.

The code is commented and I think (hope) enough self explanatory.
It should not be considered as a project for itself but more as a demonstrator.

The code could seem complicated but it really is not. You'll probably notice a lot of variables, but I
prefer working with variables rather than directly with numeric values. It's much easier to maintain
or modify a code.

Activity create.

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Gr aphI ni t
CheckDevi ceType

pnl Gr aph. I ni t i al i ze( "pnl Gr aph")
Act i vi t y. AddVi ew( pnl Gr aph, Gr aphX0, Gr aphY0, Gr aphW, Gr aphH)

cvsGr aph. I ni t i al i ze( pnl Gr aph)
Cur veI ni t
Gr i dI ni t
I f Fi r st Ti me Then
Cur veVal I ni t
End I f
Scal eI ni t
End Sub

Activity resume.

Sub Act i vi t y_Resume
Di mi As I nt

Act i vi t y. Ti t l e = Pr ogName & " " & Pr ogVer si on
Gr aphCl ear
Gr i dDr aw
For i = 0 To Cur veNb - 1
Cur veDr aw( i )
Next
End Sub

The different dimensions for the graph are all expressed in percentage of the Activity height d%y ,
to fit the different device sizes.

Initialization of the Graph panel dimensions. (called from Activity_Create)

Sub Gr aphI ni t
' i ni t i al i ze t he Gr aph var i abl es
' al l di mensi ons ar e expr essed i n %of hei ght
Gr aphX0 = 3%y
Gr aphW= 100%x - 2 * Gr aphX0
Gr aphX1 = Gr aphX0 + Gr aphW

Gr aphY0 = 3%y
Gr aphH = 100%y - 2 * Gr aphY0
Gr aphY1 = Gr aphY0 + Gr aphH

r ect Gr aph. I ni t i al i ze( 0, 0, Gr aphW, Gr aphH)
Gr aphCol or = Col or s. Whi t e
End Sub

10 Advanced drawings 127 Basic4Android User's Guide
The text sizes are also adapted to the device sizes.

I have considered four different device sizes :
Smartphone 3.5 smartphone with a 3.5 inch screen size
Smartphone 5 smartphone with a 5 inch screen size
Tablet 7 tablet with a 7 inch screen size
Tablet 10 tablet with a 10 inch screen size

Code to check the device type. (called from Activity_Create)

Sub CheckDevi ceType
' check devi ce t ype, used t o def i ne t ext si zes
' shoul d be compl et ed i f necessar y

Di ml v As Layout Val ues
l v = Get Devi ceLayout Val ues

Sel ect l v. Scal e
Case 2
Devi ceType = "Smar t phone 5"
Case 1. 5
I f l v. Wi dt h > 1100 Then
Devi ceType = "Tabl et 7"
El se
Devi ceType = "Smar t phone 3. 5"
End I f
Case 1
I f l v. Wi dt h > 1100 Then
Devi ceType = "Tabl et 10"
El se I f l v. Wi dt h < 600 Then
Devi ceType = "Smar t phone 3. 5"
El se
Devi ceType = "Tabl et 7"
End I f
End Sel ect
End Sub

10 Advanced drawings 128 Basic4Android User's Guide
Initialization of the curves parameters. (called from Activity_Create)

Sub Cur veI ni t
' set cur ve l i ne col or
Cur veLi neCol or ( 0) = Col or s. Red
Cur veLi neCol or ( 1) = Col or s. Bl ue
Cur veLi neCol or ( 2) = Col or s. RGB( 10, 140, 0)

' set cur ve l i ne wi st h ( st r oke)
Cur veLi neSt r oke( 0) = 3di p
Cur veLi neSt r oke( 1) = 2di p
Cur veLi neSt r oke( 2) = 1di p

' set cur ve t ext si ze accor di ng t o t he devi ce t ype
Cur veText Si ze = 14
Sel ect Devi ceType
Case "Smar phone 3. 5"
Cur veText Si ze = 14
Case "Smar phone 5"
Cur veText Si ze = 22
Case "Tabl et 7"
Cur veText Si ze = 28
Case "Tabl et 10"
Cur veText Si ze = 42
End Sel ect

' get t he t ext hei ght
Cur veText Hei ght = cvsGr aph. Measur eSt r i ngHei ght ( "Ag", Typef ace. DEFAULT,
Cur veText Si ze) + 2di p
End Sub


10 Advanced drawings 129 Basic4Android User's Guide
Initilization of the grid. (called from Activity_Create)

Sub Gr i dI ni t
' i ni t i al i ze t he Gr i d var i abl es
' al l di mensi ons ar e expr essed pr opor t i onal t o t he cur ves t ext hei ght

' hor zont al di mensi ons
Gr i dX0 = 2 * Cur veText Hei ght
Gr i dW= Gr aphW- Gr i dX0 - 1. 2 * Cur veText Hei ght
Gr i dX1 = Gr i dX0 + Gr i dW

' ver i cal di mensi ons
Gr i dY0 = 3. 2 * Cur veText Hei ght
Gr i dH = Gr aphH - Gr i dY0 - 1. 2 * Cur veText Hei ght
Gr i dY1 = Gr i dY0 + Gr i dH

' def i ne t he number of di vi si ons f or each axi s
I f l v. Wi dt h > l v. Hei ght Then
Gr i dNbDi vX = 10
Gr i dNbDi vY = 6
El se
Gr i dNbDi vX = 5
Gr i dNbDi vY = 12
End I f

' cal cul at e t he di vi si on di mensi ons i n pi xel s
Gr i dDel t aX = Gr i dW/ Gr i dNbDi vX
Gr i dDel t aY = Gr i dH / Gr i dNbDi vY

' assi gn t he gr i d r ect angl e
r ect Gr i d. I ni t i al i ze( Gr i dX0, Gr i dY0, Gr i dX1, Gr i dY1)

' set t he di f f er ent col or s
Gr i dCol or = Col or s. Whi t e
Gr i dLi neCol or = Col or s. Li ght Gr ay
Gr i dFr ameCol or = Col or s. Bl ack

Scal eText Col or = Col or s. Bl ack

' set scal e t ext si ze accor di ng t o t he devi ce t ype
Scal eText Si ze = 12
Sel ect Devi ceType
Case "Smar t phone 3. 5"
Scal eText Si ze = 12
Case "Smar t phone 5"
Scal eText Si ze = 18
Case "Tabl et 7"
Scal eText Si ze = 24
Case "Tabl et 10"
Scal eText Si ze = 36
End Sel ect
Scal eText Hei ght = cvsGr aph. Measur eSt r i ngHei ght ( "Ag", Typef ace. DEFAULT,
Scal eText Si ze) + 2di p

End Sub



10 Advanced drawings 130 Basic4Android User's Guide
Initialization of the curve values. (called from Activity_Create)
These are sample curves, this routine can be adapted to each application.
This routine is called only when Fi r st Ti me = Tr ue.

Sub Cur veVal I ni t
Di mi , n As I nt
Di mt As Doubl e
Di mAmpl i t ude( Cur veNb) As Doubl e
Di mOf f set ( Cur veNb) As Doubl e
Di mOmega( Cur veNb) As Doubl e

' set cur ve ampl i t ude
Ampl i t ude( 0) = 2. 5
Ampl i t ude( 1) = 1. 5
Ampl i t ude( 2) = . 02

' set cur ve of f set
Of f set ( 0) = 0
Of f set ( 1) = 1
Of f set ( 2) = - 1

' set cur ve omega
Omega( 0) = 2. 4 * cPI
Omega( 1) = 8 * cPI

' cal cul at e cur ve poi nt val ues
For i = 0 To Cur veNb - 1
For n = 0 To Cur veNbPoi nt s
t = n / 100
I f i = 2 Then
Cur ve( i , n) = Of f set ( i ) + Ampl i t ude( i ) * Rnd( - 100, 100)
El se
Cur ve( i , n) = Of f set ( i ) + Ampl i t ude( i ) * Si n( Omega( i ) * t )
End I f
Next
Next

' set cur ve names and uni t s
Cur veName( 0) = "Vol t age"
Cur veUni t ( 0) = "[ V] "
Cur veName( 1) = "Cur r ent "
Cur veUni t ( 1) = "[ A] "
Cur veName( 2) = "Accel er at i on"
Cur veUni t ( 2) = "[ m/ s2] "

' set scal e val ues
Scal eXMax = Cur veNbPoi nt s / 10
Scal eXMi n = 0

Scal eYMax = 3
Scal eYMi n = - 3
End Sub

Initialization of the scales according to the device orientation. (called from Activity_Create)

Sub Scal eI ni t
' i ni t i l i ze t he scal es accor di ng t o t he gr i d di mensi ons.
Scal eXDel t a = Scal eXMax / Gr i dNbDi vX
Scal eX = Gr i dW/ ( Scal eXMax - Scal eXMi n)

Scal eYDel t a = ( Scal eYMax - Scal eYMi n) / Gr i dNbDi vY
Scal eY = Gr i dH / ( Scal eYMax - Scal eYMi n)
End Sub
10 Advanced drawings 131 Basic4Android User's Guide
Drawing of the grid. (called from Activity_Resume)

Sub Gr i dDr aw
' dr aw t he Gr i d
Di mi As I nt
Di mx0, y0 As Fl oat

' dr aw ver t i cal l i nes
For i = 1 To Gr i dNbDi vX - 1
x0 = Gr i dX0 + i * Gr i dDel t aX
cvsGr aph. Dr awLi ne( x0, Gr i dY0, x0, Gr i dY1, Gr i dLi neCol or , 1)
Next

' dr aw hor i zont al l i nes
For i = 1 To Gr i dNbDi vY - 1
y0 = Gr i dY0 + i * Gr i dDel t aY
cvsGr aph. Dr awLi ne( Gr i dX0, y0, Gr i dX1, y0, Gr i dLi neCol or , 1)
Next

' dr aw t he f r ame
cvsGr aph. Dr awRect ( r ect Gr i d, Gr i dFr ameCol or , Fal se, 1)

' dr aw t he scal es
Scal eYDr aw
Scal eXDr aw

' i nval i dat e ( updat e) t he Gr aph
Act i vi t y. I nval i dat e
End Sub

Drawing the X scale. (called from GridDraw)

Sub Scal eXDr aw
' dr aw X scal e
Di mi As I nt
Di mt xt As St r i ng
Di mx, y As Fl oat

y = Gr i dY1 + Scal eText Hei ght
For i = 0 To Gr i dNbDi vX
t xt = ( Scal eXMi n + i * Scal eXDel t a)
x = Gr i dX0 + i * Gr i dDel t aX
cvsGr aph. Dr awText ( t xt , x, y, Typef ace. DEFAULT, Scal eText Si ze,
Scal eText Col or , "CENTER")
Next
End Sub

10 Advanced drawings 132 Basic4Android User's Guide
Drawing of the Y scale. (called from GridDraw)

Sub Scal eYDr aw
' dr aw Y scal e
Di mi As I nt
Di mt xt As St r i ng
Di mx, y As Fl oat

x = Gr i dX0 - Scal eText Hei ght / 3
For i = 0 To Gr i dNbDi vY
t xt = ( Scal eYMax - i * Scal eYDel t a)
y = Gr i dY0 + Scal eText Hei ght / 3 + i * Gr i dDel t aY
cvsGr aph. Dr awText ( t xt , x, y, Typef ace. DEFAULT, Scal eText Si ze,
Scal eText Col or , "RI GHT")
Next
End Sub

Drawing the curves. (called from Activity_Resume)

Sub Cur veDr aw( i As I nt )
' dr aw t he cur ve of i ndex i
Di mn As I nt
Di md, t h, x0, y0, x1, y1 As Fl oat
Di mText Hei ght As Fl oat

' dr aw t he cur ve
x0 = Gr i dX0
y0 = Gr i dY0 + ( Scal eYMax - Cur ve( i , 0) ) * Scal eY
d = Gr i dW/ Cur veNbPoi nt s
For n = 1 To Cur veNbPoi nt s
x1 = Gr i dX0 + n * d
y1 = Gr i dY0 + ( Scal eYMax - Cur ve( i , n) ) * Scal eY
cvsGr aph. Dr awLi ne( x0, y0, x1, y1, Cur veLi neCol or ( i ) , Cur veLi neSt r oke( i ) )
x0 = x1
y0 = y1
Next

' get t he t ext hei ght
Text Hei ght = cvsGr aph. Measur eSt r i ngHei ght ( "Ag", Typef ace. DEFAULT,
Cur veText Si ze) + 2di p

' dr aw cur ve name
y0 = Gr i dY0 - Text Hei ght / 3
cvsGr aph. Dr awText ( Cur veName( i ) & " " & Cur veUni t ( i ) , Gr i dX0, y0 - i *
Text Hei ght , Typef ace. DEFAULT, Cur veText Si ze, Cur veLi neCol or ( i ) , "LEFT")
End Sub


10 Advanced drawings 133 Basic4Android User's Guide
10.3.2 Second Graph program

Graph1 is a second diagram example program, it's an evolution of the previous one, that uses a
different scale for each curve.

The source code of this example program, Graph1, is joined in the SourceCode folder.







10 Advanced drawings 134 Basic4Android User's Guide
10.3.3 Charts Framework

The Charts Framework module allows to draw several types of diagrams:
Pie charts
Bar charts
Stacked Bar charts
Curves

It can be downloaded here : Charts Framework

Attention : The Charts Framework is a code module and not a library.





The goal of this chapter is to show how to use the Charts Framework and not to explain how its
code is build. The joined source codes allows to play with each kind of chart type.

10 Advanced drawings 135 Basic4Android User's Guide
10.3.3.1 Pie Chart
Source code in the Charts\PieChart folder.

Sub Gl obal s
Di mpnl Pi e As Panel
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Cr eat ePi eTab
End Sub

Sub Cr eat ePi eTab
' i ni t i al ze t he panel t o di spl ay t he pi e char t
pnl Pi e. I ni t i al i ze( "pnl Pi e")
Act i vi t y. AddVi ew( pnl Pi e, 10%x, 10%y, 80%x, 80%y)

' i ni t i al i ze t he pi e dat a
Di mPD As Pi eDat a
PD. I ni t i al i ze
PD. Tar get = pnl Pi e ' Set t he t ar get vi ew

' Add t he i t ems.
' The l ast par amet er I s t he col or . Passi ng 0 wi l l make i t a r andomcol or .
Char t s. AddPi eI t em( PD, "I t em#1", 120, 0)
Char t s. AddPi eI t em( PD, "I t em#2", 25, 0)
Char t s. AddPi eI t em( PD, "I t em#3", 50, 0)
Char t s. AddPi eI t em( PD, "I t em#4", 190, 0)
Char t s. AddPi eI t em( PD, "I t em#5", 350, 0)

' Tot al si ze of gaps bet ween sl i ces. Set t o 0 f or no gaps.
PD. GapDegr ees = 20

' The backgr ound col or of t he l egend bi t map.
PD. LegendBackCol or = Col or s. ARGB( 150, 100, 100, 100)
' PD. LegendBackCol or = Col or s. Whi t e

' Thi s cal l dr aws t he pi e.
' PD - The pi e dat a
' Col or s. Gr ay - The vi ew' s backgr ound col or
' Tr ue - Cr eat e a l egend bi t map.
Di ml egend As Bi t map
l egend = Char t s. Dr awPi e( PD, Col or s. Gr ay, Tr ue)
' l egend = Char t s. Dr awPi e( PD, Col or s. Li ght Gr ay, Tr ue)
' l egend = Char t s. Dr awPi e( PD, Col or s. Whi t e, Tr ue)

I f l egend. I sI ni t i al i zed Then
' I ni t i al i ze t he l egend I mageVi ew
Di mI mageVi ew1 As I mageVi ew
I mageVi ew1. I ni t i al i ze( "")
I mageVi ew1. Set Backgr oundI mage( l egend)

' Add t he l egend I mageVi ew t o t he Pi e Panel
pnl Pi e. AddVi ew( I mageVi ew1, 10di p, 10di p, l egend. Wi dt h, l egend. Hei ght )
End I f
End Sub

10 Advanced drawings 136 Basic4Android User's Guide
Initialize the Panel for the Pie Chart :
' i ni t i al ze t he panel t o di spl ay t he pi e char t
pnl Pi e. I ni t i al i ze( "pnl Pi e")
Act i vi t y. AddVi ew( pnl Pi e, 10%x, 10%y, 80%x, 80%y)

10%x, 10%y, 80%x, 80%y are the position and dimensions of the pie panel.

Initialize the Pie data :
' i ni t i al i ze t he pi e dat a
Di mPD As Pi eDat a
PD. I ni t i al i ze
PD. Tar get = pnl Pi e ' Set t he t ar get vi ew

Add the pie chart data :
' Add t he i t ems.
' The l ast par amet er I s t he col or . Passi ng 0 wi l l make i t a r andomcol or .
Char t s. AddPi eI t em( PD, "I t em#1", 120, 0)
Char t s. AddPi eI t em( PD, "I t em#2", 25, 0)
Char t s. AddPi eI t em( PD, "I t em#3", 50, 0)
Char t s. AddPi eI t em( PD, "I t em#4", 190, 0)
Char t s. AddPi eI t em( PD, "I t em#5", 350, 0)

Drawing routine : Char t s. AddPi eI t em( PD, "I t em#1", 120, 0)
Where :
PD is the PieData object
"I t em#1" is the item title
120 is the item value
0 is the color, enter 0 for random color

Set the gap value :
' Tot al si ze of gaps bet ween sl i ces. Set t o 0 f or no gaps.
PD. GapDegr ees = 20

This is the total gap between the pies in degrees. Enter 0 for no gap.

Set the legend background color :
' The backgr ound col or of t he l egend bi t map.
PD. LegendBackCol or = Col or s. ARGB( 150, 100, 100, 100)
' PD. LegendBackCol or = Col or s. Whi t e

You can play with different colors, the original color is partially transparent to see the chart behind
the legend.

Calls the pie drawing routine :
' Thi s cal l dr aws t he pi e.
' PD - The pi e dat a
' Col or s. Gr ay - The vi ew' s backgr ound col or
' Tr ue - Cr eat e a l egend bi t map.
Di ml egend As Bi t map
l egend = Char t s. Dr awPi e( PD, Col or s. Gr ay, Tr ue)

Drawing routine: l egend = Char t s. Dr awPi e( PD, Col or s. Gr ay, Tr ue)
Where :
l egend Bitmap of the legend image returned by the routine
PD PieData object
Col or s. Gr ay Background color of the pie chart.
Tr ue Boolean variable defining whether a legend image should be drawn.
10 Advanced drawings 137 Basic4Android User's Guide
Check if the legend bitmap does exist :
I f l egend. I sI ni t i al i zed Then

If True then:
Initialize the legend ImageView, set it's background image and add it to the pie panel :
' I ni t i al i ze t he l egend I mageVi ew
Di mI mageVi ew1 As I mageVi ew
I mageVi ew1. I ni t i al i ze( "")
I mageVi ew1. Set Backgr oundI mage( l egend)

' Add t he l egend I mageVi ew t o t he Pi e Panel
pnl Pi e. AddVi ew( I mageVi ew1, 10di p, 10di p, l egend. Wi dt h, l egend. Hei ght )
End I f
End Sub




10 Advanced drawings 138 Basic4Android User's Guide
10.3.3.2 Bar Chart

Source code in the Charts\BarChart folder.

Sub Gl obal s
Di mpnl Bar s As Panel
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Cr eat eBar sTab
End Sub

Sub Cr eat eBar sTab
' i ni t i al ze t he panel t o di spl ay t he bar char t
pnl Bar s. I ni t i al i ze( "pnl Bar s")
Act i vi t y. AddVi ew( pnl Bar s, 10%x, 10%y, 80%x, 80%y)

' i ni t i al i ze t he bar dat a
Di mBD As Bar Dat a
BD. I ni t i al i ze
BD. Tar get = pnl Bar s
BD. Bar sWi dt h = 15di p
BD. St acked = Fal se

' set t he bar col or s
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Red, 230) ) ' Fi r st bar col or
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Bl ue, 230) )
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Gr een, 230) )

' Add t he i t ems.
For i = 1 To 4
Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( - 1000, 1000) , Rnd( - 1000,
1000) , Rnd( - 1000, 1000) ) )
' Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( 0, 1000) , Rnd( 0, 1000) ,
Rnd( 0, 1000) ) )
Next

' I ni t i al i ze t he gr aph obj ect
' Set t he bar char t par amet er s
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "Bar s Char t "
G. XAxi s = "Year "
G. YAxi s = "Val ues"
G. YSt ar t = - 1000 ' mi n ver t i cal scal e
' G. YSt ar t = 0
G. YEnd = 1000 ' max ver t i cal scal e
G. YI nt er val = 200 ' ver t i cal scal e di vi si ons
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awBar sChar t ( G, BD, Col or s. Whi t e)
End Sub

Sub MakeTr anspar ent ( Col or As I nt , Al pha As I nt ) As I nt
Ret ur n Bi t . And( Col or , Bi t . Or ( 0x00FFFFFF, Bi t . Shi f t Lef t ( Al pha, 24) ) )
End Sub

10 Advanced drawings 139 Basic4Android User's Guide
Initialize the Panel for the Bar Chart :
' i ni t i al ze t he panel t o di spl ay t he bar char t
pnl Bar s. I ni t i al i ze( "pnl Bar s")
Act i vi t y. AddVi ew( pnl Bar s, 10%x, 10%y, 80%x, 80%y)

10%x, 10%y, 80%x, 80%y are the position and dimensions of the bar panel.

Initialize the Bar data :
' i ni t i al i ze t he bar dat a
Di mBD As Bar Dat a
BD. I ni t i al i ze
BD. Tar get = pnl Bar s
BD. Bar sWi dt h = 15di p
BD. St acked = Fal se

BD. St acked = Fal se indicates that it is a BarChart and not a StackedBarChart.

Set the bar colors :
' set t he bar col or s
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Red, 230) ) ' Fi r st bar col or
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Bl ue, 230) )
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Gr een, 230) )

Add the bar data :
' Add t he i t ems.
For i = 1 To 4
Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( - 1000, 1000) , Rnd( - 1000,
1000) , Rnd( - 1000, 1000) ) )
' Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( 0, 1000) , Rnd( 0, 1000) ,
Rnd( 0, 1000) ) )
Next

A bar chart can have n sets of m values.
Loop to add the sets, in the example n =4.
For i = 1 To 4

Routine adding the bar values, in the example m =3 :
Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( - 1000, 1000) , Rnd( - 1000,
1000) , Rnd( - 1000, 1000) ) )
Where :
BD BarData object
2005 + i Horizontal axis tag
Ar r ay As Fl oat Array of values the m values per set.

The bar chart can draw negative and positive values.
This is not the case for stacked bar charts.

10 Advanced drawings 140 Basic4Android User's Guide
Initialize the graph object, set the bar chart parameters and draw the chart :
' I ni t i al i ze t he gr aph obj ect
' Set t he bar char t par amet er s and dr aw t he char t
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "Bar s Char t "
G. XAxi s = "Year "
G. YAxi s = "Val ues"
G. YSt ar t = - 1000 ' mi n ver t i cal scal e
' G. YSt ar t = 0
G. YEnd = 1000 ' max ver t i cal scal e
G. YI nt er val = 200 ' ver t i cal scal e di vi si ons
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awBar sChar t ( G, BD, Col or s. Whi t e)
End Sub

Drawing routine : Char t s. Dr awBar sChar t ( G, BD, Col or s. Whi t e)
Where:
G Graph object
BD BarData object
Col or s. Whi t e Background color of the bar chart panel


Routine to set a color partially transparent :
Sub MakeTr anspar ent ( Col or As I nt , Al pha As I nt ) As I nt
Ret ur n Bi t . And( Col or , Bi t . Or ( 0x00FFFFFF, Bi t . Shi f t Lef t ( Al pha, 24) ) )
End Sub




10 Advanced drawings 141 Basic4Android User's Guide
10.3.3.3 Stacked Bar Chart

Source code in the Charts\StackedBarChart folder.

For details, look at the Bar Chart chapter.

Sub Gl obal s
Di mpnl St ackedBar s As Panel
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Cr eat eSt ackedBar sTab
End Sub

Sub Cr eat eSt ackedBar sTab
' i ni t i al ze t he panel t o di spl ay t he st acked bar char t
pnl St ackedBar s. I ni t i al i ze( "pnl St ackedBar s")
Act i vi t y. AddVi ew( pnl St ackedBar s, 10%x, 10%y, 80%x, 80%y)

' i ni t i al i ze t he bar dat a
Di mBD As Bar Dat a
BD. I ni t i al i ze
BD. Tar get = pnl St ackedBar s
BD. Bar sWi dt h = 40di p
BD. St acked = Tr ue ' Makes i t a st acked bar s char t

' set t he bar col or s
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Red, 230) ) ' Fi r st bar col or
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Bl ue, 230) )
Char t s. AddBar Col or ( BD, MakeTr anspar ent ( Col or s. Gr een, 230) )

' Add t he i t ems.
For i = 1 To 4
Char t s. AddBar Poi nt ( BD, 2005 + i , Ar r ay As Fl oat ( Rnd( 0, 400) , Rnd( 0, 400) ,
Rnd( 0, 400) ) )
Next

' I ni t i al i ze t he gr aph obj ect
' Set t he bar char t par amet er s
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "St acked Bar s Char t "
G. XAxi s = "Year "
G. YAxi s = "Val ues"
G. YSt ar t = 0
G. YEnd = 1000
G. YI nt er val = 100
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awBar sChar t ( G, BD, Col or s. Whi t e)
End Sub

Sub MakeTr anspar ent ( Col or As I nt , Al pha As I nt ) As I nt
Ret ur n Bi t . And( Col or , Bi t . Or ( 0x00FFFFFF, Bi t . Shi f t Lef t ( Al pha, 24) ) )
End Sub

The routine is exactly the same as for Bar Charts.
The only difference is the bar with that is wider and the BD.Stacked parameter is True.
BD. Bar sWi dt h = 40di p
BD. St acked = Tr ue ' Makes i t a st acked bar s char t


10 Advanced drawings 142 Basic4Android User's Guide



10 Advanced drawings 143 Basic4Android User's Guide
10.3.3.4 Lines Chart

Source code in the Charts\LinesChart folder.

The routine can draw one or more lines, the difference is explained below.

Sub Gl obal s
Di mpnl Li nes As Panel
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Cr eat eLi nesTab
End Sub

Sub Cr eat eLi nesTab
' I ni t i al ze t he panel t o di spl ay t he l i nes char t
pnl Li nes. I ni t i al i ze( "pnl Li nes")
Act i vi t y. AddVi ew( pnl Li nes, 10%x, 10%y, 80%x, 80%y)

' I ni t i al i ze t he l i ne dat a
Di mLD As Li neDat a
LD. I ni t i al i ze
LD. Tar get = pnl Li nes

' Set t he l i ne col or s
Char t s. AddLi neCol or ( LD, Col or s. Red) ' Fi r st l i ne col or
Char t s. AddLi neCol or ( LD, Col or s. Bl ue) ' Second l i ne col or

' Add t he l i ne poi nt s.
For i = 0 To 360 St ep 10
' I n t he case of 2 l i nes or mor e we ar e addi ng an ar r ay of val ues.
' One f or each l i ne.
' Make sur e t o cr eat e an ar r ay f or each poi nt .
' You cannot r euse a si ngl e ar r ay f or al l poi nt s.
Char t s. AddLi neMul t i pl ePoi nt s( LD, i , Ar r ay As Fl oat ( Si nD( i ) , CosD( i ) ) , i Mod
90 = 0)
Next

' I ni t i al i ze t he gr aph obj ect
' Set t he l i ne char t par amet er s and dr aw t he l i ne char t
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "2 Li nes Char t ( Si ne & Cosi ne) "
G. XAxi s = "Degr ees"
G. YAxi s = "Val ues"
G. YSt ar t = - 1
G. YEnd = 1
G. YI nt er val = 0. 2
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awLi neChar t ( G, LD, Col or s. Whi t e)
End Sub



10 Advanced drawings 144 Basic4Android User's Guide
Initialize the Panel for the Lines Chart :
' I ni t i al ze t he panel t o di spl ay t he l i nes char t
pnl Li nes. I ni t i al i ze( "pnl Li nes")
Act i vi t y. AddVi ew( pnl Li nes, 10%x, 10%y, 80%x, 80%y)

10%x, 10%y, 80%x, 80%y are the position and dimensions of the lines panel.

Initialize the Lines data :
' I ni t i al i ze t he l i ne dat a
Di mLD As Li neDat a
LD. I ni t i al i ze
LD. Tar get = pnl Li nes

Set the line colors :
' Set t he l i ne col or s
Char t s. AddLi neCol or ( LD, Col or s. Red) ' Fi r st l i ne col or
Char t s. AddLi neCol or ( LD, Col or s. Bl ue) ' Second l i ne col or

Add the lines data :
' Add t he l i ne poi nt s.
For i = 0 To 360 St ep 10
' I n t hi s case we ar e addi ng an ar r ay of t wo val ues. One f or each l i ne.
' Make sur e t o cr eat e an ar r ay f or each poi nt .
' You cannot r euse a si ngl e Ar r ay For al l poi nt s.
Char t s. AddLi neMul t i pl ePoi nt s( LD, i , Ar r ay As Fl oat ( Si nD( i ) , CosD( i ) ) , i Mod
90 = 0)
Next

In this part of the routine we generate the values for each line at each point.

Routine adding the line values :
Char t s. AddLi neMul t i pl ePoi nt s( LD, i , Ar r ay As Fl oat ( Si nD( i ) , CosD( i ) ) , i Mod 90 = 0)
Where :
LD LineData object
i X value of the horizontal axis, can be different than i.
Ar r ay As Fl oat ( Si nD( i ) , CosD( i ) )
Array of Y values for index i
In the example there are 2 lines : Si nD( i ) and CosD( i )
For a single line chart we could have this statement :
Char t s. AddLi neMul t i pl ePoi nt s( LD, i , Si nD( i ) , i Mod 90 = 0)
For a three line chart we could have this statement :
Char t s. AddLi neMul t i pl ePoi nt s( LD, i , Ar r ay As Fl oat ( Val 1, Val 2, Val 3) , i Mod 90 = 0)
i Mod 90 = 0 When true then a horizontal tag, with the value of i, is displayed on
the horizontal axis.
i Mod 90 = 0 is equal to the reminder of i / 90,
the reminder is true only when i =0, 90, 180, 270 or 360.



The general routine would look like this:
Char t s. AddLi neMul t i pl ePoi nt s( LD, x, Ar r ay As Fl oat ( Val 1, Val 2, . . . , Val N) , TagFunct i on)

TagFunct i on is a function that is true when we want to have a tag on the horizontal axis.

10 Advanced drawings 145 Basic4Android User's Guide
Initialize the graph object, set the lines chart parameters and draw the chart :
' I ni t i al i ze t he gr aph obj ect
' Set t he l i ne char t par amet er s and dr aw t he l i ne char t
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "2 Li nes Char t ( Si ne & Cosi ne) "
G. XAxi s = "Degr ees"
G. YAxi s = "Val ues"
G. YSt ar t = - 1
G. YEnd = 1
G. YI nt er val = 0. 2
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awLi neChar t ( G, LD, Col or s. Whi t e)
End Sub

Drawing routine : Char t s. Dr awLi neChar t ( G, LD, Col or s. Whi t e)
Where :
G Graph object
LD LineData object
Col or s. Whi t e Chart background color

There is only one text and one scale for the vertical axis.




10 Advanced drawings 146 Basic4Android User's Guide
Other example with 3 lines. Source code LinesChart1.

Sub Cr eat eLi nesTab
' I ni t i al ze t he panel t o di spl ay t he l i nes char t
pnl Li nes. I ni t i al i ze( "pnl Li nes")
Act i vi t y. AddVi ew( pnl Li nes, 10%x, 10%y, 80%x, 80%y)

' I ni t i al i ze t he l i ne dat a
Di mLD As Li neDat a
LD. I ni t i al i ze
LD. Tar get = pnl Li nes

' Set t he l i ne col or s
Char t s. AddLi neCol or ( LD, Col or s. Red) ' Fi r st l i ne col or
Char t s. AddLi neCol or ( LD, Col or s. Bl ue) ' Second l i ne col or
Char t s. AddLi neCol or ( LD, Col or s. Gr een) ' Thi r d l i ne col or

' Add t he l i ne poi nt s.
Di mx As Fl oat
For i = 0 To 500 St ep 10
' I n t he case of 2 l i nes or mor e we ar e addi ng an ar r ay of val ues.
' One f or each l i ne.
' Make sur e t o cr eat e an ar r ay f or each poi nt .
' You cannot r euse a si ngl e ar r ay f or al l poi nt s.
x = i / 100
Char t s. AddLi neMul t i pl ePoi nt s( LD, x, Ar r ay As Fl oat ( Rnd( - 20, 21) + 20, Rnd( -
15, 16) - 20, CosD( 3 * i ) * 35) , i Mod 50 = 0)
Next

' I ni t i al i ze t he gr aph obj ect
' Set t he l i ne char t par amet er s and dr aw t he l i ne char t
Di mG As Gr aph
G. I ni t i al i ze
G. Ti t l e = "3 Li nes Char t ( Rnd and Cos) "
G. XAxi s = "Ti me"
G. YAxi s = "Val ues"
G. YSt ar t = - 50
G. YEnd = 50
G. YI nt er val = 10
G. Axi sCol or = Col or s. Bl ack
Char t s. Dr awLi neChar t ( G, LD, Col or s. Whi t e)
End Sub


Horizontal tags every 50
increments :
i Mod 50 = 0

The x values are (x = i / 100) :
0, 0.5, 1, 1.5, 2 etc.


Size :
10%x, 10%y, 80%x, 80%y







10 Advanced drawings 147 Basic4Android User's Guide
The charts can be of different sizes, but it's up to you to adapt the scales.
In the example below the vertical scale tags are overlapping.







Size :
20%x, 20%y, 60%x, 60%y














Size :
0, 0, 100%x, 100%y








The margins and the text sizes remain the same, independent of the chart size.
If really you want a small size chart you could change the margins and the text sizes in the Charts
code, but be careful because in that case your code module becomes a custom one.

10 Advanced drawings 148 Basic4Android User's Guide
10.4 Anti ali asi ng fi lter

Erel posted the code to set the antialiasing filter in a thread where a user asked for that possibility.

Here is the code:

Sub Set Ant i Al i as ( c As Canvas, Act i ve As I nt )
' Act i ve = 0 f i l t er OFF
' Act i ve = 1 f i l t er ON
Di mr As Ref l ect or
Di mNat i veCanvas As Obj ect
r . Tar get = c
Nat i veCanvas = r . Get Fi el d( "canvas" )
Di mPai nt Fl agsDr awFi l t er As Obj ect
Pai nt Fl agsDr awFi l t er = r . Cr eat eObj ect 2( " andr oi d. gr aphi cs. Pai nt Fl agsDr awFi l t er ", _
Ar r ay As Obj ect ( 0, Act i ve) , Ar r ay As St r i ng( "j ava. l ang. i nt " , "j ava. l ang. i nt ") )
r . Tar get = Nat i veCanvas
r . RunMet hod4( " set Dr awFi l t er " , Ar r ay As Obj ect ( Pai nt Fl agsDr awFi l t er ) , _
Ar r ay As St r i ng( "andr oi d. gr aphi cs. Dr awFi l t er ") )
End Sub

An example program to test it with simple lines can be found on the forum : DrawLines



11 Class modules 149 Basic4Android User's Guide
11 Class modules

Basic4android v2.00 adds support for classes modules.

11.1 Getting started

Classes definition from Wikipedia:

In object-oriented programming, a class is a construct that is used to create instances of itself referred to
as class instances, class objects, instance objects or simply objects. A class defines constituent members
which enable its instances to have state and behavior. Data field members (member variables or instance
variables) enable a class instance to maintain state. Other kinds of members, especially methods, enable the
behavior of a class instances. Classes define the type of their instances.

A class usually represents a noun, such as a person, place or thing, or something nominalized. For example,
a "Banana" class would represent the properties and functionality of bananas in general. A single, particular
banana would be an instance of the "Banana" class, an object of the type "Banana".

Example: Source code Persons in the Classes/ Persons folder.

In the Person module

' Cl ass Per son modul e
Sub Cl ass_Gl obal s
Pr i vat e Fi r st Name, Last Name As St r i ng
Pr i vat e Bi r t hDat e As Long
End Sub

Sub I ni t i al i ze ( aFi r st Name As St r i ng, aLast Name As St r i ng, aBi r t hDat e As Long)
Fi r st Name = aFi r st Name
Last Name = aLast Name
Bi r t hDat e = aBi r t hDat e
End Sub

Publ i c Sub Get Name As St r i ng
Ret ur n Fi r st Name & " " & Last Name
End Sub

Publ i c Sub Get Cur r ent Age As I nt
Ret ur n Get AgeAt ( Dat eTi me. Now)
End Sub

Publ i c Sub Get AgeAt ( Dat e As Long) As I nt
Di mdi f f As Long
di f f = Dat e - Bi r t hDat e
Ret ur n Fl oor ( di f f / Dat eTi me. Ti cksPer Day / 365)
End Sub

Main module.

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
Di mp As Per son
p. I ni t i al i ze( "J ohn", "Doe", Dat eTi me. Dat ePar se( "05/ 12/ 1970") )
Log( p. Get Cur r ent Age)
End Sub


11 Class modules 150 Basic4Android User's Guide
I will start by explaining the differences between classes, code modules and types.

Similar to types, classes are templates. From this template you can instantiate any number of
objects.
The type fields are similar to the classes global variables. However unlike types which only define
the data structure, classes also define the behavior. The behavior is defined in the classes subs.

Unlike classes which are a template for objects, code modules are collections of subs. Another
important difference between code modules and classes is that code modules always run in the
context of the calling sub (the activity or service that called the sub). The code module doesn't hold
a reference to any context. For that reason it is impossible to handle events or use CallSub with
code modules.
Classes store a reference to the context of the activity or service module that called the Initialize
sub. This means that classes objects share the same life cycle as the service or activity that
initialized them.

Code modules are somewhat similar to singleton or static classes.

11.1.1 Adding a class module



Adding a new or existing class module is done by choosing Project ->Add New Module ->Class
module or Add Existing module.
Like other modules, classes are saved as files with bas extension.

11.1.2 Classes structures

Classes must have the following two subs:

Class_Globals - This sub is similar to the activity Globals sub. These variables will be the class
global variables (sometimes referred to instance variables or instance members).

Initialize - A class object should be initialized before you can call any other sub. Initializing an
object is done by calling the Initialize sub. When you call Initialize you set the object's context (the
parent activity or service).
Note that you can modify this sub signature and add arguments as needed.

11 Class modules 151 Basic4Android User's Guide
In the above code we created a class named Person and later instantiate an object of this type:

Di mp As Per son
p. I ni t i al i ze( "J ohn", "Doe", Dat eTi me. Dat ePar se( "05/ 12/ 1970") )
Log( p. Get Cur r ent Age)

Calling initialize is not required if the object itself was already initialized:

Di mp2 As Per son
p2 = p ' bot h var i abl es now poi nt t o t he same Per son obj ect .
Log( p2. Get Cur r ent Age)

11.1.3 Polymorphism

Polymorphism allows you to treat different types of objects that adhere to the same interface in the
same way.
Basic4android polymorphism is similar to the Duck typing concept.

As an example we will create two classes named: Square and Circle.
Each class has a sub named Draw that draws the object to a canvas:
Source code Draw in the Classes/Draw folder.

' Cl ass Squar e modul e
Sub Cl ass_Gl obal s
Pr i vat e mx, my, mLengt h As I nt
End Sub

' I ni t i al i zes t he obj ect . You can add par amet er s t o t hi s met hod i f needed.
Sub I ni t i al i ze ( x As I nt , y As I nt , l engt h As I nt )
mx = x
my = y
mLengt h = l engt h
End Sub

Sub Dr aw( c As Canvas)
Di mr As Rect
r . I ni t i al i ze( mx, my, mx + mLengt h, my + mLengt h)
c. Dr awRect ( r , Col or s. Whi t e, Fal se, 1di p)
End Sub


' Cl ass Ci r cl e modul e
Sub Cl ass_Gl obal s
Pr i vat e mx, my, mRadi us As I nt
End Sub

' I ni t i al i zes t he obj ect . You can add par amet er s t o t hi s met hod i f needed.
Sub I ni t i al i ze ( x As I nt , y As I nt , r adi us As I nt )
mx = x
my = y
mRadi us = r adi us
End Sub

Sub Dr aw( cvs As Canvas)
cvs. Dr awCi r cl e( mx, my, mRadi us, Col or s. Yel l ow, Fal se, 1di p)
End Sub

11 Class modules 152 Basic4Android User's Guide
In the main module we create a list with Squares and Circles. We then go over the list and draw all
the objects:

Sub Pr ocess_Gl obal s
Di mshapes As Li st
End Sub

Sub Gl obal s
Di mcvs As Canvas
End Sub

Sub Act i vi t y_Cr eat e( Fi r st Ti me As Bool ean)
cvs. I ni t i al i ze( Act i vi t y)
Di msq1, sq2 As Squar e
Di mci r cl e1 As Ci r cl e
shapes. I ni t i al i ze
sq1. I ni t i al i ze( shapes, 100di p, 100di p, 50di p)
sq2. I ni t i al i ze( shapes, 2di p, 2di p, 100di p)
ci r cl e1. I ni t i al i ze( shapes, 50%x, 50%y, 100di p)
Dr awAl l Shapes
End Sub

Sub Dr awAl l Shapes
For i = 0 To shapes. Si ze - 1
Log( shapes. Get ( i ) )
Cal l Sub2( shapes. Get ( i ) , "Dr aw", cvs)
Next
Act i vi t y. I nval i dat e
End Sub

As you can see, we do not know the specific type of each object in the list. We just assume that it
has a Draw method that expects a single Canvas argument. Later we can easily add more types of
shapes.
You can use the SubExi st s keyword to check whether an object includes a specific sub.

You can also use the I s keyword to check if an object is of a specific type.

11.1.4 Self reference

The Me keyword returns a reference to the current object. Me keyword can only be used inside a
class module.
Consider the above example. We could have passed the shapes list to the Initialize sub and then add
each object to the list from the Initialize sub:

Sub I ni t i al i ze ( Shapes As Li st , x As I nt , y As I nt , r adi us As I nt )
mx = x
my = y
mRadi us = r adi us
Shapes. Add( Me)
End Sub



11 Class modules 153 Basic4Android User's Guide
11.1.5 Acti vi ty obj ect

This point is related to the activities special life cycle.
Make sure to first read the activities and processes life-cycle tutorial.

Android UI elements hold a reference to the parent activity. As the OS is allowed to kill background
activities in order to free memory, UI elements cannot be declared as process global variables (these
variables live as long as the process lives). Such elements are named Activity objects. The same is
true for custom classes. If one or more of the class global variables is of a UI type (or any activity
object type) then the class will be treated as an "activity object". The meaning is that instances of
this class cannot be declared as process global variables.

11 Class modules 154 Basic4Android User's Guide
11.2 Classes from the forum

A certain number of examples exist in the forum.
Below a non exhaustive list with comments from the develppers.

TableView - Supports tables of any size Erel
This class is a much improved version of the ScrollView based Table.

CustomListView Erel
A flexible list based on ScrollView

CameraEx Erel
CameraEx class wraps the Camera object and using reflection and other code it extends its
functionality.

CheckList Informatix
I created a class to manage a list with checkboxes (but not only, you can use it for any kind
of list with rows). The layout is highly customizable and you can even extend a clicked item
with extra content. You can rearrange the items programmatically or manually (drag &
drop).

SlideMenu corwin42
This is a class that implements a sliding menu as seen in many apps like Google+, Evernote,
Facebook etc.

ScrollPanel Informatix
This class displays a small panel beside the vertical scrollbar in a scrollview. You can
display what you want in its label and drag it to quickly scroll.

Floating Windows Informatix
With this class, you can create floating windows, move them with the finger, dock them,
stick them to an edge, maximize them, customize their action bar... You fill them as you fill
a panel.

ActionBar Informatix
This class allows to create Action Bars.
There was already a good library to do that (AHActionBar) but I needed more features and
more flexibility.

Animated Sliding Menu NJDude
This class will allow you to create animated sliding menus.

ICS Like Horizontal and Vertical Seekbars mabool
This class implements ICS Like SeekBars.

ClsWheel klaus
It allows to display different data input screens with wheels. What can be done ? You can
define five different types of Wheel input screens.

If you want to develop your own classes you should have a look at the classes above to see and
understand what has been done and how.
11 Class modules 155 Basic4Android User's Guide
11.3 First example Wheel sel ecti on

11.3.1 Simpl e example

We will develop a wheel selection class.

The source code is in the Classes/ClsWheelSimple1 folder.

The height of the views is automatically adjusted according to the text size.
The width of the views is automatically adjusted according to the longest
text.

To display the wheel we use :
1 ScrollView to display the data and allow scrolling
The entries in the ScrollView are Labels added in the code.
4 Panels
o the background panel holding all views
o a top and a bottom panel for the shadows
o a center panel as the 'display window'

Background Panel ScrollView Top, center bottom Panels Lines on top and
bottom Panels























ScrollView on All Views
background Panel superimposed on
background Panel

Cherry
Prune
Strawberry
Raspberry
Blueberry
Cherry
Prune
Strawberry
Raspberry
Blueberry
Cherry
Prune
Strawberry
Raspberry
Blueberry
11 Class modules 156 Basic4Android User's Guide
The code :

In Class_Globals we define different variables.

Sub Cl ass_Gl obal s
Pr i vat e pnl Backgr ound, pnl Top, pnl Mi ddl e, pnl Bot t omAs Panel
Pr i vat e Cal l back As Obj ect ' cal l i ng modul e
Pr i vat e scv As Scr ol l Vi ew ' Scr ol l Vi ew f or t he dat a
Pr i vat e Col Wi dt h As I nt ' wi dt h of t he col umn ( Scr ol l Vi ew)
Pr i vat e Font Si ze As Fl oat ' f ont si ze f or t he t ext i n t he Scr ol l Vi ew
Pr i vat e l bl Hei ght As I nt ' hei ght of t he Scr ol l Vi ew

Pr i vat e Wheel Cont ent As Li st ' cont ent of t he

' var i abl es used t o cal cul at e t he di mensi ons of pnl Backgr ound
Pr i vat e Lef t , Top, Wi dt h, Hei ght As Fl oat

Pr i vat e l i neWi dt h = 4di p As I nt ' wi dt h of t he l i nes

' col or s
Pr i vat e col BackGr ound = Col or s. Bl ue As I nt ' backgr ound
Pr i vat e col Shadow = Col or s. Bl ack As I nt ' shadow of t op and bot t ompanel s
Pr i vat e col Wi ndowLi ne = Col or s. Red As I nt ' l i nes of cent er wi ndow
Pr i vat e col Wi ndow = Col or s. ARGB( 96, 255, 0, 0) As I nt ' cent er wi ndow
End Sub

Initialization routine :
We define local variables to use them in other routines.

' I ni t i al i zes t he Wheel .
' Cal l backModul e = cal l i ng modul e
' Par ent = par ent act i vi t y or panel
' cWheel Cont ent = Li st obj ect wi t h t he cont ent on t he wheel
' cFont Si ze = f ont si ze of t he t ext i n t he wheel
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , Par ent As Obj ect , _
cWheel Cont ent As Li st , cFont Si ze As Fl oat )

Cal l back = Cal l backModul e
Font Si ze = cFont Si ze
Wheel Cont ent = cWheel Cont ent

We calculate the height of one Label in the ScrollView. We define a Canvas for the Parent object to
measure the height of the text in pixels for the given font size and add a top and bottom margin
depending on the font size.

' cal cul at e t he t ext hei ght i n pi xel s accor di ng t o t he t ext si ze
Di mcvs As Canvas
cvs. I ni t i al i ze( Par ent )
l bl Hei ght = cvs. Measur eSt r i ngHei ght ( "Ag", Typef ace. DEFAULT, Font Si ze) + _
Di pToCur r ent ( Font Si ze / 2)

With cvs. Measur eSt r i ngHei ght we measure the height of the text according to the font size.
Then we add a small amount for margins depending also on the font size, Font Si ze / 2 is a good
value. But as the font size is independent of the screen density we need to transform this value into
a di p (density independent pixels) value with the Di pToCur r ent function.
11 Class modules 157 Basic4Android User's Guide
We admit the height of the wheel (the ScrollView) and the background Panel equal to 5 Label
heights. We have 2 label heights above the center window and 2 label heights below it.
' we admi t t he t ot al hei ght t o 5 t i mes t he l abel hei ght
Hei ght = 5 * l bl Hei ght

We calculate the max text length, add a margin and add two line widths for the border.
' cal cul at e t he wi dt h of t he l ongest t ext i n t he Scr ol l Vi ew
' accor di ng t o t he t ext si ze
Col Wi dt h = 0
For j = 0 To Wheel Cont ent . Si ze - 1
Col Wi dt h = Max( Col Wi dt h, cvs. Measur eSt r i ngWi dt h( Wheel Cont ent . Get ( j ) , _
Typef ace. DEFAULT, Font Si ze) )
Next
Col Wi dt h = Col Wi dt h + 20di p ' add a mar gi n
Wi dt h = Col Wi dt h + 2 * l i neWi dt h ' add t wo l i ne wi dt hs f or t he t ot al wi dt h

We set Col Wi dt h = 0 (the ScrollView width) and with cvs. Measur eSt r i ngWi dt h we measure
the text length of each entry and memorize the bigger value in Col Wi dt h.
Then we add 20di p for the margins.
The whole width of the background panel is the scrollview width plus two line widths.

We initialize the background panel, add it onto the parent object and set its background color.
' i ni t i al i ze pnl Backgr ound and add i t ont o t he par ent obj ect
' and set i t s col or
pnl Backgr ound. I ni t i al i ze( "pnl Backgr ound")
I f Par ent I s Act i vi t y Then
Di mact As Act i vi t y
act = Par ent
Lef t = ( act . Wi dt h - Wi dt h) / 2 ' cent er pnl Backgr ound i n t he par ent obj ect
Top = ( act . Hei ght - Hei ght ) / 2
act . AddVi ew( pnl Backgr ound, Lef t , Top, Wi dt h, Hei ght )
El se I f I sPanel ( Par ent ) Then
Di mpnl p As Panel
pnl p = Par ent
Lef t = ( pnl p. Wi dt h - Wi dt h) / 2 ' cent er pnl Backgr ound i n t he par ent obj ect
Top = ( pnl p. Hei ght - Hei ght ) / 2
pnl p. AddVi ew( pnl Backgr ound, Lef t , Top, Wi dt h, Hei ght )
El se
Log( "Par ent must be an act i vi t y or a panel . ")
Ret ur n Fal se
End I f
pnl Backgr ound. Col or = col BackGr ound

We initialize pnl Backgr ound calculate its Left and Top properties to centre it on the screen or
on the parent panel. If the parent view is not an activity nor a panel an error message is
displayed.
11 Class modules 158 Basic4Android User's Guide
We initialize the ScrollView and add it onto the background panel.
' i ni t i al i ze t he Scr ol l Vi ew and add i t ont o t he par ent obj ect
scv. I ni t i al i ze2( l bl Hei ght * ( Wheel Cont ent . Si ze + 4) , "scv")
pnl Backgr ound. AddVi ew( scv, l i neWi dt h, 0, Col Wi dt h, Hei ght )
The internal panel height is equal to the size of the WheelContent plus 4 label heights for the two
empty labels on top and the two on the bottom.

We fill the ScrollView.
' f i l l t he Scr ol l Vi ew
For j = 0 To Wheel Cont ent . Si ze + 5
Di ml bl As Label
l bl . I ni t i al i ze( "")
scv. Panel . AddVi ew( l bl , 0, j * l bl Hei ght , Col Wi dt h, l bl Hei ght )
l bl . Gr avi t y = Gr avi t y. CENTER_HORI ZONTAL + Gr avi t y. CENTER_VERTI CAL
l bl . Col or = Col or s. Whi t e
l bl . Text Col or = Col or s. Bl ack
l bl . Text Si ze = Font Si ze
I f j >= 2 AND j <= Wheel Cont ent . Si ze + 2 - 1 Then
l bl . Text = Wheel Cont ent . Get ( j - 2)
El se
l bl . Text = ""
End I f
Next
We need to dim the labels in the loop to have an independent instance for each.
No need to add an event name in the Initialize method, we don't use any Label event.
Add the Label onto the ScrollView.Panel.
Set Gravity of the Labels to centre the text vertically and horizontally.
Set the Label background and text color.
Fill the ScrollView, the first two Labels are empty to ensure that the first entry is shown in the
middle window. And we add two empty Labels at the end.

We initialize the top panel and set its background colors.
' i ni t i al i ze t he t op panel and set i t s backgr ound col or s
' and set i t s col or
pnl Top. I ni t i al i ze( "")
pnl Backgr ound. AddVi ew( pnl Top, 0, 0, Wi dt h, 2 * l bl Hei ght )
Di mgdw As Gr adi ent Dr awabl e
Di mcol s( 2) As I nt
col s( 0) = col Shadow
col s( 1) = Col or s. Tr anspar ent
gdw. I ni t i al i ze( "TOP_BOTTOM", col s)
gdw. Cor ner Radi us = 0
pnl Top. Backgr ound = gdw
Di mcvs1 As Canvas
cvs1. I ni t i al i ze( pnl Top) ' i ni t i al i ze a canvas and dr aw t he l i ne on t he bot t om
cvs1. Dr awLi ne( l i neWi dt h, pnl Top. Hei ght - l i neWi dt h / 2, Wi dt h - l i neWi dt h, _
pnl Top. Hei ght - l i neWi dt h / 2, col Wi ndowLi ne, l i neWi dt h)
The background of the top panel is a GradientDrawable with two colors the col Shadow color on
top and transparent on the bottom.
We dim a GradientDrawable object and an array of Int for the two colors, initialize the
GradientDrawable, set the color orientation "TOP_BOTTOM" and the colors, set the radius and set
the GradientDrawable as the panel background.
Then we initialize a Canvas and draw a line on the bottom border.

We initialize the centre panel and set its background color.
' i ni t i al i ze t he mi ddl e panel and set i t s backgr ound col or
pnl Mi ddl e. I ni t i al i ze( "")
pnl Backgr ound. AddVi ew( pnl Mi ddl e, 0, 2 * l bl Hei ght , Wi dt h, l bl Hei ght )
pnl Mi ddl e. Col or = col Wi ndow

11 Class modules 159 Basic4Android User's Guide
We initialize the bottompanel and set its background colors.
' i ni t i al i ze t he bot t ompanel and set i t s backgr ound
pnl Bot t om. I ni t i al i ze( "")
pnl Backgr ound. AddVi ew( pnl Bot t om, 0, ( 2 + 1) * l bl Hei ght , Wi dt h, 2 * l bl Hei ght )
Di mgdw As Gr adi ent Dr awabl e
Di mcol s( 2) As I nt
col s( 0) = col Shadow
col s( 1) = Col or s. Tr anspar ent
gdw. I ni t i al i ze( "BOTTOM_TOP", col s)
gdw. Cor ner Radi us = 0
pnl Bot t om. Backgr ound = gdw
Di mcvs2 As Canvas
cvs2. I ni t i al i ze( pnl Bot t om) ' i ni t i al i ze a canvas and dr aw t he l i ne on t he t op
cvs2. Dr awLi ne( l i neWi dt h, l i neWi dt h / 2, Wi dt h - l i neWi dt h, l i neWi dt h / 2, _
col Wi ndowLi ne, l i neWi dt h)
The principle is the same as for the top panel.

The wheel at this state is not usable it has two major drawbacks.
When we scroll the wheel the selected entry is not shown centred in the middle window.
We need a method to return the selected value.
11.3.2 Show the selected entry centred in the middl e window.

The source code is in the Classes\ClsWheelSimple2 folder.

To achieve this we calculate the scrolling speed and when the user releases the scrolling we
calculate an estimated time till the scroll end, set this time to a Timer and the Timer calls a routine
to finish the scrolling to show the selected entry centred in the middle window.

We add a Touch event for the ScrollView with the Reflection library and a Timer.
In the Touch event we calculate the scrolling speed and when the user releases the scrolling we
calculate an estimated time to finish the scrolling and set this time to the Timer

Code:
In the Cl ass_Gl obal s routine we add the variables below:
Pr i vat e Ti mer Wheel As Ti mer

Pr i vat e Scr ol l Pos As I nt
Pr i vat e Scr ol l PosMax As I nt
Pr i vat e y0 As I nt
Pr i vat e t 0 As Long
Pr i vat e speed As Doubl e

Then, in the Sub I ni t i al i ze routine just before the ScrollView filling we add the code below.
' add t he Touch event t o t he Scr ol l Vi ew
Pr i vat e obj Wheel As Ref l ect or
obj Wheel . Tar get = scvWheel
obj Wheel . Set OnTouchLi st ener ( "scvWheel _Touch")
obj Wheel . RunMet hod2( "set Ver t i cal Scr ol l Bar Enabl ed", Fal se, "j ava. l ang. bool ean")

' f i l l t he Scr ol l Vi ew

We define a Reflector object, set its target to the ScrollView, add the ScrollView Touch event and
remove the vertical scrollbar.
And at the end of the Sub I ni t i al i ze routine we add:
Ti mer Wheel . I ni t i al i ze( "Ti mer Wheel ", 200)

End Sub
11 Class modules 160 Basic4Android User's Guide
Then we add the Sub scvWheel _Touch routine :

Pr i vat e Sub scvWheel _Touch( Vi ewTag As Obj ect , Act i on As I nt , X As Fl oat , _
Y As Fl oat , Mot i onEvent As Obj ect ) As Bool ean
Di mdt As Long
Di mt t As I nt

Sel ect Act i on
Case 0 ' ACTI ON_DOWN
t 0 = Dat eTi me. Now
y0 = Y
Case 1 ' ACTI ON_UP
t t = Max( 10, - Logar i t hm( 1 / speed, cE) * 110)
Ti mer Wheel . I nt er val = t t
Ti mer Wheel . Enabl ed = Tr ue
Case 2 ' ACTI ON_MOVE
dt = ( Dat eTi me. Now - t 0)
speed = Abs( ( Y - y0) / dt * 250)
t 0 = Dat eTi me. Now
y0 = Y
End Sel ect

Ret ur n Fal se
End Sub

In ACTI ON_DOWN we set the variables t 0 to the current time and y0 to the current y position.
In ACTI ON_MOVE we calculate the time difference dt between the current time and the previous
move. Then we calculate the moving speed, the value of 250 was determined by trials.
And we set the variables t 0 to the current time and y0 to the current y position.
In ACTI ON_UP we calculate the estimated time t t till scroll end. The equation is based on a
logarithmic decay and the value of 110 was determined by trials.
Then we set this time to the Timer.Interval and enable the Timer.

The Ti mer Wheel _Ti ck routine:
Pr i vat e Sub Ti mer Wheel _Ti ck
Ti mer Wheel . Enabl ed = Fal se
scvWheel . Scr ol l Posi t i on = Fl oor ( scvWheel . Scr ol l Posi t i on / l bl Hei ght + . 5) * _
l bl Hei ght
End Sub
We disable the Timer and calculate the final ScrollPosition as a multiple of the l bl Hei ght with the
current scroll position and set it to the scvWheel . Scr ol l Posi t i on.

11 Class modules 161 Basic4Android User's Guide
11.3.3 Return the selected value

The source code is in the Classes\ClsWheelSimple3 folder.

We add several new Views :
Two Panels
o pnlScreen covers the whole
screen to consume the
events of other views on
the screen.
o pnlMain holding the
wheel, a title and two
Buttons.
A title Label
o lblTitle
Two Buttons
o btnOK returns
the selected value and hides
pnlScreen.
o btnCancel hides pnlScreen.



To avoid that events of Views behind the wheel are raised we add a Panel pnlScreen covering the
whole screen with an empty pnlScreen_Click event.
Pr i vat e Sub pnl Scr een_Cl i ck
' empt y t o consume t he pnl Scr een event s
End Sub

The same for pnlMain.
Pr i vat e Sub pnl Mai n_Cl i ck
' empt y t o consume t he pnl Mai n event s
End Sub

We declare some new variables :
Pr i vat e bt nSpace, bt nHei ght , bt nWi dt h As I nt ' but t on di mensi ons
Pr i vat e pnl Mai nWi dt h, pnl Mai nHei ght As I nt ' pnl Mai n di mensi ons
Pr i vat e Ti t l e As St r i ng
Pr i vat e Cal l BackVi ew As Obj ect

We modify the Initialization routine to add the Title variable:
' I ni t i al i zes t he Wheel .
' Cal l backModul e = cal l i ng modul e
' Par ent = par ent act i vi t y or panel
' cTi t l e = t i t l e f or t he i nput
' cWheel Cont ent = Li st obj ect wi t h t he cont ent on t he wheel
' cFont Si ze = f ont si ze of t he t ext i n t he wheel
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , Par ent As Obj ect , cTi t l e As _
St r i ng, cWheel Cont ent As Li st , cFont Si ze As Fl oat )

In the routine we set the dimensions of the buttons and calculate the dimensions of pnlMain. The
detail of this code is not explained here you can look at it in the provided source code.

11 Class modules 162 Basic4Android User's Guide
We need to modify the Show routine and add an object for the returned value.
The return object can be a Label, an EditText, a Button or a String.
' show t he wheel
' cCal l BackVi ew = vi ew or st r i ng var i abl e t hat get s t he r et ur ned val ue
' Val ue = val ue t o pr eset
Publ i c Sub Show( cCal l BackVi ew As Obj ect , Val ue As Obj ect )
Di mi ndex As I nt

Cal l BackVi ew = cCal l BackVi ew

pnl Scr een. Vi si bl e = Tr ue

i ndex = Wheel Cont ent . I ndexOf ( Val ue)
scvWheel . Scr ol l Posi t i on = i ndex * l bl Hei ght
DoEvent s
scvWheel . Scr ol l Posi t i on = i ndex * l bl Hei ght
DoEvent s
End Sub

We get the selected value in this routine :
Pr i vat e Sub Get Sel ect i on As St r i ng
Di mi As I nt

i = ( Fl oor ( scvWheel . Scr ol l Posi t i on / l bl Hei ght ) )
Ret ur n Wheel Cont ent . Get ( i )
End Sub

We return the selected value to the Text property of the given view in the Show routine or to the
given String variable.
Pr i vat e Sub bt nOK_Cl i ck
I f Cal l BackVi ew I s Label Then
Di ml bl As Label
l bl = Cal l BackVi ew
l bl . Text = Get Sel ect i on
El se I f Cal l BackVi ew I s St r i ng Then
Cal l BackVi ew = Get Sel ect i on
End I f
pnl Scr een. Vi si bl e = Fal se
End Sub

11 Class modules 163 Basic4Android User's Guide
11.3.4 Color properties

Another improvement would be to add color properties to the wheels.
Since B4A version 2.70 it is possible to add properties to a class.
More details in chapter 1 Chapter 10.5 Add properties to a class.

The source code is in the Classes\ClsWheelSimple4 folder.

First we add a BackgroundColor property that changes the color of the lateral lines.



The color can be set with the set BackGr oundCol or .
The color can be read back with get BackGr oundCol or .

The code in the class module :

' Get s or set s t he Backgr oundCol or pr oper t y
Sub set BackGr oundCol or ( col As I nt )
col BackGr ound = col
pnl Backgr ound. Col or = col BackGr ound
End Sub

Sub get BackGr oundCol or As I nt
Ret ur n col BackGr ound
End Sub

The code in the main module.
whl Cust om. BackGr oundCol or = Col or s. Gr een

When you write whl Cust om. the different properties will be displayed.



As a reminder, a comment line added before the Sub declaration will be displayed in the inline help.
' Get s or set s t he Backgr oundCol or pr oper t y
Sub set BackGr oundCol or ( col As I nt )
11 Class modules 164 Basic4Android User's Guide
The second color property is the ShadowColor property.



default color : black new color : dark gray

The code in the class module :
' Get s or set s t he ShadowCol or pr oper t y
Sub set ShadowCol or ( col As I nt )
col Shadow = col
pnl Mai n. Col or = col Shadow
l bl Ti t l e. Col or = col Shadow
TopBackgr ound
Bot t omBackGr ound
End Sub

Sub get ShadowCol or As I nt
Ret ur n col Shadow
End Sub

The code in the main module.
whl Cust om. ShadowCol or = Col or s. Dar kGr ay

The code to set the colors of the top and the bottom panel has been moved to two separate routines
TopBackgr ound and Bot t omBackGr ound. This code was previously in the Activity_Create routine.

Pr i vat e Sub TopBackgr ound
Di mgdw As Gr adi ent Dr awabl e
Di mcol s( 2) As I nt
col s( 0) = col Shadow
col s( 1) = Col or s. Tr anspar ent
gdw. I ni t i al i ze( "TOP_BOTTOM", col s)
gdw. Cor ner Radi us = 0
pnl Top. Backgr ound = gdw
Di mcvs1 As Canvas
cvs1. I ni t i al i ze( pnl Top) ' i ni t i al i ze a canvas and dr aw t he l i ne on t he bot t om
cvs1. Dr awLi ne( l i neWi dt h, pnl Top. Hei ght - l i neWi dt h / 2, Wi dt h - l i neWi dt h,
pnl Top. Hei ght - l i neWi dt h / 2, col Wi ndowLi ne, l i neWi dt h)
End Sub

The Bot t omBackGr ound routine is similar to TopBackgr ound.

11 Class modules 165 Basic4Android User's Guide
The WindowColor property.



The code in the class module :
' Get s or set s t he ShadowCol or pr oper t y
Sub set Wi ndowCol or ( col As I nt )
col Wi ndowLi ne = col

' get t he col or component s
Di mr es( 4) As I nt
r es( 0) = Bi t . Unsi gnedShi f t Ri ght ( Bi t . AND( col Wi ndowLi ne, 0xf f 000000) , 24) '
al pha
r es( 1) = Bi t . Unsi gnedShi f t Ri ght ( Bi t . AND( col Wi ndowLi ne, 0xf f 0000) , 16) ' r ed
r es( 2) = Bi t . Unsi gnedShi f t Ri ght ( Bi t . AND( col Wi ndowLi ne, 0xf f 00) , 8) ' gr een
r es( 3) = Bi t . AND( col Wi ndowLi ne, 0xf f ) ' bl ue
' set s t he al pha val ue t o 96
col Wi ndow = Col or s. ARGB( 96, r es( 1) , r es( 2) , r es( 3) )

TopBackgr ound
Bot t omBackGr ound
pnl Mi ddl e. Col or = col Wi ndow
End Sub

In this routine we get the aplha, red, blue and green components from the col Wi ndowLi ne color and
then set the alpha value to 96 for col Wi ndow.

Sub get Wi ndowCol or As I nt
Ret ur n col Wi ndowLi ne
End Sub

The code in the main module.
whl Cust om. Wi ndowCol or = Col or s. Bl ue





11 Class modules 166 Basic4Android User's Guide
The LabelTextColor property.



The code in the class module :
' Get s or set s t he Label Text Col or pr oper t y
Sub set Label Text Col or ( col As I nt )
col Label Text Col or = col

Di mi As I nt

For i = 0 To scvWheel . Panel . Number Of Vi ews - 1
Di ml bl As Label
l bl = scvWheel . Panel . Get Vi ew( i ) ' get t he Label f r omt he scr ol l Vi ew
l bl . Text Col or = col Label Text Col or ' set t he new col or
Next
End Sub

In this routine we get each Label from the Scrollview and set it's TextColor property to the new
color.

Sub get Label Text Col or As I nt
Ret ur n col Label Text Col or
End Sub

The code in the main module.
whl Cust om. Label Text Col or = Col or s. Red


11 Class modules 167 Basic4Android User's Guide
11.3.5 A more advanced example

A more advanced Wheel Class can be found in on Forum here ClsWheel.
With several predefined wheels :
DATE a date input : year / month / day
A default value can be defined or Now, the current date.
The returned value has the current DateFormat.
TIME_HM a time input : hour / minute
A default value can be defined or Now, the current time.
The returned value has the current TimeFormat.
TIME_HMS a time input : hour / minute / second
A default value can be defined or Now, the current time.
The returned value has the current TimeFormat.
DATE_TIME a date +time input : year / month / day / hour / minute
A default value can be defined or Now, the current date and time.
The returned value has the current DateFormat and TimeFormat.
CUSTOM a custom input with user defined input values.
The number of side by side wheels is user defined (max. 5 wheels).
A default value can be defined.
A specific separation character can be defined, a blanc character is default.



TIME_HMS CUSTOM a custom input
with user defined input values.
The number of side by side wheels is user defined (max. 5 wheels).
A default value can be defined.
A specific separation character can be defined, a blanc character is default. CUSTOM


11 Class modules 168 Basic4Android User's Guide
11.4 Second example LimitBar

The second example is a LimitBar.

The source code is in the Classes\ClsLimitBar1 folder.

The LimitBar looks like this:

Two cursors allow to define two limits.

In the demo program we add two labels one on each side to display the two limit values.



We'll use two panels :
l t bPanel Back the background with the background color and the dark 'background' line.

l t bPanel Fr ont the foreground, transparent with the 'foreground' line and the two cursors.


and two canvases :
cvsPanel Back to draw the background line onto l t bPanel Back.
cvsPanel Fr ont to draw the foreground line and the cursors onto l t bPanel Fr ont .

First we declare several objects and variables in Sub Cl ass_Gl obal s :

Sub Cl ass_Gl obal s
Pr i vat e Cal l back As Obj ect ' cal l i ng modul e
Pr i vat e l t bPanel Back As Panel ' t he backgr ound panel
Pr i vat e l t bPanel Fr ont As Panel ' t he f or egr ound panel
Pr i vat e cvsPanel Back As Canvas ' t he backgr ound canvas
Pr i vat e cvsPanel Fr ont As Canvas ' t he f or egr ound canvas
Pr i vat e r ect Panel Fr ont As Rect ' a r ect angl e f or t he f or egr ound canvas

Pr i vat e BackLi neCol or As I nt ' col or f or t he backgr ound l i ne
BackLi neCol or = Col or s. Bl ack
Pr i vat e Fr ont Li neCol or As I nt ' col or f or t he f or egr ound l i ne
Fr ont Li neCol or = Col or s. RGB( 51, 181, 229)
Pr i vat e Li mi t Sl i der Col or As I nt ' col or f or t he cur sor s
Li mi t Sl i der Col or = Col or s. ARGB( 180, 51, 181, 229)
Pr i vat e Mar gi n = 15di p As Fl oat ' l ef t and r i ght mar gi ns f or t he l i ne
Pr i vat e x0, y0, x1 As I nt ' val ues used i nt er nal y
Pr i vat e MaxVal = 100 As I nt ' val ue of t he Max pr oper t y
Pr i vat e Scal e As Doubl e ' scal e bet ween posi t i on val ue and pi xel s
Pr i vat e cLi mi t Lef t As I nt ' val ue of t he l ef t l i mi t
Pr i vat e cLi mi t Ri ght As I nt ' val ue of t he r i ght l i mi t
Pr i vat e Posi t i onPi xel s( 2) As I nt ' l ef t and r i ght posi t i ons i n pi xel s
' 0 = l ef t 1 = r i ght
Pr i vat e PosI ndex As I nt ' cur r ent i ndex of t he posi t i on
Pr i vat e Event Name As St r i ng ' event name
Pr i vat e Pat hs( 2) As Pat h ' t wo pat hs f or t he cur sor shape
End Sub
11 Class modules 169 Basic4Android User's Guide
Then we need the routine to initialize the LimitBar :

The code is self explanatory.

' I ni t i al i zes t he obj ect .
' Cal l backModul e = cal l i ng modul e
' Par ent = par ent vi ew, t he Act i vi t y or a Panel
' cEvent Name = event name used i n t he cal l i ng modul e
' cLef t , cRi ght , cWi dt h, cRi ght = posi t i on and di mensi ons pr oper t i es of t he
Li mi t Bar
' cCol or = backgr ound col or of t he Li mi t Bar
' cRadi us = cor ner r adi us of t he Li mi t Bar
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , Par ent As Act i vi t y, cEvent Name
As St r i ng, cLef t As I nt , cTop As I nt , cWi dt h As I nt , cHei ght As I nt , cCol or As
I nt , cRadi us As I nt )
' set i nt er nal var i abl es
Cal l back = Cal l backModul e
Event Name = cEvent Name

cHei ght = Max( cHei ght , 30di p) ' l i mi t s t he hei ght t o mi n 30di p
cRadi us = Mi n( cRadi us, cHei ght / 2) ' l i mi t s t he max r adi us t o hal f t he hei ght

' i ni t i al i ze t he backgr ound panel and add i t ont o t he par ent vi ew
l t bPanel Back. I ni t i al i ze( "")
Par ent . AddVi ew( l t bPanel Back, cLef t , cTop, cWi dt h, cHei ght )
' i ni t i al i ze and set t he Col or Dr awabl e f or t he backgr ound panel
Di mcdw As Col or Dr awabl e
cdw. I ni t i al i ze( cCol or , cRadi us)
l t bPanel Back. Backgr ound = cdw

' i ni t i al i ze t he f or egr ound panel and add i t ont o t he par ent vi ew
l t bPanel Fr ont . I ni t i al i ze( "l t bPanel Fr ont ")
Par ent . AddVi ew( l t bPanel Fr ont , cLef t , cTop, cWi dt h, cHei ght )
' i ni t i al i ze t he f or egr ound panel r ect angl e used t o er ase l t bPanel Fr ont
r ect Panel Fr ont . I ni t i al i ze( 0, 0, l t bPanel Fr ont . Wi dt h, l t bPanel Fr ont . Hei ght )
l t bPanel Fr ont . Br i ngToFr ont

' set l ocal var i abl es
x0 = Mar gi n
x1 = l t bPanel Back. Wi dt h - Mar gi n
y0 = 6di p
set Max( 100)

' i ni t i al i ze t he backgr ound canvas and dr aw t he backgr ound l i ne
cvsPanel Back. I ni t i al i ze( l t bPanel Back)
cvsPanel Back. Dr awLi ne( x0, y0, x1, y0, BackLi neCol or , 2)
l t bPanel Back. I nval i dat e

' i ni t i al i ze t he f or egr ound canvas
cvsPanel Fr ont . I ni t i al i ze( l t bPanel Fr ont )

' set t he l ef t cur sor par amet er s and dr aw i t
PosI ndex = 0
Posi t i onPi xel s( 0) = x0
Dr awPos( x0, 0)

' set t he r i ght cur sor par amet er s and dr aw i t
PosI ndex = 1
Posi t i onPi xel s( 1) = x1
Dr awPos( x1, 0)
End Sub

11 Class modules 170 Basic4Android User's Guide
The drawing routine for the cursors and the foreground line :

We :
Erase the whole panel by drawing a transparent rectangle.
Set the current position to the active cursor Posi t i onPi xel s( PosI ndex) = x
PosI ndex is the index of the current cursor.
Define both cursors according to the current position.
The cursor shapes are defined with two Paths.
Draw the cursors.
Draw the foreground line.
If I f Mode = 1 then we highlight the active cursor.

Pr i vat e Sub Dr awPos( x As I nt , Mode As I nt )
' dr aw a t r anspar ent r ect angl e t o er ase t he f or egr ound panel
cvsPanel Fr ont . Dr awRect ( r ect Panel Fr ont , Col or s. Tr anspar ent , Tr ue, 1)

' set t he cur r ent cur sor posi t i on
Posi t i onPi xel s( PosI ndex) = x

' def i ne t he l ef t cur sor pat h accor di ng t o i t s cur r ent posi t i on
Pat hs( 0) . I ni t i al i ze( Posi t i onPi xel s( 0) , y0)
Pat hs( 0) . Li neTo( Posi t i onPi xel s( 0) , y0 + 22di p)
Pat hs( 0) . Li neTo( Posi t i onPi xel s( 0) - 12di p, y0 + 22di p)
Pat hs( 0) . Li neTo( Posi t i onPi xel s( 0) - 12di p, y0 + 8di p)
Pat hs( 0) . Li neTo( Posi t i onPi xel s( 0) , y0)

' def i ne t he r i ght cur sor pat h accor di ng t o i t s cur r ent posi t i on
Pat hs( 1) . I ni t i al i ze( Posi t i onPi xel s( 1) , y0)
Pat hs( 1) . Li neTo( Posi t i onPi xel s( 1) , y0 + 22di p)
Pat hs( 1) . Li neTo( Posi t i onPi xel s( 1) + 12di p, y0 + 22di p)
Pat hs( 1) . Li neTo( Posi t i onPi xel s( 1) + 12di p, y0 + 8di p)
Pat hs( 1) . Li neTo( Posi t i onPi xel s( 1) , y0)

' dr aw t he t wo cur sor s and t he f or egr ound l i ne
cvsPanel Fr ont . Dr awPat h( Pat hs( 0) , Li mi t Sl i der Col or , Tr ue, 1)
cvsPanel Fr ont . Dr awPat h( Pat hs( 1) , Li mi t Sl i der Col or , Tr ue, 1)
cvsPanel Fr ont . Dr awLi ne( Posi t i onPi xel s( 0) , y0, Posi t i onPi xel s( 1) , y0, _
Fr ont Li neCol or , 3di p)
' i f Mode = 1 dr aw t he cur r ent cur sor wi t h t he Fr ont Li neCol or ( hi ghl i ght ed)
I f Mode = 1 Then
cvsPanel Fr ont . Dr awPat h( Pat hs( PosI ndex) , Fr ont Li neCol or , Tr ue, 1)
End I f
l t bPanel Fr ont . I nval i dat e ' updat e t he f or egr ound panel
End Sub



11 Class modules 171 Basic4Android User's Guide
To detect cursor moves we use the touch event of the foreground panel :

Pr i vat e Sub l t bPanel Fr ont _Touch ( Act i on As I nt , X As Fl oat , Y As Fl oat )
' check i f t he cur sor i s out si des t he l i mi t s
X = Max( x0, X)
X = Mi n( x1, X)

' sel ect t he Act i on t ype
Sel ect Act i on
Case 0 ' DOWN
I f X < Abs( Posi t i onPi xel s( 0) + Posi t i onPi xel s( 1) ) / 2 Then
' i f X i s cl oser t o t he l ef t cur sor we choose i t
PosI ndex = 0
El se
' ot her wi se we choose t he r i ght cur sor
PosI ndex = 1
End I f
Dr awPos( X, 1) ' we dr aw t he cur r ent cur sor hi ghl i ght ed

Case 2 ' MOVE
Dr awPos( X, 1) ' we dr aw t he cur r ent cur sor hi ghl i ght ed

Case 1 ' UP
Dr awPos( X, 0) ' we dr aw t he cur r ent cur sor not hi ghl i ght ed
End Sel ect

' we cal cul at e t he cur r ent l i mi t val ue f r omt he X posi t i on i n pi xel s
I f PosI ndex = 0 Then
cLi mi t Lef t = Fl oor ( ( X - x0) / Scal e + . 5)
El se
cLi mi t Ri ght = Fl oor ( ( X - x0) / Scal e + . 5)
End I f

' when Act i on i s UP check i f cLi mi t Lef t > cLi mi t Ri ght
' i f yes we i nver t t he l i mi t val ues and r edr aw t he cur sor s
I f Act i on = 1 AND cLi mi t Lef t > cLi mi t Ri ght Then
Di mval As I nt
val = cLi mi t Lef t
cLi mi t Lef t = cLi mi t Ri ght
cLi mi t Ri ght = val
PosI ndex = 0
X = cLi mi t Lef t * Scal e + x0
Dr awPos( X, 0)
PosI ndex = 1
X = cLi mi t Ri ght * Scal e + x0
Dr awPos( X, 0)
End I f

' i f a cal l back r out i ne exi st s i n t he cal l i ng modul e we cal l i t
I f SubExi st s( Cal l back, Event Name & "_Val uesChanged") Then
Cal l Sub3( Cal l back, Event Name & "_Val uesChanged", cLi mi t Lef t , cLi mi t Ri ght )
End I f
End Sub


11 Class modules 172 Basic4Android User's Guide
Finaly we add a few properties :
To add properties see more details in Chapter 10.5 Add properties to a class.

The Max property :
' get s or set s t he max val ue
Sub set Max( cMax As I nt )
MaxVal = cMax
Scal e = ( x1 - x0) / MaxVal
End Sub

Sub get Max As I nt
Ret ur n MaxVal
End Sub

The LimitLeft property :
' get s or set s t he l ef t l i mi t
Sub set Li mi t Lef t ( Pos As I nt )
' i f Pos i s l ower t han 0 set cLi mi t Lef t t o 0
cLi mi t Lef t = Max( 0, Pos)
PosI ndex = 0
Dr awPos( x0 + cLi mi t Lef t * Scal e, 0)
End Sub

Sub get Li mi t Lef t As I nt
Ret ur n cLi mi t Lef t
End Sub

The LimitRight property :
' get s or set s t he r i ght l i mi t
Sub set Li mi t Ri ght ( Pos As I nt )
' i f Pos i s hi gher t han MaxVal set cLi mi t Ri ght t o MaxVal
cLi mi t Ri ght = Mi n( MaxVal , Pos)
PosI ndex = 1
Dr awPos( x0 + cLi mi t Ri ght * Scal e, 0)
End Sub

Sub get Li mi t Ri ght As I nt
Ret ur n cLi mi t Ri ght
End Sub

The Visible property :
' get s or set s t he Vi si bl e pr oper t y
Sub set Vi si bl e( I sVi si bl e As Bool ean)
l t bPanel Back. Vi si bl e = I sVi si bl e
End Sub

Sub get Vi si bl e As Bool ean
Ret ur n l t bPanel Back. Vi si bl e
End Sub

I didn't add more properties to keep the example code 'simple'.
But other properties could easily bee added.

11 Class modules 173 Basic4Android User's Guide
11.5 Add properties to a class

Since Basic4Android version 2.70, properties can be added to classes or custom views.

To add a property you can add one or two specific routines.
The routine names are composed of the property name and a prefix :
get (must be lower case) to read the property.
set (must be lower case) to set the property.

Example for a Max property, we can :
Add only the routine to read the property.
Sub get Max As I nt
Ret ur n MaxVal
End Sub
In this case the property is read only.
Add only the routine to set the property.
Sub set Max( cMax As I nt )
MaxVal = cMax
' some ot her code
End Sub
In this case the property is write only.
Add both routines.
In this case the property is read / write:

A concrete example from the LimitBar class.
Code in the class module :
' get s or set s t he max val ue
Sub set Max( cMax As I nt )
MaxVal = cMax
Scal e = ( x1 - x0) / MaxVal
End Sub

Sub get Max As I nt
Ret ur n MaxVal
End Sub

Code in the calling module, for example :
l t bTest . Max = 100

l t bTest is the name of the LimitBar.


In the calling routine when you write
the name of the custom view followed
by a dot, like l t bTest .

All the properties, public routines and
public variables are displayed in the
inline help.



You find more concrete property example codes in the two class examples :
Wheel Input
LimitBar
11 Class modules 174 Basic4Android User's Guide
11.6 Display a custom view in the Designer

Starting from v2.70, the visual designer supports custom views.

Note that the WYSIWYG designer (which runs on a real device / emulator) shows a place-holder
instead of the custom view.

Adding the custom views with the designer is simpler and allows the developer to build and
maintain the complete UI with the visual designer and designer script.

Custom views with designer support can be implemented as a class or inside a library.

The example below is taken from Erels' tutoriel.
The source is in the Classes \CustomViewDemo folder.

To make a custom view available in the Designer we must add two routines in the class module,
events can also be declared :
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , cEvent Name As St r i ng)

The custom view is defined in the Designer and this routine is needed to get back the calling
module object and the event name from the Designer.

Publ i c Sub Desi gner Cr eat eVi ew( Base As Panel , Lbl As Label , Pr ops As Map)

Three parameters are sent back from the Designer :

A Panel Base is used as a placeholder to show the custom view in the Designer.
This Panel can either be used or not.
The panel properties are defined in the Designer.

A Label Lbl is used to hold all text related properties beeing set in the Designer.
This Label can either be used or not.
The label will not appear unless you explicitely add it.

A Map Pr ops with additional entries.
Currently the only entry is an "activity" key that holds a reference to the parent Activity
object.

Events can be declared at the top of the class code:
If the event routine contains parameters, these must also be declared.
The Event declarations below are used by the Dim and Event Generator.

' Event s decl ar at i on
#Event : Doubl eCl i ck
#Event : Si ngl eCl i ck
#Event : I t emCl i ck( Posi t i on As I nt , Val ue As Obj ect )

' Cl ass modul e
Sub Cl ass_Gl obal s

11 Class modules 175 Basic4Android User's Guide
To add a custom view in the Designer :





Open the Designer and select Add View / CustomView.









The CustomView is added.









Select the CustomView type.







Modify the properties, like for any other
'standard' view.

Name btnDouble as an example.





11 Class modules 176 Basic4Android User's Guide
Right click on the CustomView to display the menu.



It allows you to generate, in the current Activity code, the Dim statement:

Di mbt nDoubl e As Doubl eCl i ckBut t on

and the event routines

Sub bt nDoubl e_Doubl eCl i ck

End Sub

Sub bt nDoubl e_Si ngl eCl i ck

End Sub

Sub bt nDoubl e_I t emCLi ck( Posi t i on As St r i ng, Val ue As Obj ect )

End Sub

for the CustomView.

The event routines are generated according to the declarations in the code.
#Event : Doubl eCl i ck
#Event : Si ngl eCl i ck
#Event : I t emCl i ck( Posi t i on As I nt , Val ue As Obj ect )









11 Class modules 177 Basic4Android User's Guide
11.6.1 Example with the Li mitBar

Another concrete example is shown with the LimitBar class example.

The source code is in the Classes\ClsLimitBar2 folder.

To be able to also add a LimitBar in the code we must modify the I ni t i al i ze routine.
We rename it from I ni t i al i ze to AddVi ew because we need to add a new Initialize routine.
Then we remove the two variables Cal l backModul e and cEvent Name because they will be defined
in the new Initialize routine.

Previous code :
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , Par ent As Act i vi t y, cEvent Name
As St r i ng, cLef t As I nt , cTop As I nt , cWi dt h As I nt , cHei ght As I nt , cCol or As
I nt , cRadi us As I nt )
' set i nt er nal var i abl es
Cal l back = Cal l backModul e
Event Name = cEvent Name

cHei ght = Max( cHei ght , 30di p) ' l i mi t s t he hei ght t o mi n 30di p

New code :
Publ i c Sub AddVi ew( Par ent As Act i vi t y, cLef t As I nt , cTop As I nt , cWi dt h As I nt ,
cHei ght As I nt , cCol or As I nt , cRadi us As I nt )
cHei ght = Max( cHei ght , 30di p) ' l i mi t s t he hei ght t o mi n 30di p

Then we :

- Add the new Initialize routine :
' I ni t i al i zes t he obj ect . You can add par amet er s t o t hi s met hod i f needed.
Publ i c Sub I ni t i al i ze( Cal l backModul e As Obj ect , cEvent Name As St r i ng)
Cal l back = Cal l backModul e
Event Name = cEvent Name
End Sub

- Add the DesignerCreateView routine :
Publ i c Sub Desi gner Cr eat eVi ew( Base As Panel , Lbl As Label , Pr ops As Map)
' we use t he Base panel as t he backgr ound panel
l t bPanel Back = Base

' i ni t i al i ze t he f or egr ound panel and add i t ont o t he backgr ound panel
l t bPanel Fr ont . I ni t i al i ze( "l t bPanel Fr ont ")
l t bPanel Back. AddVi ew( l t bPanel Fr ont , 0, 0, l t bPanel Back. Wi dt h, _
l t bPanel Back. Hei ght )
' i ni t i al i ze t he f or egr ound panel r ect angl e used t o er ase l t bPanel Fr ont
r ect Panel Fr ont . I ni t i al i ze( 0, 0, l t bPanel Fr ont . Wi dt h, l t bPanel Fr ont . Hei ght )
l t bPanel Fr ont . Br i ngToFr ont

I ni t
End Sub

There is a common part for both Initialize routines, this has been set into the separate I ni t routine.

Add the Event declaration on top of the module code :

' Event s decl ar at i on
#Event : Val uesChanged

11 Class modules 178 Basic4Android User's Guide
We add the CustomView in the Designer to the existing layout file, shown in the Abstract Designer.





Adjust it to fit between the two labels.



Set the Custom Type property to LimitBar.




Set the Name property to ltbTest.




Set the Color property to Blue.







11 Class modules 179 Basic4Android User's Guide
11.7 Compi le a class i nto a Library

Starting from Basic4android v2.50 you can compile your project, or part of it to a regular library.

Why should I compile a library?
Break large projects into several smaller (more maintainable) projects.
Build reusable components and use them from any number of projects.
Share components with other developers without sharing the source code.
Create different versions of your application (free, pro...) by referencing the same "core"
library.
The output of library compilation are two files: a jar file with the compiled code and a xml file that
includes the metadata that is required by the IDE.

These two files are automatically saved in the additional libraries folders.

Compiling to a library is quite simple. Under Project menu there is a new compile option -
"Compile To Library (Alt +5)". When you choose this option all the modules except of the main
activity are compiled into a library.



You can exclude other modules as well with the ExcludeFromLibrary attribute (see this tutorial for
more information about attributes).

The main activity and the other excluded modules can be used to test the library.

You can reference the library from other projects and access the same functionality as in the
original project.

11 Class modules 180 Basic4Android User's Guide
Library specific attributes

The following attributes are specific for library compilation:

Project attributes (placed in the main activity):
LibraryVersion - A number that represents the library version. This number will appear next to the
library name in the libraries list.
LibraryAuthor - The library author. This value is added to the library xml file.
LibraryName (B4A v2.70) - The compiled library name. Sets the library name instead of showing
the save dialog.

All modules:
ExcludeFromLibrary - Whether to exclude this module during library compilation. Values: True or
False. Note that the Main activity is always excluded.

Classes:
Event - Adds an event to the list of events. This attribute can be used multiple times. Note that the
events list only affects the IDE events autocompletion feature.

Example :
In the Main module
#Regi on Pr oj ect At t r i but es
#Appl i cat i onLabel : Li mi t Bar Demo2
#Ver si onCode: 1
#Ver si onName:
' Suppor t edOr i ent at i ons possi bl e val ues: unspeci f i ed, l andscape or por t r ai t .
#Suppor t edOr i ent at i ons: unspeci f i ed
#CanI nst al l ToExt er nal St or age: Fal se

#Li br ar yVer si on: 1. 0
#Li br ar yName: Li mi t Bar
#Li br ar yAut hor : Kl aus Chr i st l
#End Regi on

In a code module :
#Excl udeFr omLi br ar y

Notes

- You should right click on the libraries list and choose Refresh after a library update.
- CallSub / CallSubDelayed - The first parameter for these keywords is a reference to the target
module. When working with modules that reside in a library you should pass the module reference
and not the module name as string (this is the better way to reference all modules in all cases).
- Code obfuscation - Libraries can be obfuscated during library compilation. Strings will not be
obfuscated in this mode.
- Services that host home screen widgets cannot be compiled into a library.

11 Class modules 181 Basic4Android User's Guide
11.7.1 Example with the Li mitBar class example

We take the LimtBarDemo2 program to show the principle.
Source code in the Classes\ClsLimtBar2 folder.

In the Project Attributes Region in the Main module we add following new attributes :

#Regi on Pr oj ect At t r i but es
#Appl i cat i onLabel : Li mi t Bar Demo2
#Ver si onCode: 1
#Ver si onName:
' Suppor t edOr i ent at i ons possi bl e val ues: unspeci f i ed, l andscape or por t r ai t .
#Suppor t edOr i ent at i ons: unspeci f i ed
#CanI nst al l ToExt er nal St or age: Fal se

#Li br ar yVer si on: 1. 0
#Li br ar yName: Li mi t Bar
#Li br ar yAut hor : Kl aus Chr i st l
#End Regi on




Then click on to compile the library.



A screen similar to this one is displayed showing that the library has been sucessfully compiled.



Two files are automaticaly added in the additional library folder.
In our example :
LimitBar.xml
LimitBar.jar


Right click in the Libs tab and click on Refresh.


The new library is now available.


11 Class modules 182 Basic4Android User's Guide
11.7.2 Using the library i n a program

To use the library we copy the LimtBarDemo2 to another folder and load it.

The resulting source code for this example is in the Classes\LblLimitBar1 folder.

We remove the LimitBar module.
We remove the three Project Attributes.
#Li br ar yVer si on: 1. 0
#Li br ar yName: Li mi t Bar
#Li br ar yAut hor : Kl aus Chr i st l
We check the LimitBar library in the Libs tab

And run the program that's it !

Open the Disigner we find the lbtTest custom view as defined previously.


Adding a LimitBar in the code.

In the example below we add one LimitBar in the Designer and another one in the code.

The source code is in the Classes\LblLimitBar2 folder.

We need to Dim the LimitBars
Di ml t bTest 1, l t bTest 2 As Li mi t Bar

We initialize l t bTest 2 in the code and add it to the parent view (Activity in our example).
l t bTest 2. I ni t i al i ze( Me, "l t bTest 2")
l t bTest 2. AddVi ew( Act i vi t y, 10di p, 100di p, 100%x - 20di p, 30di p, Col or s. Gr een,
5di p)

I ni t i al i ze : Me =CallModule, current module and "l t bTest 2" =EventName

AddVi ew parameters : Parent view, Left, Top, Width, Height, BackgroundColor, CornerRadius

You might also like