Tag Archives: Android

B4A: ABFlicB4A library for Flic buttons

cute-as-a-button-1

You probably have seen these nifty little IoT Flic buttons around. They are a fun and relative cheap BLE button that allows you to do something when the button is clicked, doubleclicked or hold.

I decided to write a wrapper for the Android SDK to use with B4A.

How to use:
1. Install the Flic app from the Google Play.
2. On their developer page, create a new app: you get a key and a secret.
3. Copy the ABFlicB4A library jar and xml to your library folder and select it in B4A

Here is a small video demonstrating the library.  You can the use the full power of B4A to do about, well, everything…

Example usage code:

Sub Process_Globals

End Sub

Sub Globals
   Private flic As ABFlic
   Private Button2 As Button
   Private Button3 As Button
   Private Button4 As Button
   Private Label1 As Label
   Private Button1 As Button

   Private MyFlicID As String

   Private FlicResults As List
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   FlicResults.Initialize
   FlicResults.Add("RESULTACTION_HOLD")
   FlicResults.Add("RESULTACTION_SINGLECLICK")
   FlicResults.Add("RESULTACTION_DOUBLECLICK")
End Sub

Sub Activity_Resume
   ' your key and secret
   flic.Initialize("Flic", "d60d36a0-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "db5c2b3d-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "ABFlicTest")
End Sub

Sub Button1_Click
   flic.ForgetButton(MyFlicID)
End Sub

Sub Button2_Click
   flic.GrabButton
End Sub

Sub Button3_Click
   flic.StartListening
End Sub

Sub Button4_Click
   flic.StopListening
End Sub

Sub flic_Added(buttonID As String, Name As String)
   MyFlicID = buttonID
   Log("Added: " & buttonID)
   Label1.Text = "Added: " & buttonID & CRLF & Label1.Text
End Sub

Sub flic_Clicked(buttonID As String, wasQueued As Boolean, timeDiff As Int)
   MyFlicID = buttonID
   Log("Clicked: " & buttonID)
   Label1.Text = "Clicked: " & buttonID & CRLF & Label1.Text
End Sub

Sub flic_DoubleClicked(buttonID As String, wasQueued As Boolean, timeDiff As Int)
   MyFlicID = buttonID
   Log("DoubleClicked: " & buttonID)
   Label1.Text = "DoubleClicked: " & buttonID & CRLF & Label1.Text
End Sub

Sub flic_Holded(buttonID As String, wasQueued As Boolean, timeDiff As Int)
   MyFlicID = buttonID
   Log("Holded: " & buttonID)
   Label1.Text = "Holded: " & buttonID & CRLF & Label1.Text
End Sub

Sub flic_Removed(buttonID As String)
   MyFlicID = ""
   Log("Removed: " & buttonID)
   Label1.Text = "Removed: " & buttonID & CRLF & Label1.Text
End Sub

Sub flic_Error(err As Int)
   Log("Error: " & err)
   Label1.Text = "Error: " & err & CRLF & Label1.Text
End Sub

I’m currently working on a Desktop/Raspberry Pi version of this library, which I will share in the B4J forum later.

The library can be found at the B4A forum.

Happy programming!

Alwaysbusy


QuiQRun! launched

Barcelona Skin

Barcelona Skin


QuiQRun!, the social, fast barcode scanner and creator!

I’m very happy to release the first version of QuiQRun! for Android! In the next weeks I may do a couple of articles on the blog on how some things are done. (Basic4Android and Java).

I want to thank everyone that did test and translate the app!

Download free version

Please rate QuiQRun! if you like it!

More information and screenshots can be found at http://www.quiqrun.com

Alain


QuiQRun! Localization

QuiQRun! Skin Italia

Skinning QuiQRun!


Hi all,

I’m looking for people who can translate about 150 terms and some short sentences for my new app QuiQRun! If you can help me, send me a mail to alain.bailleul@pandora.be.

I already have English, Dutch, Italian, French, German, Spanish and Portuguese.

What can I offer?

1. The full version of QuiQRun!
2. A skin in QuiQRun! with your favorite colors
3. Full credit in the apps credits screen
4. Eternal gratitude!

How do I use it in B4A?
The translations are stored in a language file, eg. en-us.lng.

They are stored in a predefined format:

{0000};Scanned
{0001};Scan
{0002};Create
{0003};Setting new skin, one moment...
{0004};Tap to get more info!
{0005};This QRCode is expired!
...

In Basic4Android, It checks if it has a translation, if not it uses the default you put in the GetString function. Here is the snippet I use:

Sub Process_Globals
    Public LangStrings As Map
    Public BOM As Int = 65279 ' Byte Order Mark for Windows UTF-8 files
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim R As Reflector
    R.Target = R.RunStaticMethod("java.util.Locale", "getDefault", Null, Null)
    Dim tmpLang As String = R.RunMethod("getLanguage")
    Select Case tmpLang
        Case "nl"
            LoadLanguageFile("nl-be.LNG")
        Case "fr"
            LoadLanguageFile("fr-fr.LNG")           
        Case "it"
            LoadLanguageFile("it-it.LNG")
        Case "es"
            LoadLanguageFile("es-es.LNG")
        Case "de"
            LoadLanguageFile("de-de.LNG")
        Case Else
            LoadLanguageFile("en-us.LNG")
    End Select

    ' using it:
    ToastMessageShow(GetString("{0003}","Setting new skin, one moment..."), true)
End Sub

Public Sub LoadLanguageFile(setLanguageFile as String)
    LangStrings.Initialize
    
    If File.Exists(File.DirAssets, setLanguageFile) Then
        Dim txtR As TextReader
        txtR.Initialize(File.OpenInput(File.DirAssets, setLanguageFile))
        Dim line As String
        line = txtR.ReadLine
        Do While line  Null
            line = line.Replace(Chr(BOM), "")
            LangStrings.Put(line.SubString2(0,6), line.SubString(7))
            line = txtR.ReadLine
        Loop
        txtR.Close
    End If   
    
End Sub

Public Sub GetString(iCode As String, iDefault As String) As String
    If LangStrings.ContainsKey(iCode) Then
        Return LangStrings.Get(iCode)
    Else
        Return iDefault
    End If
End Sub

Thanks!

Alwaysbusy


Basic4Android v3.20 is released!

B4A Anchors

B4A Anchors


Again, another great update of B4A! Erel has continued to improve the visual designer, this time with a great new feature you may know from typical PC languages: Anchors. (Xojo/Realbasic users may recognize them as the LockLeft, LockTop, LockRight and LockBottom properties)

Anchors allow you to define a constant distance between the view and one or more of the parent bounds. By using anchors, you can design screens and B4A will ‘stretch’ them according to the device size. This is different than scalling because it takes more relative positions into account.

Here is a short video demonstrating the anchore feature:

Important designer improvements:
* Copy & paste – work both inside the layout or between different layouts.
* Undo / redo feature.
* The views are organized in a tree for easier navigation.
* AutoScaleAll keyword now works with all variants, not just the “standard” variant.
* Colors fields can be copied and the colors values can be pasted or directly typed.
* Designer script find / replace dialog.
* The grid is saved in the layout file.
* Landscape / Portrait designer keywords to test the current orientation.
* UI Cloud threshold reduced to 10 seconds.

Other great new features and improvements:
* #AdditionalRes attribute
* Sync button in the Files tab – Syncs the project files with the Files folder.
* Modules added to the Find Sub / Module tool (Ctrl + E).
* Tabs order in the IDE is preserved.
* Modules files that were not modified will not be saved thus preserving the correct time stamp.
* DateTime.SetTimeZone now accepts a Double instead of Int.
* Shortcuts: F11 – Restart (rapid debugger), F2 in the designer connects to the device.
* JavaObject v1.00 – new RunMethodJO / GetFieldJO methods.
* Bug fixes and other minor improvements.

So head to the B4A website to check it out and if you don’t have a license yet (hard to believe because it is worth every penny), now is a great time to get one!

Alwaysbusy!


Basic4Android: A first look at ABPlay, a game engine library

ABPlay Screenshot

ABPlay Screenshot

It has been a while since I’ve written a new article on this blog because it have been busy months both at work and in my personal life. One of the things I wanted to do was writing an easy to use Game Engine for B4A. I have written the ABPhysics engine in the past and recently Informatix pointed out I had started another engine (ABGameEngine) before that. Development on ABGameEngine was stopped early for several reasons: time was one of them, but also because several other developers were working on an engine themselves. It seemed a little bit pointless to continue.

However, the other engines were not further developed either. Until recently Erel came up with the GameView. This is an excellent View that will cover the needs of a lot of beginning programmers. I definitely would like to urge starting game developers to take a look at this. Registered users of B4A can download the GameView lib from here.

But still, I wanted something more. I looked at ABgameEngine again, as it had some great ideas like layers, animated sprites, gamepads etc. But it was also very old code and not written very well. And it crashed all the time 🙂

I decided to restart from scratch a couple of weeks ago. Some weekends and evenings later ABPlay was born! And with a lot of goodies!

Here is a small demo video of what I got so far. it demonstrates the following:

1. Layers
     (Layer 1) the moving background with the Odies as animated sprites
     (Layer 2) the black foreground layer with a weird dancing creature that passes now and then
2. Animated sprites, not bound to a layer
     (our hero Garfield is back!)
3. A sprite can have different animations.
     (like one for standing, one for walking, one for fighting, etc)
4. A sprite can have different predefined 'Walks'
     (A walk can be build like you would build a path. It's a sequence of lines, bezier curves, wait periods etc. It's like a simple flash movie)
5. Gamepad controls
     (the 'joystick' pad on the left)
     (the 'action' pad on the right)
     (the 'direction' pad as an alternative to the joystick, not shown in this video)
6. In the demo I cannot demonstrate it with a mouse, but it is completely multi touch
     (You can control Garfield AND press the Action button X AND do a swipe anywhere at the same time)

But let’s have a look (beware this is running on the Emulator. On a real device it is much smoother):

I’m actually very pleased with the result. The graphics and handling is very smooth.
Above all, it’s still very easy to program. Here is the whole code for the demo app:

#Region  Project Attributes
	#ApplicationLabel: ABPlayTest
	#VersionCode: 1
	#VersionName:
	'SupportedOrientations possible values: unspecified, landscape or portrait.
	#SupportedOrientations: landscape
	#CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
	#FullScreen: true
	#IncludeTitle: false
#End Region

Sub Process_Globals

End Sub

Sub Globals
	Dim myPlay As ABPlay
	' the panel that will hold the ABPlay
	Dim myPanel As Panel

	' a background and foregroud layer
	Dim bgLayer As ABLayer
	Dim fgLayer As ABLayer

	' some colors to show the multi touch points in the demo
	Dim myColors() As Int = Array As Int(Colors.Red, Colors.Green, Colors.Blue, Colors.Cyan, Colors.Yellow, Colors.Gray, Colors.White, Colors.Magenta, Colors.LightGray, Colors.DarkGray)

	' our hero
	Dim Hero As ABSprite
	' our enemies
	Dim Enemies As List

	' param to set the set the speed
	Dim Speed As Float = 0.2

	' some variables to hold the current state of the hero
	Dim currentAction As String
	Dim currentDirection As String
	Dim currentIsStanding As Boolean
End Sub

Sub Activity_Create(FirstTime As Boolean)
	' initialize ABPlay with myPanel
	myPanel.Initialize("")
	Activity.AddView(myPanel, 0,0,100%x,100%y)
	myPlay.Initialize(myPanel, "myPlay")

	'////////////// BEGIN loading sprite sequences
	' Load Sprite Sequences
	myPlay.LoadSpriteSequence("GarStandingLeft",LoadBitmap(File.DirAssets, "garleftstill.png"),6, 1, 1000)
	myPlay.LoadSpriteSequence("GarStandingLeft",LoadBitmap(File.DirAssets, "garleftstill.png"),6, 1, 1000)
	myPlay.LoadSpriteSequence("GarStandingRight",LoadBitmap(File.DirAssets, "garrightstill.png"),6, 1, 1000)
	myPlay.LoadSpriteSequence("GarWalkingLeft",LoadBitmap(File.DirAssets, "garleft.png"),8, 1, 1000)
	myPlay.LoadSpriteSequence("GarWalkingRight",LoadBitmap(File.DirAssets, "garright.png"),8, 1, 1000)
	myPlay.LoadSpriteSequence("GarStandingLeftFight",LoadBitmap(File.DirAssets, "garleftstillfight.png"),2, 1, 250)
	myPlay.LoadSpriteSequence("GarStandingRightFight",LoadBitmap(File.DirAssets, "garrightstillfight.png"),2, 1, 250)
	myPlay.LoadSpriteSequence("GarWalkingLeftFight",LoadBitmap(File.DirAssets, "garleftfight.png"),7, 1, 1000)
	myPlay.LoadSpriteSequence("GarWalkingRightFight",LoadBitmap(File.DirAssets, "garrightfight.png"),7, 1, 1000)
	' and the ones for Odie
	myPlay.LoadSpriteSequence("OdieStandingLeft", LoadBitmap(File.DirAssets, "odieleftstill.png"),7,1,Rnd(800,1200))
	myPlay.LoadSpriteSequence("OdieStandingRight", LoadBitmap(File.DirAssets, "odierightstill.png"),7,1,Rnd(800,1200))
	myPlay.LoadSpriteSequence("OdieWalkingLeft", LoadBitmap(File.DirAssets, "odieleft.png"),5,1,Rnd(800,1200))
	myPlay.LoadSpriteSequence("OdieWalkingRight", LoadBitmap(File.DirAssets, "odieright.png"),5,1,Rnd(800,1200))
	' and the one for the creature
	myPlay.LoadSpriteSequence("CreaturePassToRight", LoadBitmap(File.DirAssets, "creature.png"), 3, 4, 1200)
	'////////////// END loading sprite sequences

	'////////////// BEGIN building the Hero Garfield
	' initialize the hero
	Hero.Initialize("Hero", 50%x, 50%y)
	' add sprite sequences
	Hero.AddSpriteSequence("GarStandingLeft")
	Hero.AddSpriteSequence("GarStandingRight")
	Hero.AddSpriteSequence("GarWalkingLeft")
	Hero.AddSpriteSequence("GarWalkingRight")
	Hero.AddSpriteSequence("GarStandingLeftFight")
	Hero.AddSpriteSequence("GarStandingRightFight")
	Hero.AddSpriteSequence("GarWalkingLeftFight")
	Hero.AddSpriteSequence("GarWalkingRightFight")
	Hero.StartSpriteSequence("GarStandingLeft", True)
	currentDirection="LEFT"
	'//////////////  END building the Hero Garfield

	'////////////// BEGIN building the background layer with Odies
	' initalize a background layer
	bgLayer.Initialize("background", 0,0)
	bgLayer.SetBackground(LoadBitmap(File.DirAssets, "bga.jpg"), 1.0)
	myPlay.AddLayer(bgLayer)

	' initialize some enemies
	Enemies.Initialize
	Dim a As Int
	For a = 1 To 10
		Dim Odie As ABSprite

		' initialize an Odie with some animation sequences
		Odie.Initialize("Odie" & a, Rnd(10%x,90%x), Rnd(10%y, 90%y))
		' add multiple sprite sequences
		Odie.AddSpriteSequences(Array As String("OdieStandingLeft","OdieStandingRight","OdieWalkingLeft","OdieWalkingRight"))

		' create a random walk to the right
		Dim WalkRight As ABSpriteWalk
		WalkRight.Initialize("ToTheRight", True)
		Dim newX As Int = Odie.x+Rnd(20%x, 80%x)
		WalkRight.AddLine("OdieWalkingRight",Odie.x, Odie.y, newX, Odie.y, Rnd(90,100))
		WalkRight.AddWait("OdieStandingRight",newX, Odie.y, Rnd(10,50))
		WalkRight.AddLine("OdieWalkingLeft",newX, Odie.y, Odie.x, Odie.y, Rnd(90,100))
		WalkRight.AddWait("OdieStandingLeft",Odie.x, Odie.y, Rnd(10,50))
		Odie.AddWalk(WalkRight)

		' create a random walk to the left
		Dim WalkLeft As ABSpriteWalk
		WalkLeft.Initialize("ToTheLeft", True)
		Dim newX As Int = Odie.x-Rnd(20%x, 80%x)
		WalkLeft.AddLine("OdieWalkingLeft",Odie.x, Odie.y, newX, Odie.y , Rnd(90,100))
		WalkLeft.AddWait("OdieStandingLeft",newX, Odie.y, Rnd(10,50))
		WalkLeft.AddLine("OdieWalkingRight",newX, Odie.y, Odie.x, Odie.y, Rnd(90,100))
		WalkLeft.AddWait("OdieStandingRight",Odie.x, Odie.y, Rnd(10,50))
		Odie.AddWalk(WalkLeft)

		' pick random a walk, left or right
		Dim GoLeft As Int = Rnd(0,2)
		If GoLeft = 0 Then
			Odie.StartWalk("ToTheRight")
		Else
			Odie.StartWalk("ToTheLeft")
		End If
		bgLayer.AddSprite(Odie)
	Next
	'////////////// END building the background layer with Odies

	'////////////// BEGIN building the foreground layer with creature
	' initalize a foreground layer
	Dim fgLayer As ABLayer
	fgLayer.Initialize("foreground", 0,0)
	fgLayer.SetBackground(LoadBitmap(File.DirAssets, "fga.png"), 100%y/400)
	myPlay.AddLayer(fgLayer)

	' and a weird creature...
	Dim creature As ABSprite
	creature.Initialize("creature", -100%x, 100%y-240)
	creature.AddSpriteSequence("CreaturePassToRight")
	' with a walk
	Dim pass As ABSpriteWalk
	pass.Initialize("DanseToTheRight", True)
	pass.AddLine("DansingRight",creature.x, creature.y, 200%x, creature.y, 300)
	creature.AddWalk(pass)
	' and start the walk
	creature.StartWalk("DanseToTheRight")
	' add the creature to the foreground layer
	fgLayer.AddSprite(creature)
	'////////////// END building the foreground layer with creature

	'////////////// BEGIN Add game pads
	' initialize and start a Joystick Gamepad
	myPlay.InitializeJoystickPad(18, 100%y-210, 192, 192 , LoadBitmap(File.DirAssets, "joystick_bg.png"),LoadBitmap(File.DirAssets, "joystick.png"))
	myPlay.ShowJoystickPad(True)	

	' initialize and start a Action Gamepad
	myPlay.InitializeActionPad(100%x-210, 100%y-210, 192, 192 , LoadBitmap(File.DirAssets, "action_active.png"),LoadBitmap(File.DirAssets, "action_inactive.png"),LoadBitmap(File.DirAssets, "action_mask.png"),True, False, True, False)
	myPlay.ShowActionPad(True)
	'////////////// END Add game pads
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
	' NEEDED FOR THE MOMENT TO CATCH THE HOME KEY, RESUME/PAUSE NOT YET SUPPORTED!
	myPlay.StopAndRecycle
	Activity.Finish
End Sub

Sub Activity_KeyPress (KeyCode As Int) As Boolean 'Return True to consume the event
	Select Case KeyCode
		Case KeyCodes.KEYCODE_BACK
			' NEEDED: stop the drawing thread and recycle stuff
			myPlay.StopAndRecycle
			Activity.Finish
			Return True
		Case KeyCodes.KEYCODE_HOME
			Return True
	End Select
End Sub

Sub myPlay_Draw(c As Canvas, State As ABState)
	' the actual drawing, do NOT set a debug stop in here!

	'////////////// BEGIN Calculation stuff
	' calculate hero stuff depending on what buttons we pressed on the gamepad
	currentAction = ""
	If State.UsingActionPad Then
		' go into fight state
		If State.ACTION_X Then
			currentAction = "X"
		End If
		' go back to center
		If State.ACTION_Y Then
			Hero.SetPostition(50%x,50%y)
		End If
	End If

	Dim XMovement As Int
	Dim YMovement As Int
	If State.UsingJoystickPad Then
		XMovement = State.JOYSTICK_X*Speed
		YMovement = State.JOYSTICK_Y*Speed
		' update the hero's position and direction
		If XMovement<0 Then
			currentDirection = "LEFT"
		Else
			currentDirection = "RIGHT"
		End If
		Hero.SetPostition(Hero.x+XMovement, Hero.y+YMovement)
		currentIsStanding = False
	Else
		currentIsStanding = True
	End If

	' set the animation type
	Select Case currentDirection
		Case "LEFT"
			Select Case currentAction
				Case "X"
					If currentIsStanding Then
						Hero.StartSpriteSequence("GarStandingLeftFight", False)
					Else
						Hero.StartSpriteSequence("GarWalkingLeftFight", False)
					End If
				Case Else
					If currentIsStanding Then
						Hero.StartSpriteSequence("GarStandingLeft", False)
					Else
						Hero.StartSpriteSequence("GarWalkingLeft", False)
					End If
			End Select
		Case "RIGHT"
			Select Case currentAction
				Case "X"
					If currentIsStanding Then
						Hero.StartSpriteSequence("GarStandingRightFight", False)
					Else
						Hero.StartSpriteSequence("GarWalkingRightFight", False)
					End If
				Case Else
					If currentIsStanding Then
						Hero.StartSpriteSequence("GarStandingRight", False)
					Else
						Hero.StartSpriteSequence("GarWalkingRight", False)
					End If
			End Select
	End Select	

	' update the hero animation
	Hero.Update

	' move our backgrounds, does not make sense but shows the possibilities
	Dim newX, newY As Int
	Dim newMovementX, newMovementY As Int
	newMovementX=Min(Abs(XMovement),1)
	newMovementY=Min(Abs(YMovement),1)
	If currentIsStanding = False Then
		If currentDirection = "LEFT" Then
			newX = bgLayer.ViewX
			newY = bgLayer.ViewY
			If newX-newMovementX >= 0 Then
				newX = newX-newMovementX
			End If
			If newY-newMovementY >= 0 Then
				newY = newY-newMovementY
			End If
			bgLayer.SetLayerPostion(newX, newY)
		Else
			newX = bgLayer.ViewX
			newY = bgLayer.ViewY
			If newX+newMovementX <= bgLayer.OuterWidth - myPlay.Width Then
				newX = newX+newMovementX
			End If
			If newY+newMovementY <= bgLayer.OuterHeight - myPlay.Height Then
				newY = newY+newMovementY
			End If
			bgLayer.SetLayerPostion(newX, newY)
		End If
	End If

	'////////////// END Calculation stuff

	'////////////// BEGIN Drawing stuff
	'ok, all the calulations are done, let's draw!

	' draw the background layer with all its sprites on it and advance all sprite animations and walks
	myPlay.DrawLayer("background", c)

	Dim a As Int
	' draw the multitouch points that are not on the gamepad, no action here but just to show the possibilities
	For a = 0 To State.touchPoints.Size - 1
		Dim tmpP As ABTouchPoint
		tmpP = State.touchPoints.GetValueAt(a)
		c.DrawCircle(tmpP.X, tmpP.Y, 50dip, myColors(tmpP.id), True, 1dip)
	Next

	' draw the hero
	Hero.Draw(c)

	' draw the foreground layer with all its sprites on it and advance all sprite animations and walks
	myPlay.DrawLayer("foreground", c)
	'////////////// END Drawing stuff

	' NEEDED: very last line of the Draw event. Let ABPlay know it may process touches again!
	myPlay.DrawDone()
End Sub

I’m not there yet, but it’s a good start. It needs a lot more testing and a lot of new features.

Until next time!
Alwaysbusy

Click here to Donation if you like my work


Basic4Android: ABSYNCMenu, making an Actionbar with Submenus. Easy!


ABSYNCMenu.bas is a code module for an Actionbar with submenus completely written in Basic4Android. It’s an easy to use module you can drop into any project and with a couple of lines of code you have your own action bar with submenus!

Note: I’m aware there is an excellent actionbar library from corwin42 called AHActionBar at the B4A website, but as this ABSYNCMenu module is part of the upcoming ABSYNC Genesis tool (more on this tool in a later article!), I wanted to share this module with you.

Let’s get started!

Start a new project and import the attached module ABSYNCMenu.bas.

In the Main Activity we will add all the code needed to create and handle the action bar and menu. I’ll only cover the code needed for the actionbar in this tutorial, not the other ‘normal’ B4A code. There are some excellent tutorials in the B4A forum, check them out.

We define tree panels that are needed to build the ABSYNC Menu in the Sub Globals.
ABS_MainMenuPanel: for the transparent background over the whole activity that makes all the rest of the program darker and unclickable.
ABS_ActionBarPanel: for the the actionbar
ABS_DropdownMenuPanel: for the dropdown menu

Sub Globals
    Dim ABS_MainMenuPanel As Panel
    Dim ABS_ActionBarPanel As Panel
    Dim ABS_DropdownMenuPanel As Panel
End Sub

In the Activity_Create sub we load our initial layout file (.bal) we created in the designer. This may just be an empty form. See the project at the end of the article for more info. Then we call our BuildMenu() function where we define our action bar and menus.

Sub Activity_Create(FirstTime As Boolean)
    ' load the initial layout
    Activity.LoadLayout("1")

    ' call the function to initialize our menu
    BuildMenu
End Sub

Suppose we want to create the following actionbar with submenus:

Notice some menu items need to have an icon and some of them need to be disabled.
I’ll go over every major part in the code of the BuildMenu() function to explain how it works.

Start with the ABSYNC menu definition:

ABSYNCMenu.ABSYNCMenuBegin(ABS_MainMenuPanel, ABS_ActionBarPanel, ABS_DropdownMenuPanel, "ABSYNCMenuEvent", Activity.Width, Activity.Height)

Set some properties, like the colors and height of the action bar:

ABSYNCMenu.ActionBarHeight = 40dip
ABSYNCMenu.ColorActionBar = Colors.ARGB(255,255,0,0)
ABSYNCMenu.ColorActionBarItemEnabled = Colors.ARGB(255,255,255,255)
ABSYNCMenu.ColorActionBarItemDisabled = Colors.ARGB(255,64,64,64)
ABSYNCMenu.ColorMenu = Colors.ARGB(255,255,255,255)
ABSYNCMenu.ColorMenuItemEnabled = Colors.ARGB(255,0,0,0)
ABSYNCMenu.ColorMenuItemDisabled = Colors.ARGB(255,192,192,192)

Important! When you add an actionbar item you can have them left our right aligned. Depending on the alignment the icons are shown in a different order.

If the alignment is LEFT then the order of the shown icons is:
first added, second added, third added, …

If the alignment is RIGHT then the order of the shown icons is:
…, third added, second added, first added

Let’s add a simple item to the taskbar. Every actionbar item has to start with ABSYNCMenu.AddActionBarItemBegin and has to end with ABSYNCMenu.AddActionBarItemEnd. The syntax for the AddActionBarItem is as follows:

Sub AddActionBarItem(ReturnValue As String, bmpEnabled As String, bmpDisabled As String, ItemWidth As Int, LeftAligned As Boolean, Visible As Boolean, Enabled As Boolean, MenuWidth As Int)

ReturnValue: the value that will be returned to the ABSYNCMenuEvent() function. This is also the text that will be shown if no icon is provided.
bmpEnabled: the file name of the bmp for the Enabled icon.
bmpDisabled: the file name of the bmp for the Disabled icon.
ItemWidth: the width of this item. Can be bigger than the icon width. The icon will then be centered withion this width.
LeftAligned: is this icon aligned to the left of your screen or the right. See note above about alignment.
Visible: is this item visible.
Enabled: is this item enabled.
MenuWidth: the total with of the sub menu, if any.

So our full first item is like this:

ABSYNCMenu.AddActionBarItemBegin
ABSYNCMenu.AddActionBarItem("Home", "", "", 50dip, True, True, True, 0)
ABSYNCMenu.AddActionBarItemEnd

Another example is an actionbar item with an icon and a submenu. right after you added the actionbar item, you can add the submenu with the AddMenuItem() function.
the syntax of AddMenuItem() is:

Sub AddMenuItem(ReturnValue As String, bmpEnabled As String, bmpDisabled As String, ItemHeight As Int, IconWidth As Int, Enabled As Boolean)

ReturnValue: the value that will be returned to the ABSYNCMenuEvent() function. This is also the text that will be shown next to the icon
bmpEnabled: the file name of the bmp for the Enabled icon.
bmpDisabled: the file name of the bmp for the Disabled icon.
ItemHeight: the height of this item.
IconWidth: the width of the iconspace.
Enabled: is this item enabled.

The full item looks like this:

ABSYNCMenu.AddActionBarItemBegin
ABSYNCMenu.AddActionBarItem("Menu", "abmenuE.png", "abmenuD.png", 50dip, False, True, True, 160dip)
ABSYNCMenu.AddMenuItem("Register", "", "", 40dip, 30dip, True)
ABSYNCMenu.AddMenuItem("Connections", "ConnectionsE.png", "ConnectionsD.png", 40dip, 0, True)
ABSYNCMenu.AddMenuItem("Tables", "", "", 40dip, 0, False)
ABSYNCMenu.AddActionBarItemEnd

After all items are added, end the ABSYNC menu definition and add it to this activity:

ABSYNCMenu.ABSYNCMenuEnd(ABS_ActionBarPanel, ABS_DropdownMenuPanel)
Activity.AddView(ABS_MainMenuPanel, 0,0, Activity.Width, ABSYNCMenu.ActionBarHeight)

Now we can write our function that will handle the menu click event. This function will be automatically called by the ABSYNCMenu module.
This function is straightforward. The comments will explain what happens:

' function that returns if someone clicked on an action bar item or on a sub menu item
' Here is where you do your stuff
Sub ABSYNCMenuEvent(ReturnValue As String, HasMenu As Boolean)
	If HasMenu Then
		' is an action bar item with a menu, open it and return
		ABS_MainMenuPanel.SetLayout(0,0, Activity.Width, Activity.Height)
	Else
		' is an action bar item without a menu OR an actual menu item so we have to handle it
		ABS_MainMenuPanel.SetLayout(0,0, Activity.Width, ABSYNCMenu.ActionBarHeight)
		Select Case ReturnValue
			Case "Home"
				LoadLayoutIntoActivity("1")
			Case "Register"
				LoadLayoutIntoActivity("2")
			Case "Connections"
				LoadLayoutIntoActivity("3")
			Case "Tables"
				LoadLayoutIntoActivity("4")
			Case "All tables"
				ToastMessageShow(ReturnValue, False)
			Case "Register tables"
				ToastMessageShow(ReturnValue, False)
		End Select
	End If
        ' and redraw the action bar and menu
	ABSYNCMenu.Draw(ABS_ActionBarPanel, ABS_DropdownMenuPanel)
End Sub

Finally we’ll have to cover the touch events on the tree panels. We’ll send the event to the ABSYNCMenu module an it will handle all the rest for you.

Sub ABS_ActionBarPanel_Touch (Action As Int, X As Float, Y As Float) As Boolean 'Return True to consume the event
	' in the touch event, let the ABSYNCMenu module handle the touch
	Return ABSYNCMenu.DoActionBarTouch(Action, X, Y)
End Sub

Sub ABS_DropdownMenuPanel_Touch (Action As Int, X As Float, Y As Float) As Boolean 'Return True to consume the event
	' in the touch event, let the ABSYNCMenu module handle the touch
	Return ABSYNCMenu.DoMenuTouch(Action, X, Y)
End Sub

Sub ABS_MainMenuPanel_Touch (Action As Int, X As Float, Y As Float) As Boolean 'Return True to consume the event
	' did not touch a menu or action bar item. Close it up!
	ABS_MainMenuPanel.SetLayout(0,0, Activity.Width, ABSYNCMenu.ActionBarHeight)
	Return True
End Sub

Finished! As you can see with some very easy coding we’ll have a fully working actionbar with dropdown menu’s!

Check out the source code with the ABSYNCMenu.bas module here:
http://gorgeousapps.com/ABSYNCMenu.zip

Until next time!

Click here to Donation if you like my work


Basic4Android: Just got even better with version 1.9


The new version of B4A is here!

To celebrate the new version I have a coupon for the first 20 lucky readers who buy the Basic4android Enterprise Version for $49.5
instead of $99!

Folow this link Buy B4A Enterprise
and use coupon code: auxkmr

This version includes several important new features:

– Designer scripts – this is probably the most innovative feature added to Basic4android since the first version. It will make it much easier to support different screen sizes and resolutions.

As quoted from the B4A website:

One of the most common issues that Android developers face is the need to adopt the user interface to devices with different screen sizes.
As described in the visual designer tutorial, you can create multiple layout variants to match different screens.
However it is not feasible nor recommended to create many layout variants.

Basic4android v1.9 introduces a new tool named “designer scripts” that will help you fine tune your layout and easily adjust it to different screens and resolutions.

The idea is to combine the usefulness of the visual designer with the flexibility and power of programming code.

– B4A-Bridge – now supports Bluetooth connections as well as wireless connections.
– Java 7 JDK is supported.
– The logging system was improved and all error messages should now show in the filtered logs.
– List.SortType – new method that allows sorting items of custom types based on one of the type fields.
– Bug fixes and other minor improvements.

Read more on the new exciting scripts feature here.


%d bloggers like this: