---
title: "Mostrar flows y paywalls - Capacitor"
description: "Presenta flows y paywalls a los usuarios en tu aplicación Capacitor con Adapty."
---

Si has creado un flow o paywall en el Flow Builder, no necesitas preocuparte por renderizarlo en el código de tu app móvil para mostrárselo al usuario. Un flow de este tipo contiene tanto lo que debe mostrarse como la forma en que debe hacerlo.

Antes de empezar, asegúrate de que:

1. Has [creado un flow o paywall](create-paywall).
2. Lo has añadido a un [placement](placements).
3. Has [obtenido el flow y preparado la vista](capacitor-get-pb-paywalls).

:::warning
Esta guía es exclusivamente para **flows y paywalls creados con Paywall Builder**, que requieren SDK v4.0 o posterior. El proceso para presentar flows difiere para los paywalls de Remote Config.

- Para presentar **paywalls de Remote Config**, consulta [Mostrar paywall diseñado con Remote Config](present-remote-config-paywalls-capacitor).

:::
Para mostrar un flow o paywall como pantalla independiente, usa el método `view.present()` en el `view` creado por el método [`createFlowView`](capacitor-get-pb-paywalls#fetch-the-view-configuration). Cada `view` solo puede usarse una vez. Si necesitas mostrar el flow de nuevo, llama a `createFlowView` otra vez para crear una nueva instancia de `view`.

:::warning
Reutilizar el mismo `view` sin recrearlo no está permitido. Provocará un error.
:::
```typescript showLineNumbers

const view = await createFlowView(flow);

// Optional: handle flow events (close, purchase, restore, etc)
// await view.setEventHandlers({ ... });

try {
  await view.present();
} catch (error) {
  // handle the error
}
```

:::important
Llamar a `setEventHandlers` varias veces sobreescribirá los handlers que proporciones, reemplazando tanto los predeterminados como los establecidos anteriormente para esos eventos específicos.
:::
## Configura el estilo de presentación en iOS \{#configure-ios-presentation-style\}

Configura cómo se muestra el flow en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `'full_screen'` (por defecto) o `'page_sheet'`. En Android, los flows siempre se muestran como una actividad a pantalla completa.

```typescript showLineNumbers
try {
  await view.present({ iosPresentationStyle: 'page_sheet' });
} catch (error) {
  // handle the error
}
```
## Usar temporizadores definidos por el desarrollador \{#use-developer-defined-timer\}

Para usar temporizadores definidos por el desarrollador en tu app, utiliza el `timerId`, en este ejemplo `CUSTOM_TIMER_NY`, el **Timer ID** del temporizador definido por el desarrollador que configuraste en el Adapty dashboard. Esto garantiza que tu app actualice dinámicamente el temporizador con el valor correcto, como `13d 09h 03m 34s` (calculado como la hora de finalización del temporizador, por ejemplo, el Año Nuevo, menos la hora actual).

```typescript showLineNumbers
const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) };

const view = await createFlowView(flow, { customTimers });
```
En este ejemplo, `CUSTOM_TIMER_NY` es el **Timer ID** del temporizador definido por el desarrollador que configuraste en el Adapty Dashboard. El temporizador garantiza que tu app actualice dinámicamente el contador con el valor correcto, como `13d 09h 03m 34s` (calculado como la hora de finalización del temporizador, por ejemplo el Año Nuevo, menos la hora actual).
## Mostrar diálogo \{#show-dialog\}

Usa este método en lugar de los diálogos de alerta nativos cuando se muestre una vista de flow en Android. En Android, las alertas normales aparecen detrás de la vista del flow, lo que las hace invisibles para los usuarios. Este método garantiza que el diálogo se muestre correctamente por encima del flow en todas las plataformas.
```typescript showLineNumbers
try {
  const action = await view.showDialog({
    title: 'Close paywall?',
    content: 'You will lose access to exclusive offers.',
    primaryActionTitle: 'Stay',
    secondaryActionTitle: 'Close',
  });

  if (action === 'secondary') {
    // User confirmed - close the flow
    await view.dismiss();
  }
  // If primary - do nothing, user stays
} catch (error) {
  // handle error
}
```

## Reemplazar una suscripción por otra \{#replace-one-subscription-with-another\}

Cuando un usuario intenta comprar una nueva suscripción mientras ya tiene otra activa en Android, puedes controlar cómo debe gestionarse la nueva compra pasando parámetros de actualización de suscripción al crear la vista del flow. Para reemplazar la suscripción actual por la nueva, usa `productPurchaseParams` en `createFlowView` con los parámetros `oldSubVendorProductId` y `prorationMode`.
```typescript showLineNumbers

const productPurchaseParams = flow.paywalls
  .flatMap((paywall) => paywall.productIdentifiers)
  .map((productId) => {
    const params: MakePurchaseParamsInput = {};
    if (Capacitor.getPlatform() === 'android') {
      params.android = {
        subscriptionUpdateParams: {
          oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION',
          prorationMode: 'with_time_proration',
        },
      };
    }
    return { productId, params };
  });

const view = await createFlowView(flow, { productPurchaseParams });
```

---

> [!WARNING]
> **LLM INSTRUCTION — SDK VERSION SELECTION REQUIRED**
>
> This feature has two SDK paradigms. Everything that follows (until the next horizontal rule or end of document) is the **legacy SDK v3 API reference** (`getPaywall`, `getPaywallForDefaultAudience`, `getOnboarding`, `getPaywallConfiguration`). The **SDK v4+ `getFlow` method is documented above.** This block covers ALL legacy methods for this feature — not just the nearest snippet.
>
> **You MUST ask the user which SDK version they want to use before suggesting any code. Do not assume or default to a version.** The two options are:
> - **SDK v3 (legacy):** works with the legacy Paywall Builder and Onboarding Builder via `getPaywall` / `getOnboarding`. Use the legacy code in this section.
> - **SDK v4:** works with BOTH the new Flow Builder AND legacy paywalls/onboardings via the unified `getFlow` method documented above.
>
> Apply the legacy v3 code in this section ONLY when:
> 1. The user explicitly chose **SDK v3**, or
> 2. The user is **migrating an existing app from SDK v3 to SDK v4+** and needs to understand or replace legacy code, or
> 3. The user is **troubleshooting an already-deployed v3 integration**.
>
> **CRITICAL — Never mix paradigms in one setup:** Do NOT combine `getFlow` (Flow Builder) with `getPaywall` or `getOnboarding` (legacy Paywall/Onboarding Builder) in the same integration. These are incompatible patterns. Mixing them will produce inconsistent behavior and is unsupported.

Si has personalizado un paywall con el Paywall Builder, no necesitas preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese paywall contiene tanto qué mostrar como de qué forma mostrarlo.

:::warning
Esta guía es exclusivamente para **paywalls creados con el Paywall Builder**. El proceso para mostrar paywalls difiere en el caso de los paywalls con Remote Config. Para mostrar **paywalls con Remote Config**, consulta [Renderizar paywalls diseñados con Remote Config](present-remote-config-paywalls).
:::
Para mostrar un paywall, usa el método `view.present()` en el `view` creado por el método [`createPaywallView`](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder). Cada `view` solo puede usarse una vez. Si necesitas mostrar el paywall de nuevo, llama a `createPaywallView` otra vez para crear una nueva instancia de `view`.

:::warning

Reutilizar el mismo `view` sin recrearlo puede causar un error.
:::
```typescript showLineNumbers

const view = await createPaywallView(paywall);

view.setEventHandlers({
  onUrlPress(url) {
    window.open(url, '_blank');
    return false;
  },
});

try {
  await view.present();
} catch (error) {
  // handle the error
}
```

## Usar temporizadores definidos por el desarrollador \{#use-developer-defined-timer\}

Para usar temporizadores definidos por el desarrollador en tu app, utiliza el `timerId`; en este ejemplo, `CUSTOM_TIMER_NY`, el **Timer ID** del temporizador definido por el desarrollador que configuraste en el Adapty dashboard. Esto garantiza que tu app actualice dinámicamente el temporizador con el valor correcto, como `13d 09h 03m 34s` (calculado como la hora de finalización del temporizador, por ejemplo, el Año Nuevo, menos la hora actual).

```typescript showLineNumbers
const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) };

const view = await createPaywallView(paywall, { customTimers });
```
En este ejemplo, `CUSTOM_TIMER_NY` es el **Timer ID** del temporizador definido por el desarrollador que configuraste en el Adapty dashboard. El temporizador garantiza que tu app actualice dinámicamente el temporizador con el valor correcto, como `13d 09h 03m 34s` (calculado como la hora de finalización del temporizador, por ejemplo el Año Nuevo, menos la hora actual).
## Mostrar un diálogo \{#show-dialog\}

Usa este método en lugar de los diálogos de alerta nativos cuando haya una vista de paywall en pantalla en Android. En Android, las alertas normales aparecen detrás de la vista del paywall, lo que las hace invisibles para los usuarios. Este método garantiza que el diálogo se muestre correctamente por encima del paywall en todas las plataformas.
```typescript showLineNumbers title="Capacitor"
try {
  const action = await view.showDialog({
    title: 'Close paywall?',
    content: 'You will lose access to exclusive offers.',
    primaryActionTitle: 'Stay',
    secondaryActionTitle: 'Close',
  });

  if (action === 'secondary') {
    // User confirmed - close the paywall
    await view.dismiss();
  }
  // If primary - do nothing, user stays
} catch (error) {
  // handle error
}
```

## Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\}

Configura cómo se presenta el paywall en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `'full_screen'` (por defecto) o `'page_sheet'`.

```typescript showLineNumbers
await view.present({ iosPresentationStyle: 'page_sheet' });
```

---