# Visual constructor

***

Test out the best Paywalls and Welcome pages of your Android Apps with Appflow\.ai Visual Constructor

### **Paywall**

The SDK provides a shortcut for displaying paid products. After setting the style in Appflow\.ai's [remote constructor](/docs/subscription-analytics/visual-constructor.md), you can display it by call method:

```kotlin
Appflow.showPaywall(context: Context, listener: PaywallListener)
```

When the user clicks the back button, the paywall will automatically close, you can also actively close the following methods

```kotlin
Appflow.closePaywall()
```

#### &#x20;**Example**

```kotlin
Appflow.showPaywall(context, object : Appflow.PaywallListener {
    override fun onPurchaseCompleted(purchase: Purchase) {
        Toast.makeText(this@MainActivity, "successful purchase ${purchase.skus}", Toast.LENGTH_SHORT).show()
    }

    override fun onClose() {}

    override fun onFail(msg: String?) {
        Toast.makeText(this@MainActivity, "show paywall fail $msg", Toast.LENGTH_LONG).show()
        // or
        // Appflow.closePaywall()
    }
})
```

#### **API Reference**

| PaywallListener                         |                                                           |
| --------------------------------------- | --------------------------------------------------------- |
| onPurchaseCompleted(purchase: Purchase) | onPurchaseCompleted(purchase: Purchase)                   |
| onClose()                               | This method is called when the user closes the paywall    |
| onFail(msg: String?)                    | This method will be called when the paywall loading error |

### **WelcomePage**

The SDK provides a welcome page that you can add to your application in the following ways

add in layout page

```kotlin
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <com.imp.page.welcome.WelcomeView
        android:id="@+id/welcomeView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
```

or dynamically add in the code

```kotlin
class SplashActivity : Activity() {

    private lateinit var mWelcomeView: WelcomeView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mWelcomeView = WelcomeView(this)
        setContentView(mWelcomeView)
    }
}
```

{% hint style="info" %} <mark style="color:blue;">**NOTE**</mark>

WelcomePage supports timeout setting，the default timeout is 30 seconds，you can set it in the following ways：
{% endhint %}

&#x20;a、 in layout page，add timeOut property

```kotlin
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">

    <!-- Set the timeout to 5 seconds -->
    <com.imp.page.welcome.WelcomeView
        android:id="@+id/welcomeView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:timeOut="5"/>

</FrameLayout>
```

b、in the code, set by the constructor&#x20;

```kotlin
class SplashActivity : Activity() {

    private lateinit var mWelcomeView: WelcomeView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mWelcomeView = WelcomeView(this, 5)//Set the timeout to 5 seconds
        setContentView(mWelcomeView)
    }
}
```

When WelcomePage displays success, failure, or timeout, it will tell you through WelcomeViewListener

```
WelcomeView.setListener(listener: WelcomeViewListener)
```

#### &#x20;**Example**&#x20;

```kotlin
class SplashActivity : AppCompatActivity() {

    private lateinit var mWelcomeView: WelcomeView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)

        mWelcomeView = findViewById(R.id.welcomeView)
        mWelcomeView.setListener(object : WelcomeView.WelcomeViewListener {
            override fun onShow() {
                Handler(Looper.getMainLooper()).postDelayed({ goMain() }, 2000)
            }

            override fun onFail(t: Throwable) {
                goMain()
            }
        })
    }

    private fun goMain() {
        startActivity(Intent(this@SplashActivity, MainActivity::class.java))
        finish()
    }

    override fun onBackPressed() {}
}
```

#### **API Reference**&#x20;

| WelcomeViewListener  |                                 |
| -------------------- | ------------------------------- |
| onShow()             | Success callback                |
| onFail(t: Throwable) | Callback when fails or time out |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.appflow.ai/docs/sdk-set-up-instructions/android-sdk/visual-constructor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
