A B4A Spinner lets someone choose one option without filling the screen with a long list of controls. The useful part is not just adding the dropdown—it is loading its choices at the right time and making the selected value behave predictably.

On this page 10 sections
  1. Key Takeaways
  2. What Is a B4A Spinner?
  3. How to Add a Spinner in B4A
  4. How to Add and Reload Spinner Items
  5. How to Handle Selections and Set a Default
  6. How to Load Choices from a Database or API
  7. Common B4A Spinner Errors and How to Fix Them
  8. Important Points / Key Information
  9. Examples / Supporting Information
  10. Conclusion

Part of our software engineering technologies guide library

Key Takeaways

B4A is the Android development tool in the B4X family. This guide covers its native Spinner using a classic Activity project first, followed by a separate B4XPages placement note. It explains loading items, selection events, defaults, database and API data, and common mistakes [1] [2].

  • Load a designer layout before using its Spinner, and do not initialize that designer-created view again.
  • Use Add or AddAll to populate choices; clear old items when rebuilding the list.
  • A native B4A Spinner raises ItemClick for a user item press. Apply programmatic selection logic explicitly.
  • Guard empty lists and index bounds, and keep loading or error messages separate from real selectable values.

What Is a B4A Spinner?

A Spinner is a compact single-choice control. It displays the selected value, then opens its list when tapped. It works well for a short set of options such as an app category, language or measurement unit [1] [4].

Unlike an EditText , it does not ask the user to type a value. Unlike a ListView , it does not keep a full list visible. Neither makes a Spinner automatically the best choice: a searchable list is often easier when there are many options.

The B4A wrapper supplies methods such as Add , Clear and GetItem , so a beginner does not need to start with Java adapter code. Android examples using onItemSelected explain the underlying platform, but their event names are not the native B4A event contract [1] [4].

Native Spinner or a custom dropdown?

This article uses Spinner , not a custom spinner library or B4XComboBox . Those controls can offer different styling, events and data behavior. Follow the reference for the actual type declared in your project rather than mixing examples from different controls.

How to Add a Spinner in B4A

Start with the layout and names. A valid declaration alone does not create the designer view; loading its layout does [1].

Prepare a small classic Activity example

Open a classic B4A Activity project. In its visual designer, save a layout named Main containing a Spinner named Spinner1 and a Label named Label1 . Set the Spinner's event name to Spinner1 and generate the corresponding members. The exact IDE menu wording can differ by version.

Place the Spinner declaration in Sub Globals , not Sub Process_Globals . The reference identifies the native Spinner as an Activity Object. Put it beneath a visible label such as “Category”, and leave enough space for the choices to be read and tapped [1].

Load, populate and apply the first selection

The following is one coherent example for those two designer views. Keep the project's existing module attributes and lifecycle stubs; replace or merge the matching Subs rather than declaring them twice.

Sub Globals
    Private Spinner1 As Spinner
    Private Label1 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Main")

    Spinner1.TextSize = 18
    Spinner1.Clear
    Spinner1.AddAll(Array As String( _
        "Technology", "Science", "Business", "Education"))

    SelectCategory(0)
End Sub

Private Sub SelectCategory(Index As Int)
    If Index < 0 Or Index >= Spinner1.Size Then Return
    Spinner1.SelectedIndex = Index
    ApplyCategory(Index)
End Sub

Private Sub ApplyCategory(Index As Int)
    If Index < 0 Or Index >= Spinner1.Size Then Return
    Label1.Text = "Category: " & Spinner1.GetItem(Index)
End Sub

Sub Spinner1_ItemClick(Position As Int, Value As Object)
    ApplyCategory(Position)
End Sub

LoadLayout comes first, the choices are added next, and only then does the code select index 0 . The label is updated explicitly rather than depending on an automatic click event [1] [3].

Do not surround all view-population code with If FirstTime Then in a classic Activity. FirstTime is not a general substitute for rebuilding a newly created screen. Match view setup to the Activity's actual creation and keep any saved choice separately.

These are source-checked teaching examples, not a claim of a successful B4A compilation or Android device test. Check them in your own IDE, layout and library configuration before using them in an app.

If your project uses B4XPages instead

In a B4A B4XPages project, declare page views in that page's Class_Globals and load the layout into Root in B4XPage_Created . Do not paste a second Activity_Create into the page class [5].

'B4A B4XPages placement, not a full class file.
Sub Class_Globals
    Private Root As B4XView
    Private Spinner1 As Spinner
    Private Label1 As Label
End Sub

Private Sub B4XPage_Created(Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("Main")
    Spinner1.AddAll(Array As String("Technology", "Science"))
    SelectCategory(0)
End Sub

Keep the page template's existing Initialize Sub and add the selection helpers and event from the main example to that class. This native Spinner declaration is B4A-specific ; it is not cross-platform code for B4i or B4J just because it sits in B4XPages.

How to Add and Reload Spinner Items

Add appends one text item. AddAll adds multiple items from a list; the official reference also shows it with a string array [1].

Add one option at a time

After the layout is loaded, this is enough to add an extra category:

Spinner1.Add("Design")

When items come from an EditText , trim and validate the text first. Add does not deduplicate similar labels or decide whether an empty value is meaningful.

Rebuild choices from a List

Keep the options together so sorting, filtering and reloading are easier to follow:

Private Sub LoadCountries
    Dim Countries As List
    Countries.Initialize
    Countries.AddAll(Array As String("India", "Germany", "Brazil", "Japan"))
    Countries.Sort(True)

    Spinner1.Clear
    Spinner1.AddAll(Countries)
    Spinner1.Enabled = Spinner1.Size > 0
    If Spinner1.Size > 0 Then SelectCategory(0)
End Sub

This fragment reuses the main example's generic selection helper and label. Rename the label text from “Category” to “Country” when adapting it. Clear prevents duplicate accumulation when the loading Sub runs again [1].

Sorting changes positions. If your app saves a preference, restore it from a stable value or identifier rather than assuming an old index still means the same thing.

How to Handle Selections and Set a Default

For the native B4A Spinner, the handler is Spinner1_ItemClick(Position As Int, Value As Object) when the event name is Spinner1 . Position identifies the item, and Value is its value [1].

Read a selection when you need it

An event is useful for an immediate preview. A form can also read the current choice later, when the user submits it:

Dim Index As Int = Spinner1.SelectedIndex
If Index >= 0 And Index < Spinner1.Size Then
    Dim Choice As String = Spinner1.SelectedItem
    Log("Chosen category: " & Choice)
Else
    Log("No category is selected")
End If

The reference says SelectedIndex returns -1 when nothing is selected. Valid item positions run from 0 to Size - 1 , so check the bounds before assigning an index or calling GetItem [1].

Apply a default without pretending it was a click

To show the third item in the main example, call SelectCategory(2) after populating the list. That helper updates both the Spinner and the label.

B4X founder Erel describes ItemClick as a user click event. Do not wait for assigning SelectedIndex to perform business logic automatically. Keeping that logic in a helper makes both paths explicit [3].

A repeated press on the already selected item also counts as ItemClick in the native reference. Avoid placing an irreversible action or duplicate database write in every click without its own validation [1].

Restore by value, not by remembered position

Find the current item's position after the new list has been loaded:

Dim SavedChoice As String = "Science"
Dim Found As Int = Spinner1.IndexOf(SavedChoice)
If Found >= 0 And Found < Spinner1.Size Then
    SelectCategory(Found)
Else If Spinner1.Size > 0 Then
    SelectCategory(0)
End If

For choices coming from a database, maintain the selected record's stable ID separately from its display label. Labels may change or repeat, and an alphabetical sort can move every index.

How to Load Choices from a Database or API

Separate data retrieval from changing the control. Build and validate the replacement choices first, then swap them into the Spinner. That makes a failed refresh less likely to leave an empty or half-filled dropdown.

Read a small local SQLite result

This optional fragment requires the B4A SQL library and an already initialized db As SQL . Its example table is categories , with name and enabled columns. It is not code that creates a database or its schema.

Private Sub LoadCategoriesFromDb(db As SQL)
    Dim Choices As List
    Choices.Initialize
    Dim c As Cursor
    Dim Ready As Boolean = False

    Try
        c = db.ExecQuery2( _
            "SELECT name FROM categories WHERE enabled = ? ORDER BY name", _
            Array As String("1"))
        For i = 0 To c.RowCount - 1
            c.Position = i
            Choices.Add(c.GetString("name"))
        Next
        Ready = True
    Catch
        Log(LastException)
    End Try
    If c.IsInitialized Then c.Close

    If Ready Then
        Spinner1.Clear
        Spinner1.AddAll(Choices)
        Spinner1.Enabled = Spinner1.Size > 0
        If Spinner1.Size > 0 Then
            SelectCategory(0)
        Else
            Label1.Text = "No categories available"
        End If
    Else
        Label1.Text = "Categories could not be refreshed"
    End If
End Sub

ExecQuery2 uses ? placeholders and a string-argument array. Bind any variable filter value instead of joining user input into SQL. Close the cursor on the normal and caught-error paths [6].

This is suitable only for a quick local query and small result. A slow query or a large processing loop can still hold up the interface. The documented asynchronous pattern uses ExecQueryAsync and QueryComplete(Success As Boolean, Result As ResultSet) ; Erel's tutorial demonstrates waiting for that result before processing and closing it [6] [7].

Receive an API result safely

For HTTP data, B4A's OkHttpUtils2 pattern uses a local HttpJob , waits for JobDone , checks Success and releases the job after consuming the response. A successful HTTP response does not prove the body has the JSON shape your app expects [8] [9].

The example contract could be a top-level JSON array of category strings, such as ["Technology", "Science"] . JSONParser.NextArray is for that shape; NextObject is for a top-level object. Validate item types and labels before updating choices [9].

This optional request fragment shows resource and error handling. It deliberately leaves the endpoint as an argument and the UI replacement in your app's callback:

Private Sub FetchCategoryChoices(ApiUrl As String)
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download(ApiUrl)
    Wait For (j) JobDone(j As HttpJob)

    If j.Success Then
        Try
            Dim Parser As JSONParser
            Parser.Initialize(j.GetString)
            Dim Choices As List = Parser.NextArray
            'Validate Choices, then pass them to your page's loading logic.
        Catch
            Log(LastException)
            'Keep the last valid choices; show the error separately.
        End Try
    Else
        Log("Category request failed")
    End If
    j.Release
End Sub

Enable the required OkHttpUtils2 and JSON libraries, and supply your app's own verified HTTPS endpoint as ApiUrl . No real endpoint is supplied or called in this tutorial. The fragment is not a complete lifecycle, retry or concurrency implementation: prevent overlapping reloads and confirm the target screen is still valid before updating its views.

Keep “Loading…” or “Could not load” in a separate Label, not as a selectable category. If no valid choices exist, disable the Spinner. For an Indian-language list, test the actual script and longer labels rather than judging the form only with short English samples.

Common B4A Spinner Errors and How to Fix Them

Check initialization and item count before changing more complicated code. These two logs often show where the sequence broke:

Log("Spinner initialized: " & Spinner1.IsInitialized)
If Spinner1.IsInitialized Then
    Log("Item count: " & Spinner1.Size)
    Log("Selected index: " & Spinner1.SelectedIndex)
End If

The Spinner is empty

Confirm the correct layout loaded before Add or AddAll . Check whether a later Clear removed the items, whether the database returned rows, and whether an asynchronous result has arrived. A declared variable is not the same as a populated view [1].

ItemClick does not run

Compare the designer's event name with the Sub prefix. For the native Spinner, use the documented parameter types rather than copying a custom control's event. If the selection was assigned in code, call the shared helper explicitly [1] [3].

There is an initialization or invalid-index error

Check the layout name, generated member name and initialization order. Do not manually reinitialize a designer view. Before accessing an item, ensure the list is not empty and the index is within its current bounds [1].

Choices duplicate or the saved choice becomes wrong

Clear before rebuilding. Restore after loading, not before data arrives. Do not keep a stale index when sorting, filtering or replacing a list. For duplicate labels, a separate stable-ID mapping is safer than treating the text as a unique record identifier.

Text or dropdown colors do not look right

The native reference says to set text size and the relevant text/dropdown colors before adding items . Its Prompt property describes the title displayed when the Spinner opens; it is not a guarantee of an unselected placeholder inside a populated control [1].

Important Points / Key Information

Use a Spinner when one compact choice is easier than showing the whole list. For many searchable choices, richer rows or free text, consider another control instead of making the dropdown do everything.

Keep labels clear, contrast readable and touch targets comfortable. Show a visible field label, test long options, and try the form with the accessibility tools available on the target device. These are design checks to carry out—not accessibility certification claims.

Recheck initialization, empty data, selection bounds and asynchronous completion separately. If the first list entry is a “Select a category” instruction, it is still an item: your save logic must reject it explicitly. Prompt is a different feature [1].

Examples / Supporting Information

A category picker in a learning app

The main example uses Technology, Science, Business and Education as demonstration data. A learner's selection can update the nearby Label immediately. A later save button can validate the selected index again rather than assuming that a displayed value is still valid after a refresh.

A language selector in an India-focused app

Show understandable names for the languages your app actually supports. Keep a stable language code in the data model so changing the visible label does not change the saved preference. Test rendering with the real language labels; selecting a Spinner entry alone does not implement localization.

Frequently asked questions

How do I add items to a B4A Spinner?

Use Add for one string or AddAll for multiple strings after the layout loads. Use Clear first if you are replacing an existing list [1].

How do I get the selected value?

Read SelectedItem after checking SelectedIndex and Size , or use the Value supplied to the documented ItemClick event [1].

Why does SelectedIndex not update my label?

Assigning an index is not a user click. Put the label update in a helper and call it from both your programmatic-selection Sub and ItemClick [3].

Can I declare a native Spinner in Process_Globals?

Not in the classic Activity pattern: the official reference identifies it as an Activity Object. In a B4A B4XPages example, declare the view in the page class instead [1] [5].

Does Spinner.Prompt mean no choice has been selected?

No. It is the title displayed when the Spinner opens. If you add an instruction as the first real item, validate it separately before saving [1].

Conclusion

A reliable B4A Spinner starts with a simple order: load the view, add its choices, validate an index and apply the selected value. Keep user clicks and programmatic selection explicit, and your form becomes much easier to understand and debug.

Start with the small local example, then add data-loading behavior only when the app needs it. Before release, check empty and one-item lists, defaults after a reload, long labels and real user presses in your own B4A project.

Read nextGalaxy S23 One UI 9 Update: What India Owners Can VerifySoftware · 7 min read
tE

About the author

techduopulse Editorial Desk

Newsroom

Technology reporting, verification, and explanatory journalism.

techduopulse separates reporting from analysis and records material corrections.
How we checked thisSources (9)

We keep source links private so your reading stays on techduopulse. Each note names the publisher and document we checked.

01
B4X / Anywhere Software · Undated

B4A — Views (Core): Spinner

Primary source · Native Spinner API, ItemClick, designer initialization, activity-object scope, colors and Prompt
02
B4X / Anywhere Software · Undated

B4A — The simple way to develop native Android apps

Primary source · B4A native Android development context; no minimum-version or performance claim
03
B4X Programming Forum / Erel · 14 January 2015

Spinner.SelectedIndex=anyvalue doesn't trigger Spinner_ItemClick Sub

Primary source · User ItemClick differs from programmatic selection; do not reuse an Android onItemSelected contract
04
Android Developers · 23 October 2026

Add spinners to your app

Primary source · Compact single-choice UI; native Android adapter/events contextual only, not B4A event names
05
B4X Programming Forum / Erel · 11 June 2020

B4XPages — Cross platform and simple framework for managing multiple pages

Primary source · B4XPages class/lifecycle context and Root.LoadLayout placement; native Spinner example B4A-only
06
B4X / Anywhere Software · Date not recorded

SQL — B4A

Primary source · ExecQuery2 bound string arguments, Cursor.Close and SQL async signatures
07
B4X / Anywhere Software · Date not recorded

B4X SQL with Wait For

Primary source · Slow queries, sender filter, QueryComplete and ResultSet cleanup
08
B4X / Anywhere Software · Date not recorded

B4X OkHttpUtils2 with Wait For

Primary source · Local HttpJob, JobDone, Success check and Release
09
B4X / Anywhere Software · Date not recorded

JSON — B4A

Primary source · itialize, NextArray and NextObject
Version 1

Initial source-backed guide edition; owner-commanded manual publication. Reviewed against retained sources; no hands-on testing claimed.

Back to top