App Tutorial

Tutorial ProgressBar in Android

1. Introduzione alla ProgressBar in Android

La ProgressBar in Android è un componente grafico che permette di mostrare all’utente l’avanzamento di un’operazione in corso, come un download, un caricamento da rete o un processo di elaborazione. Utilizzarla correttamente migliora notevolmente l’esperienza utente, perché comunica che l’app è attiva e che l’operazione richiede tempo.

In questo tutorial vedremo, passo dopo passo, come:

  • capire i diversi tipi di ProgressBar (determinata e indeterminata);
  • aggiungere una ProgressBar nel layout XML;
  • gestire la ProgressBar in Java dal codice dell’Activity;
  • creare una mini app completa che simula un download;
  • personalizzare lo stile della ProgressBar;
  • seguire le principali best practices e regole di accessibilità.

2. Tipi di ProgressBar: Determinata vs Indeterminata

Android mette a disposizione principalmente due tipi di ProgressBar:

2.1 ProgressBar indeterminata

La ProgressBar indeterminata viene utilizzata quando non conosciamo la durata esatta dell’operazione. È il classico indicatore circolare che gira all’infinito finché il processo non termina. Ad esempio, è utile per una chiamata di rete di cui non sappiamo la durata.

  • Vantaggi: semplice da usare, comunica che il sistema è occupato.
  • Svantaggi: non mostra all’utente quanto tempo manca al completamento.

2.2 ProgressBar determinata

La ProgressBar determinata mostra il progresso su una scala definita, ad esempio da 0 a 100. È spesso rappresentata come una barra orizzontale che si riempie gradualmente. È ideale quando puoi stimare o conoscere la quantità di lavoro da svolgere, come un download con dimensione nota.

  • Vantaggi: comunica con chiarezza a che punto è l’operazione.
  • Svantaggi: richiede una logica in più per calcolare il progresso.

3. Aggiungere la ProgressBar nel layout XML

Per usare una ProgressBar, il primo passo è dichiararla nel file di layout XML della tua Activity (ad esempio activity_main.xml). Vediamo due esempi: uno per una ProgressBar circolare indeterminata e uno per una ProgressBar orizzontale determinata.

3.1 Esempio: ProgressBar circolare indeterminata

<ProgressBar
    android:id="@+id/progressBarIndeterminata"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    style="?android:attr/progressBarStyleLarge"
    android:indeterminate="true" />

Note principali:

  • android:indeterminate="true" indica che si tratta di una ProgressBar indeterminata (non ha un valore di progresso specifico).
  • Lo style usa uno stile di sistema per il formato circolare grande.
  • Puoi inserirla in qualsiasi layout (LinearLayout, ConstraintLayout, ecc.).

3.2 Esempio: ProgressBar orizzontale determinata

<ProgressBar
    android:id="@+id/progressBarOrizzontale"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="?android:attr/progressBarStyleHorizontal"
    android:indeterminate="false"
    android:max="100"
    android:progress="0" />

In questo caso:

  • style="?android:attr/progressBarStyleHorizontal" indica che vogliamo una barra orizzontale.
  • android:max="100" definisce il valore massimo (ad esempio 100%).
  • android:progress="0" è il valore iniziale della barra (0%).
  • android:indeterminate="false" la rende determinata (puoi aggiornare il valore da codice).

4. Gestire la ProgressBar in Java

Dopo aver definito la ProgressBar nel layout XML, devi controllarla dal codice Java per mostrarla, nasconderla o aggiornare il valore di avanzamento.

4.1 Collegare la ProgressBar all’Activity

public class MainActivity extends AppCompatActivity {

    private ProgressBar progressBarOrizzontale;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Collegamento tra ProgressBar nel layout XML e oggetto Java
        progressBarOrizzontale = findViewById(R.id.progressBarOrizzontale);
    }
}

Assicurati che l’id usato in findViewById coincida con quello definito nel layout XML.

4.2 Mostrare e nascondere la ProgressBar

Puoi controllare la visibilità della ProgressBar per mostrarla solo quando serve:

// Mostra la ProgressBar
progressBarOrizzontale.setVisibility(View.VISIBLE);

// Nasconde la ProgressBar
progressBarOrizzontale.setVisibility(View.GONE); // o View.INVISIBLE

View.GONE nasconde il componente e libera lo spazio nel layout, mentre View.INVISIBLE lo rende invisibile ma mantiene lo spazio occupato.

4.3 Aggiornare il valore di avanzamento

Per una ProgressBar determinata, puoi aggiornare il progresso con il metodo setProgress():

// Imposta il progresso al 50%
progressBarOrizzontale.setProgress(50);

// Incrementa il progresso di 10 punti
progressBarOrizzontale.incrementProgressBy(10);

Ricorda che tutte le modifiche all’interfaccia devono essere eseguite sul thread principale (UI thread). Se stai eseguendo operazioni in background, usa runOnUiThread(), Handler, AsyncTask (deprecato) o soluzioni moderne come Coroutine (in Kotlin) o WorkManager.

5. Mini App completa di esempio: simulare un download

Vediamo ora un esempio completo di mini app che simula un download usando una ProgressBar orizzontale determinata e un pulsante “Avvia Download”. Quando l’utente preme il pulsante, la barra avanza gradualmente da 0 a 100.

5.1 Layout XML completo (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:gravity="center">

    <TextView
        android:id="@+id/tvTitolo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Simulazione Download"
        android:textSize="20sp"
        android:textStyle="bold"
        android:layout_marginBottom="16dp" />

    <ProgressBar
        android:id="@+id/progressBarDownload"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="0"
        android:layout_marginBottom="16dp" />

    <Button
        android:id="@+id/btnAvviaDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Avvia Download" />

    <TextView
        android:id="@+id/tvStato"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Pronto per iniziare il download"
        android:layout_marginTop="16dp" />

</LinearLayout>

In questo layout abbiamo:

  • un titolo (TextView);
  • una ProgressBar orizzontale determinata;
  • un pulsante per avviare il download;
  • un messaggio di stato che informa l’utente.

5.2 Codice Java completo (MainActivity.java)

package com.example.progressbardemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private ProgressBar progressBarDownload;
    private Button btnAvviaDownload;
    private TextView tvStato;

    private Handler handler = new Handler();
    private int progresso = 0;
    private boolean inCorso = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Collegamento dei componenti del layout
        progressBarDownload = findViewById(R.id.progressBarDownload);
        btnAvviaDownload = findViewById(R.id.btnAvviaDownload);
        tvStato = findViewById(R.id.tvStato);

        btnAvviaDownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!inCorso) {
                    avviaDownloadSimulato();
                }
            }
        });
    }

    // Metodo che simula un download aggiornando la ProgressBar
    private void avviaDownloadSimulato() {
        inCorso = true;
        progresso = 0;
        progressBarDownload.setProgress(progresso);
        tvStato.setText("Download in corso...");

        // Disabilita il pulsante durante il download
        btnAvviaDownload.setEnabled(false);

        // Runnable che aggiorna periodicamente il progresso
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (progresso < 100) {
                    progresso += 5; // incrementa il progresso
                    progressBarDownload.setProgress(progresso);

                    // Aggiorna il testo di stato con la percentuale
                    tvStato.setText("Download in corso: " + progresso + "%");

                    // Ripeti l'aggiornamento dopo 200 millisecondi
                    handler.postDelayed(this, 200);
                } else {
                    // Download completato
                    tvStato.setText("Download completato!");
                    inCorso = false;
                    btnAvviaDownload.setEnabled(true);
                }
            }
        }, 200);
    }
}

Cosa fa questo codice:

  • inizializza la ProgressBar, il pulsante e il testo di stato;
  • quando l’utente preme “Avvia Download”, parte una simulazione che aumenta il valore di progresso da 0 a 100;
  • la ProgressBar viene aggiornata sul thread principale usando un Handler;
  • il pulsante viene disabilitato durante il “download” per evitare doppi avvii;
  • al termine, il testo di stato mostra “Download completato!” e il pulsante torna cliccabile.

6. Personalizzazione e stili

La ProgressBar può essere personalizzata per adattarsi al design della tua app. Esistono diversi livelli di personalizzazione, dai semplici cambi di colore fino alla creazione di drawable personalizzati.

6.1 Cambiare colori con i drawable

Per una ProgressBar orizzontale, puoi creare un file .xml nella cartella drawable per definire l’aspetto della barra. Ad esempio, un file chiamato progress_bar_colore.xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <corners android:radius="8dp" />
            <solid android:color="#DDDDDD" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape android:shape="rectangle">
                <corners android:radius="8dp" />
                <solid android:color="#3F51B5" />
            </shape>
        </clip>
    </item>

</layer-list>

Poi, nel layout XML, assegna questo drawable alla ProgressBar:

<ProgressBar
    android:id="@+id/progressBarOrizzontale"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:progressDrawable="@drawable/progress_bar_colore"
    android:max="100"
    android:progress="0" />

6.2 Dimensioni e margini

Puoi modificare le dimensioni e lo spazio attorno alla ProgressBar usando gli attributi di layout, ad esempio:

android:layout_height="8dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"

Cerca di mantenere una barra sufficientemente spessa da essere ben visibile e facilmente percepibile dagli utenti.

6.3 Uso degli stili (styles.xml)

Per riutilizzare le stesse impostazioni in più punti dell’app, puoi definire uno stile nel file styles.xml:

<style name="MiaProgressBarOrizzontale" parent="Widget.AppCompat.ProgressBar.Horizontal">
    <item name="android:progressDrawable">@drawable/progress_bar_colore</item>
    <item name="android:max">100</item>
</style>

E poi applicarlo nel layout:

<ProgressBar
    style="@style/MiaProgressBarOrizzontale"
    android:id="@+id/progressBarOrizzontale"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

7. Best Practices e accessibilità

Usare una ProgressBar non significa solo mostrare una barra che si muove. È importante seguire alcune buone pratiche per evitare di creare confusione o frustrazione negli utenti, e per mantenere l’app accessibile.

7.1 Comunicazione chiara con l’utente

  • Quando possibile, usa ProgressBar determinate con percentuale o tempo stimato.
  • Aggiungi testi di stato (come nel nostro esempio) per spiegare cosa sta succedendo (“Caricamento dati”, “Download in corso”).
  • Evita barre che restano ferme troppo a lungo o che si riempiono e poi ricominciano da capo: generano sfiducia.

7.2 Performance e thread

  • Non eseguire mai operazioni lunghe sul thread principale, o l’interfaccia si bloccherà.
  • Usa thread in background, Handler, AsyncTask (nelle app legacy) o API moderne come WorkManager e librerie di concorrenza.
  • Aggiorna la ProgressBar solo dal thread principale, utilizzando il meccanismo di callback appropriato.

7.3 Accessibilità

Per rendere la ProgressBar accessibile anche a chi utilizza tecnologie assistive (come i lettori di schermo), considera i seguenti aspetti:

  • Aggiungi descrizioni testuali dello stato. Ad esempio, il TextView che mostra la percentuale di completamento.
  • Usa colori con contrasto sufficiente tra barra di sfondo e barra di progresso, per aiutare gli utenti con difficoltà visive.
  • Evita di basarti solo sul colore per comunicare lo stato. Puoi usare anche testo o icone.
  • Per aggiornamenti importanti, valuta l’uso di messaggi Toast o Snackbar, purché non sostituiscano indicazioni permanenti sullo schermo.

7.4 Gestione dei cambi di configurazione

Quando il dispositivo ruota o cambia configurazione, l’Activity può essere ricreata. Assicurati di salvare e ripristinare lo stato del progresso (ad esempio usando onSaveInstanceState() e onRestoreInstanceState() o ViewModel) per evitare che la ProgressBar si azzeri inaspettatamente.

8. Conclusioni

La ProgressBar è un componente fondamentale per creare app Android moderne e usabili. In questo tutorial hai visto come:

  • capire la differenza tra ProgressBar determinata e indeterminata;
  • aggiungere una ProgressBar ai tuoi layout XML;
  • controllare la ProgressBar da Java, aggiornando il progresso e la visibilità;
  • realizzare una mini app che simula un download;
  • personalizzare l’aspetto della barra con drawable e stili;
  • seguire best practices e principi di accessibilità.

Partendo da questi esempi, puoi integrare ProgressBar più complesse nella tua app, collegandole a download reali, caricamenti da API o elaborazioni pesanti. Mantieni sempre al centro l’esperienza utente: una ProgressBar chiara, ben progettata e accessibile fa la differenza tra un’app piacevole da usare e una che sembra bloccata o poco reattiva.