Salta al contenuto principale
Sviluppo Mobile

expo-linear-gradient e react-native-linear-gradient in RN

expo-linear-gradient in Expo, react-native-linear-gradient in bare RN. Sfondi, arrotondamenti, shimmer animato, risoluzione dei problemi quando non viene visualizzato.

expo-linear-gradient e react-native-linear-gradient in React Native sul blog Capgo

Scelta rapida: nella Expo, usa expo-linear-gradient. In React Native bare, usa react-native-linear-gradient. Installa quello che corrisponde al tuo stack, poi renderizza un LinearGradient con colors e un style (solitamente flex: 1 per lo sfondo).

Expo

bunx expo install expo-linear-gradient

React Native puro

bun add react-native-linear-gradient

Uso minimo (stessa idea in entrambe le librerie: named export da Expo, default import da bare).

import { LinearGradient } from 'expo-linear-gradient';
// Bare: import LinearGradient from 'react-native-linear-gradient';

<LinearGradient colors={['#0f172a', '#2563eb']} style={{ flex: 1 }} />;

Se stai scegliendo tra stack nativi e una shell web-first, React Native vs Capacitor analizza i trade-off che interessano ai team Capgo. Il resto del post copre background, pulsanti, maschere, motion e troubleshooting.

Indice dei contenuti

Perché la tua app React Native ha bisogno di gradienti

Molte interfacce mobili falliscono per lo stesso motivo. Il layout è corretto, gli spazi sono giusti, la tipografia è accettabile, ma lo schermo sembra comunque spento. I colori pieni fanno sembrare tutto un placeholder, a meno che il resto del sistema visivo non faccia molto lavoro.

Un linear gradient React Native component risolve il problema con pochissimo code. Aggiunge profondità, crea separazione tra le sezioni e dà un peso visivo chiaro agli elementi ad alta priorità. Un buon sfondo sfumato può rendere una schermata di login intenzionale. Un buon pulsante sfumato può rendere l'azione primaria ovvia senza ricorrere a ombre pesanti o bordi troppo evidenti.

Entro il 2019, expo-linear-gradient e react-native-linear-gradient erano presenti in oltre il 42% dei progetti React Native, un forte segnale che i gradienti non sono più un effetto di nicchia. Sono strumenti UI standard nelle app in produzione, non decorazioni aggiunte alla fine, come evidenziato in questo articolo sull'adozione dei gradienti in React Native.

Cosa fanno bene i gradienti

  • Crea profondità: Uno schermo con uno sfondo piatto spesso sembra incompleto. Una sfumatura sottile dall'alto verso il basso conferisce profondità alla superficie.
  • Guida l'attenzione: CTA primarie, card di onboarding e hero header risaltano senza aggiungere rumore visivo.
  • Sostituisci le immagini: In molti casi, un gradiente dà un aspetto curato senza dover aggiungere immagini di sfondo extra.

Regola pratica: Usa i gradienti dove la gerarchia conta. Background, hero card, superfici CTA e overlay multimediali ne traggono maggior beneficio. Campi form, liste dense e contenitori di testo principale di solito no.

C'è anche un aspetto di product design. I team che lavorano su più piattaforme perdono tempo a mantenere le interfacce coerenti. Se fa parte del tuo stack, questi approcci cross-platform per UI e UX delle app mobili si allineano bene con la stessa logica: meno asset, più superfici riutilizzabili e sistemi visivi che reggono su tutti gli schermi.

Scegli il tuo percorso: setup Expo vs Bare React Native

È questo fork che causa la maggior parte dei problemi. Il rendering API sembra quasi identico in entrambe le librerie, ma la configurazione no.

Se stai usando un'app gestita da Expo, usa expo-linear-gradient. Se stai usando un'app React Native bare, usa react-native-linear-gradient. Non cercare di confondere le cose a meno che tu non sappia esattamente perché lo stai facendo.

Infografica di confronto tra i workflow Expo-managed e bare React Native per l'implementazione di gradienti lineari.

Setup di Expo

Expo è la via più fluida. L'installazione è semplice, la corrispondenza delle versioni è gestita per te e non devi preoccuparti del linking nativo.

Installo in questo modo:

bunx expo install expo-linear-gradient

Usalo in questo modo:

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';

export default function App() {
  return (
    <LinearGradient
      colors={['#0f172a', '#1d4ed8']}
      style={styles.container}
    >
      <Text style={styles.text}>Hello gradient</Text>
    </LinearGradient>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 24,
    fontWeight: '700',
  },
});

Expo è la scelta giusta quando vuoi un setup rapido, valori predefiniti sensati e meno problemi nativi. È anche per questo che i team che esplorano workflow Expo avanzati spesso confrontano Capgo e Expo EAS per gli aggiornamenti live quando il percorso gestito non copre più le esigenze dell'app.

Configurazione Bare React Native

Bare React Native offre accesso diretto ai moduli nativi, ma devi gestire tu gli aspetti più complessi.

Installa il pacchetto:

bun add react-native-linear-gradient

Per iOS, installa i pods:

cd ios && pod install

Uso base:

import React from 'react';
import { StyleSheet, Text } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';

export default function App() {
  return (
    <LinearGradient
      colors={['#111827', '#7c3aed']}
      style={styles.container}
    >
      <Text style={styles.text}>Hello gradient</Text>
    </LinearGradient>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 24,
    fontWeight: '700',
  },
});

Dove solitamente si rompono i progetti bare

L'elemento mancante nella maggior parte dei tutorial è il testing e la configurazione nativa. Secondo questo riepilogo di una discussione su Stack Overflow, il 68% dei thread su Stack Overflow su questo argomento tra il 2024 e il 2025 riguarda fallimenti dei moduli nativi in configurazioni bare React Native, e la stessa fonte segnala problemi ricorrenti con il mocking di Jest e conflitti con CocoaPods su iOS.

Se usi Jest in un'app bare, aggiungi il mock esplicitamente:

// jest.setup.js
import mockRNLinearGradient from 'react-native-linear-gradient/jest/linear-gradient-mock';

jest.mock('react-native-linear-gradient', () => mockRNLinearGradient);

E fai riferimento a quel file di configurazione nel tuo setup Jest:

module.exports = {
  preset: 'react-native',
  setupFiles: ['<rootDir>/jest.setup.js'],
};

React Native puro funziona bene per i gradienti. Semplicemente non perdona una configurazione incompleta. La maggior parte dei fallimenti non sono bug visivi. Sono problemi di linking, pods o ambiente di test.

Ecco la tabella decisionale pratica:

Tipo di progetto Libreria Consigliato
App gestita da Expo expo-linear-gradient Percorso più rapido, meno configurazione
App React Native bare react-native-linear-gradient Controllo nativo completo
App bare con Jest react-native-linear-gradient + mock Necessario per test stabili

Tecniche fondamentali per gradienti negli elementi UI

Un approccio comune è riusare sempre lo stesso piccolo set di pattern di gradiente. Sfondi. Bottoni. Titoli. Se questi tre funzionano, puoi riutilizzarli su molte schermate.

Una persona al lavoro su un laptop che mostra una dashboard moderna con elementi di design a gradiente colorati.

Un buon modello mentale è questo:

  • colors controlla la palette
  • start e end controlla la direzione
  • locations controlla dove avvengono le transizioni

Se la schermata di splash o onboarding usa un gradiente, si integra naturalmente con i pattern di sequenza di avvio descritti in questo guida alla splash screen in React Native.

Sfondi a gradiente a tutto schermo

Questo è il pattern più semplice e riutilizzabile.

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
// For bare RN, switch to:
// import LinearGradient from 'react-native-linear-gradient';

export default function WelcomeScreen() {
  return (
    <LinearGradient
      colors={['#0f172a', '#1e293b', '#2563eb']}
      start={{ x: 0, y: 0 }}
      end={{ x: 1, y: 1 }}
      style={styles.container}
    >
      <View style={styles.content}>
        <Text style={styles.title}>Welcome back</Text>
        <Text style={styles.subtitle}>Your workspace is ready.</Text>
      </View>
    </LinearGradient>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  content: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 24,
  },
  title: {
    color: '#fff',
    fontSize: 32,
    fontWeight: '800',
    marginBottom: 8,
  },
  subtitle: {
    color: 'rgba(255,255,255,0.8)',
    fontSize: 16,
  },
});

Un blend diagonale di solito sembra più dinamico di uno verticale predefinito. Ecco perché start={{ x: 0, y: 0 }} e end={{ x: 1, y: 1 }} sono un buon default quando lo schermo è prevalentemente decorativo.

Non scegliere i colori in isolamento. Testali dietro testo reale, icone e stili della status bar. Una palette che sembra bella in Figma può fallire immediatamente una volta che il contenuto si trova sopra.

Bottoni con gradiente che restano bottoni

L'errore comune qui è mettere il comportamento touch direttamente sul gradiente e dimenticare lo stato disabilitato, il feedback di pressione o la coerenza del padding. Mantieni il pulsante semantico e lascia che il gradiente sia lo strato visivo.

import React from 'react';
import {
  Pressable,
  StyleSheet,
  Text,
  ViewStyle,
  StyleProp,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';

type Props = {
  title: string;
  onPress: () => void;
  disabled?: boolean;
  style?: StyleProp<ViewStyle>;
};

export function GradientButton({
  title,
  onPress,
  disabled = false,
  style,
}: Props) {
  return (
    <Pressable onPress={onPress} disabled={disabled} style={style}>
      {({ pressed }) => (
        <LinearGradient
          colors={
            disabled
              ? ['#94a3b8', '#94a3b8']
              : pressed
              ? ['#7c3aed', '#2563eb']
              : ['#8b5cf6', '#3b82f6']
          }
          start={{ x: 0, y: 0.5 }}
          end={{ x: 1, y: 0.5 }}
          style={styles.button}
        >
          <Text style={styles.label}>{title}</Text>
        </LinearGradient>
      )}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  button: {
    minHeight: 52,
    borderRadius: 14,
    alignItems: 'center',
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  label: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '700',
  },
});

Per i pulsanti, un gradiente orizzontale spesso si legge meglio di uno diagonale. Mantiene l'etichetta stabile ed evita di far sembrare il controllo inclinato.

Testo con gradiente tramite maschera

È il pattern più accattivante del set, ed è utile se usato con moderazione. Titoli hero, banner di upgrade e headline per gli empty state sono ottimi candidati. Il testo dei paragrafi no.

Ti servirà @react-native-masked-view/masked-view.

bun add @react-native-masked-view/masked-view

Poi crea la maschera del testo:

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MaskedView from '@react-native-masked-view/masked-view';
import { LinearGradient } from 'expo-linear-gradient';

export default function GradientHeadline() {
  return (
    <View style={styles.container}>
      <MaskedView
        maskElement={
          <View style={styles.maskWrapper}>
            <Text style={styles.title}>Premium analytics</Text>
          </View>
        }
      >
        <LinearGradient
          colors={['#22c55e', '#06b6d4', '#3b82f6']}
          start={{ x: 0, y: 0 }}
          end={{ x: 1, y: 0 }}
          locations={[0, 0.5, 1]}
        >
          <Text style={[styles.title, styles.hiddenText]}>Premium analytics</Text>
        </LinearGradient>
      </MaskedView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 24,
  },
  maskWrapper: {
    backgroundColor: 'transparent',
  },
  title: {
    fontSize: 34,
    fontWeight: '800',
    letterSpacing: -1,
  },
  hiddenText: {
    opacity: 0,
  },
});

locations conta soprattutto quando vuoi che un colore occupi più spazio visivo di un altro. Se la sfumatura sembra sporca, riduci prima il numero di colori. Di solito sistema il design più in fretta che ritoccare ogni stop.

Dare vita ai gradienti con le animazioni

I gradienti statici aggiungono rifinitura. I gradienti animati danno feedback.

L'uso più pratico non è uno sfondo appariscente. È uno shimmer loader. Quell'effetto comunica agli utenti che l'app è attiva, i dati stanno arrivando e il layout che vedono è intenzionale e non un errore.

Una mano che tiene uno smartphone con un elegante dashboard di un'app di mobile banking dal design con gradiente.

Un componente shimmer completa anche altri pattern di movimento. Se la tua app utilizza già icone animate o loader, questo Guida a Lottie in React Native è utile per decidere quando uno shimmer a gradiente è sufficiente e quando ha più senso usare un asset di animazione più ricco.

Uno shimmer loader che sembra nativo

La versione più semplice e affidabile usa react-native-reanimated per far scorrere una banda di gradiente attraverso un placeholder ritagliato.

Installa Reanimated se non è già presente, poi crea un wrapper con overflow: 'hidden'. All'interno, anima un layer di gradiente da sinistra a destra.

import React, { useEffect } from 'react';
import { StyleSheet, View, ViewStyle, StyleProp } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withRepeat,
  withTiming,
  Easing,
} from 'react-native-reanimated';

const AnimatedView = Animated.createAnimatedComponent(View);

type Props = {
  width?: number | string;
  height?: number;
  borderRadius?: number;
  style?: StyleProp<ViewStyle>;
};

export function ShimmerPlaceholder({
  width = '100%',
  height = 16,
  borderRadius = 8,
  style,
}: Props) {
  const translateX = useSharedValue(-220);

  useEffect(() => {
    translateX.value = withRepeat(
      withTiming(220, {
        duration: 1200,
        easing: Easing.linear,
      }),
      -1,
      false
    );
  }, [translateX]);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: translateX.value }],
  }));

  return (
    <View
      style={[
        styles.container,
        { width, height, borderRadius },
        style,
      ]}
    >
      <AnimatedView style={[styles.shimmer, animatedStyle]}>
        <LinearGradient
          colors={['rgba(255,255,255,0)', 'rgba(255,255,255,0.35)', 'rgba(255,255,255,0)']}
          start={{ x: 0, y: 0.5 }}
          end={{ x: 1, y: 0.5 }}
          style={styles.gradient}
        />
      </AnimatedView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    overflow: 'hidden',
    backgroundColor: '#e5e7eb',
  },
  shimmer: {
    ...StyleSheet.absoluteFillObject,
    width: 220,
  },
  gradient: {
    flex: 1,
  },
});

Il segreto è che non stai cercando di animare la definizione del gradiente stessa. Stai animando un layer di gradiente sopra un placeholder statico. È più semplice, facile da gestire e solitamente più stabile su diversi dispositivi.

Ecco un walkthrough visivo dell'effetto in pratica:

Il componente animato

Alcune note sull'implementazione:

  • Usa il clipping: Il parent ha bisogno di overflow: 'hidden', altrimenti lo shimmer uscirà dai bordi arrotondati.
  • Mantieni la banda stretta: Un layer animato più piccolo è più facile da calibrare rispetto all'animazione dell'intera superficie.
  • Abbina il colore di base allo schermo: I skeleton loader devono integrarsi nel layout circostante, non sembrare un widget separato.

I gradienti animati funzionano meglio quando passano quasi inosservati. Se lo shimmer diventa l'elemento più evidente a schermo, sta facendo troppo.

Performance, accessibilità e quirk delle piattaforme

Quando i gradienti passano dalle demo alla produzione, le priorità cambiano. code sembra ancora semplice, ma rendering, leggibilità e coerenza tra le piattaforme diventano più importanti dell'effetto iniziale.

Se stai lavorando per migliorare la reattività dell'app in generale, questa guida all'ottimizzazione delle performance mobile condivide la stessa filosofia: ridurre il lavoro superfluo, testare sui dispositivi reali e ottimizzare le interfacce più utilizzate dagli utenti.

Checklist per le performance

I gradienti nativi sono generalmente efficienti, ma puoi comunque usarli male.

  • Preferisci i gradienti alle grandi immagini decorative: Spesso sono più semplici da distribuire e più facili da adattare a schermi di dimensioni diverse.
  • Evita di sovrapporre troppi layer a tutto schermo: Un gradiente di sfondo va bene. Diversi gradienti traslucidi sovrapposti, insieme a blur e animazioni pesanti, possono pesare sulle performance.
  • Memoizza i componenti riutilizzabili: Se una card con gradiente è in una lista, mantieni le props stabili ed evita il rerender per stati del parent non correlati.

Una buona regola è usare i gradienti in modo strutturale, non eccessivo. Usali per definire le superfici, non per ogni riga di un feed denso.

Checklist per l'accessibilità

I gradienti possono compromettere rapidamente la leggibilità perché il contrasto varia sulla superficie.

  • Testa il testo rispetto all'area più chiara: Se il testo bianco funziona solo sulla parte scura della sfumatura, non va bene.
  • Aggiungi uno scrim quando necessario: Un leggero overlay scuro tra sfondo e testo è spesso meglio che cambiare l'intera palette.
  • Riserva il gradiente nel testo ai titoli di grande formato: Funziona bene sui titoli. È una cattiva scelta per label piccole, testi di supporto o qualsiasi elemento critico per completare un task.

Controlla il punto peggiore del gradiente, non quello più bello.

Checklist delle particolarità delle piattaforme

iOS e Android di solito renderizzano lo stesso gradiente in modo simile, ma non sempre perfettamente.

Problema Cosa aiuta di solito
Il gradiente appare diverso tra le piattaforme Usa meno colori e un contrasto più netto tra gli stop
Gli angoli arrotondati non ritagliano il gradiente Inserisci overflow: 'hidden' sul container
Il gradiente non appare affatto Controlla larghezza, altezza o flex: 1 per primo

Controlla anche la status bar e la gestione della safe area. Un gradiente bilanciato nel simulatore potrebbe sembrare troppo alto su un dispositivo con notch se il contenuto e lo sfondo non tengono conto di quello spazio extra.

Troubleshooting e best practice finali

Ecco la versione breve che terrei in una nota di progetto.

  • Scegli la libreria in base al workflow: expo-linear-gradient per app gestite con Expo, react-native-linear-gradient per React Native bare.
  • Usa i gradienti con criterio: Sfondi, CTA, overlay e hero text sono ottimi casi d'uso.
  • Controlla la direzione con criterio: Orizzontale per i pulsanti, diagonale per sfondi decorativi, con maschera solo per testi grandi.
  • Progetta per i contenuti, non per gli stati vuoti: Testa con testi reali, icone e lo stile della status bar.
  • Tratta il setup base come un setup nativo: Pods, linking e mock di Jest non sono dettagli opzionali.

Tre errori comuni si presentano ripetutamente.

Il gradiente non appare

Causa: il componente non ha dimensioni visibili.

Soluzione: assegnagli flex: 1un'altezza esplicita o un parent con dimensioni. Un gradiente senza layout box non verrà renderizzato in modo utile.

La build iOS si rompe dopo l'installazione

Causa: i pods non sono stati installati o il grafo delle dipendenze native è fuori sincronia.

Fix: esegui pod install nella ios, pulisci la cartella di build se necessario, poi ricompila l'app. Nei progetti bare, l'installazione dei pacchetti da sola di solito non basta.

I test falliscono con errori dei moduli nativi

Causa: Jest sta cercando di caricare il modulo nativo reale.

Soluzione: mock react-native-linear-gradient con react-native-linear-gradient/jest/linear-gradient-mock nel tuo file di setup di Jest.

Se dovessi ricordare un solo concetto di questa guida, ricorda questo: il gradiente in sé è semplice. La parte difficile è la configurazione per la produzione. Una volta scelta la libreria giusta per l'architettura della tua app, tutto il resto diventa molto più prevedibile.


Se il tuo team rilascia app mobile ibride e vuole distribuire aggiornamenti di JavaScript, CSS, copy, config e asset senza attendere la revisione degli store, Capgo merita un'occhiata. Offre ai team CapacitorJS ed Electron live updates controllati, canali di rollout, protezione dai rollback e visibilità dei rilasci, senza trasformare il deployment in una black box.

Live updates per le app Capacitor

Quando un bug nel web-layer è live, rilascia la fix tramite Capgo invece di aspettare giorni l'approvazione degli store. Gli utenti ricevono l'update in background, mentre le modifiche native restano nel normale processo di review.

Ultimi articoli dal blog

Capgo ti offre gli insight migliori che ti servono per creare un'app mobile davvero professionale.