A clean, modern Android development illustration showing a CoordinatorLayout diagram with a collapsing Toolbar at the top, a FloatingActionButton, and a BottomSheet panel. Material Design style, dark blue and teal color palette, flat UI components on a dark background.

In questa guida scoprirai come usare CoordinatorLayout Android per creare interfacce dinamiche in stile Material Design, in cui toolbar, contenuti e pannelli reagiscono in modo coordinato alle azioni dell’utente. Questo CoordinatorLayout Android tutorial ti mostrerà cos’è questo layout avanzato, a cosa serve e quando conviene introdurlo nei tuoi progetti. Tutti gli esempi sono sviluppati in Java utilizzando Android Studio, così potrai integrarli facilmente nelle tue app esistenti. Continua a leggere per imparare passo dopo passo come ottenere effetti professionali con il minimo sforzo.

Cos’è CoordinatorLayout Android

CoordinatorLayout è un layout avanzato di Material Design usato quando più viste devono reagire insieme; in particolare, è utile per gestire toolbar a scomparsa, Snackbar animate e BottomSheet. Inoltre, le viste figlie comunicano tramite l’attributo app:layout_behavior, che quindi assegna un comportamento preciso in risposta alle azioni dell’utente e, in questo modo, coordina le loro interazioni.

L’elemento chiave di CoordinatorLayout è l’attributo app:layout_behavior, che assegna un comportamento specifico a ogni vista figlia. Grazie a questo attributo, la vista può comunicare con il layout genitore e con le altre viste figlie, coordinando reazioni alle azioni dell’utente. Ad esempio, la proprietà @string/appbar_scrolling_view_behavior dice a una vista di adattarsi quando la AppBarLayout scorre verso l’alto.

CoordinatorLayout è preferibile a ConstraintLayout o LinearLayout quando il tuo progetto richiede comportamenti coordinati tra viste. Mentre ConstraintLayout eccelle nel creare layout complessi con vincoli relazionali e LinearLayout è ideale per strutture semplici e lineari, CoordinatorLayout brilla quando hai toolbar a scomparsa, Snackbar che si spostano sopra un FloatingActionButton, o BottomSheet che interagiscono con il resto dell’interfaccia. Quindi, scegli CoordinatorLayout se il tuo design richiede animazioni e comportamenti dinamici tra elementi.

Rispetto a un semplice FrameLayout, che si limita a impilare le viste una sopra l’altra senza alcuna logica di coordinamento, CoordinatorLayout Android aggiunge un livello di intelligenza: ogni vista può reagire allo scroll, ai tocchi o ai cambiamenti di stato delle altre. Usa FrameLayout per container statici e sovrapposizioni semplici; scegli CoordinatorLayout Android quando vuoi Toolbar che scompaiono allo scroll, BottomSheet che emergono da sotto il contenuto o FloatingActionButton che si spostano automaticamente per non coprire una Snackbar.

Esempio 1: Toolbar con CoordinatorLayout Android

In questo esempio, sostituiamo la ActionBar predefinita con una Toolbar personalizzata tramite il metodo setSupportActionBar(). Perché funzioni, il tema dell’app deve usare una variante con suffisso NoActionBar. Inoltre, questa personalizzazione consente maggiore flessibilità nel design della barra di navigazione.

themes.xml

<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- altri attributi del tema -->
</style>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- Contenuto scrollabile qui -->

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

MainActivity.java

package com.example.coordinatorLayout;

import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

        Toolbar toolbar = findViewById(R.id.app_bar);
        setSupportActionBar(toolbar);
    }
}

Esempio 2: BottomSheet con CoordinatorLayout Android tutorial

Un BottomSheet è un pannello che si apre dal bordo inferiore dello schermo. Di conseguenza, rappresenta un elemento fondamentale del Material Design. Si configura aggiungendo l’attributo app:layout_behavior="@string/bottom_sheet_behavior" nel layout e usando la classe BottomSheetBehavior nel codice Java.

activity_main.xml (con BottomSheet)

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#CCBBFF"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:behavior_peekHeight="100dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="BottomSheet"
            android:textColor="#B30DAD"
            android:textSize="30sp" />

    </RelativeLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

MainActivity.java (con BottomSheet)

package com.example.coordinatorLayout;

import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.google.android.material.bottomsheet.BottomSheetBehavior;

public class MainActivity extends AppCompatActivity {

    private BottomSheetBehavior<View> bottomSheetBehavior;
    private View bottomSheet;

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

        bottomSheet = findViewById(R.id.bottom_sheet);
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

        // Espandi o collassa il BottomSheet programmaticamente
        // bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        // bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
    }
}

CoordinatorLayout Android tutorial è uno strumento essenziale per realizzare interfacce Material Design moderne e reattive. I casi d’uso più comuni includono toolbar collabibili, BottomSheet draggable, Snackbar coordinati e qualsiasi situazione in cui più viste devono reagire insieme alle azioni dell’utente. Se desideri approfondire ulteriormente, consulta la documentazione ufficiale di CoordinatorLayout e i design guidelines di Material Design.

AppBarLayout Android con Toolbar collassabile in CoordinatorLayout Android

Uno degli utilizzi più diffusi di CoordinatorLayout Android è la creazione di una Toolbar collassabile che scompare o si riduce quando l’utente effettua lo scroll del contenuto. Questo pattern è gestito tramite AppBarLayout e CollapsingToolbarLayout. Di seguito trovi un esempio completo in XML per ottenere una AppBarLayout Android con immagine di copertina e titolo che si riduce durante lo scroll.

activity_collapsing_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CollapsingToolbarActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:title="CoordinatorLayout Android">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:src="@drawable/header_image"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/scroll_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Contenuto lungo per testare lo scroll coordinato con AppBarLayout Android e CollapsingToolbarLayout. Aggiungi qui il testo della tua guida o della tua schermata di dettaglio." />

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

CollapsingToolbarActivity.java

package com.example.coordinatorLayout;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import com.google.android.material.appbar.CollapsingToolbarLayout;

public class CollapsingToolbarActivity extends AppCompatActivity {

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

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
        collapsingToolbarLayout.setTitle("CoordinatorLayout Android");
    }
}

BottomSheet modale e persistente con CoordinatorLayout Android

Con CoordinatorLayout Java puoi gestire sia BottomSheet persistenti (ancorati nel layout, come nell’esempio precedente) sia BottomSheet modali che compaiono sopra l’interfaccia corrente. Qui sotto trovi un esempio completo per entrambi i casi, sempre in Java.

BottomSheet persistente (layout + Java)

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/content_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:id="@+id/persistent_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:orientation="vertical"
        android:padding="16dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:behavior_peekHeight="80dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="BottomSheet persistente" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
package com.example.coordinatorLayout;

import android.os.Bundle;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.bottomsheet.BottomSheetBehavior;

public class PersistentBottomSheetActivity extends AppCompatActivity {

    private BottomSheetBehavior<View> bottomSheetBehavior;

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

        View bottomSheet = findViewById(R.id.persistent_bottom_sheet);
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

        bottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                // Gestisci i cambi di stato: COLLAPSED, EXPANDED, HIDDEN, ecc.
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                // Aggiorna la UI in base allo slideOffset, se necessario
            }
        });
    }
}

BottomSheet modale (BottomSheetDialogFragment)

package com.example.coordinatorLayout;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

public class ExampleModalBottomSheet extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.modal_bottom_sheet_content, container, false);
    }
}
package com.example.coordinatorLayout;

import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.button.MaterialButton;

public class ModalBottomSheetActivity extends AppCompatActivity {

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

        MaterialButton openBottomSheetButton = findViewById(R.id.open_bottom_sheet_button);
        openBottomSheetButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ExampleModalBottomSheet bottomSheet = new ExampleModalBottomSheet();
                bottomSheet.show(getSupportFragmentManager(), "ModalBottomSheet");
            }
        });
    }
}

FloatingActionButton e Snackbar con CoordinatorLayout Android

Un altro pattern tipico di CoordinatorLayout Android è il FloatingActionButton (FAB) che si sposta automaticamente quando compare una Snackbar, per non essere coperto visivamente. Il layout seguente mostra come dichiarare il FAB all’interno del CoordinatorLayout e come mostrare una Snackbar da codice Java.

activity_fab_snackbar.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root_coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Esempio CoordinatorLayout Java con FAB e Snackbar" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        app:srcCompat="@drawable/ic_add" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

FabSnackbarActivity.java

package com.example.coordinatorLayout;

import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

public class FabSnackbarActivity extends AppCompatActivity {

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

        final View rootCoordinator = findViewById(R.id.root_coordinator);
        FloatingActionButton fab = findViewById(R.id.fab);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(rootCoordinator,
                        "Azione eseguita con CoordinatorLayout Android",
                        Snackbar.LENGTH_LONG)
                        .setAction("Annulla", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                // Gestisci il click su "Annulla"
                            }
                        })
                        .show();
            }
        });
    }
}

Behavior personalizzato in CoordinatorLayout Android

In questo CoordinatorLayout Android tutorial, il vero punto di forza di CoordinatorLayout Android è la possibilità di definire Behavior personalizzati, cioè classi Java che descrivono come una vista deve reagire ai cambiamenti di un’altra (scroll, movimento, comparsa/scomparsa). In questo esempio creiamo un Behavior che sposta una View verso l’alto quando una AppBarLayout viene collassata.

MyCustomBehavior.java

package com.example.coordinatorLayout;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

import com.google.android.material.appbar.AppBarLayout;

public class MyCustomBehavior extends CoordinatorLayout.Behavior<View> {

    public MyCustomBehavior() {
        super();
    }

    public MyCustomBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(@NonNull CoordinatorLayout parent,
                                   @NonNull View child,
                                   @NonNull View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent,
                                          @NonNull View child,
                                          @NonNull View dependency) {
        float ratio = -dependency.getY() / dependency.getHeight();
        float translation = ratio * child.getHeight();
        child.setTranslationY(-translation);
        return true;
    }
}

Utilizzo nel layout XML

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="200dp" />

    <View
        android:id="@+id/animated_view"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_gravity="bottom"
        android:background="@android:color/holo_blue_light"
        app:layout_behavior="com.example.coordinatorLayout.MyCustomBehavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

NestedScrollView con CoordinatorLayout: scroll coordinato

Per ottenere uno scroll coordinato tra contenuto e AppBarLayout Android devi usare una vista che supporti lo scrolling annidato, come NestedScrollView o RecyclerView, insieme al Behavior @string/appbar_scrolling_view_behavior. Questo consente a CoordinatorLayout Android di ricevere gli eventi di scroll e aggiornare la Toolbar o altri componenti. Seguendo questo CoordinatorLayout Android tutorial, potrai implementare scroll coordinati fluidi in qualsiasi progetto.

Esempio completo con NestedScrollView

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar_nested"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nested_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Testo lungo per verificare lo scroll coordinato con CoordinatorLayout Android e NestedScrollView" />

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Proprietà principali di BottomSheetBehavior in CoordinatorLayout Android

StatoDescrizione
STATE_COLLAPSEDPannello collassato, visibile solo per l’altezza di peekHeight
STATE_EXPANDEDPannello completamente espanso
STATE_HIDDENPannello completamente nascosto (richiede setHideable(true))
STATE_DRAGGINGL’utente sta trascinando il pannello
STATE_SETTLINGIl pannello sta raggiungendo uno stato finale dopo il trascinamento

Dipendenza Gradle

implementation 'com.google.android.material:material:1.9.0'

FAQ su CoordinatorLayout Android

  • CoordinatorLayout vs FrameLayout?
    Usa FrameLayout quando ti serve solo un contenitore semplice per sovrapporre viste senza interazioni complesse. Scegli CoordinatorLayout Android quando hai bisogno di Behavior, Toolbar collassabili, Snackbar che spostano il FloatingActionButton o BottomSheet che interagiscono con il contenuto.
  • Come aggiungere un BottomSheet al CoordinatorLayout?
    Dichiara una vista (es. LinearLayout o FrameLayout) all’interno di CoordinatorLayout e imposta app:layout_behavior="@string/bottom_sheet_behavior". In Java recupera la vista e usa BottomSheetBehavior.from(view) per controllarne lo stato (ESPANSA, COLLASSATA, NASCOSTA).
  • Come fare la Toolbar che scompare allo scroll?
    Utilizza AppBarLayout Android con CollapsingToolbarLayout, aggiungi il flag app:layout_scrollFlags="scroll|exitUntilCollapsed" e racchiudi il contenuto in una NestedScrollView o RecyclerView con app:layout_behavior="@string/appbar_scrolling_view_behavior". In questo modo lo scroll coordina il movimento della Toolbar.
  • Posso usare CoordinatorLayout con RecyclerView invece di NestedScrollView?
    Sì, CoordinatorLayout Android funziona perfettamente con RecyclerView. È sufficiente che la RecyclerView sia figlia del CoordinatorLayout e che abbia impostato app:layout_behavior="@string/appbar_scrolling_view_behavior" per coordinare lo scroll con AppBarLayout.
  • Quando ha senso creare un Behavior personalizzato?
    Crea un Behavior custom quando due o più viste devono reagire tra loro in modo non coperto dai Behavior standard (scroll della Toolbar, BottomSheet, Snackbar). Ad esempio, per spostare un banner promozionale in base allo scroll, nascondere/mostrare un pulsante in sincronia con l’AppBarLayout o creare animazioni personalizzate guidate dallo scroll.