> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-v6-beta2-flutter-uikit.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Layout Listener

Monitor layout changes with `LayoutListener`. This listener provides callbacks for call layout changes, participant list visibility, and Picture-in-Picture (PiP) mode state changes.

## Prerequisites

* An active [call session](/calls/android/join-session)
* Access to the `CallSession` instance

## Register Listener

Register a `LayoutListener` to receive layout event callbacks:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    val callSession = CallSession.getInstance()

    callSession.addLayoutListener(this, object : LayoutListener() {
        override fun onCallLayoutChanged(layoutType: LayoutType) {
            Log.d(TAG, "Layout changed to: $layoutType")
        }

        override fun onParticipantListVisible() {
            Log.d(TAG, "Participant list is now visible")
        }

        override fun onParticipantListHidden() {
            Log.d(TAG, "Participant list is now hidden")
        }

        override fun onPictureInPictureLayoutEnabled() {
            Log.d(TAG, "PiP mode enabled")
        }

        override fun onPictureInPictureLayoutDisabled() {
            Log.d(TAG, "PiP mode disabled")
        }
    })
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    CallSession callSession = CallSession.getInstance();

    callSession.addLayoutListener(this, new LayoutListener() {
        @Override
        public void onCallLayoutChanged(LayoutType layoutType) {
            Log.d(TAG, "Layout changed to: " + layoutType);
        }

        @Override
        public void onParticipantListVisible() {
            Log.d(TAG, "Participant list is now visible");
        }

        @Override
        public void onParticipantListHidden() {
            Log.d(TAG, "Participant list is now hidden");
        }

        @Override
        public void onPictureInPictureLayoutEnabled() {
            Log.d(TAG, "PiP mode enabled");
        }

        @Override
        public void onPictureInPictureLayoutDisabled() {
            Log.d(TAG, "PiP mode disabled");
        }
    });
    ```
  </Tab>
</Tabs>

<Note>
  The listener is automatically removed when the `LifecycleOwner` (Activity/Fragment) is destroyed, preventing memory leaks.
</Note>

***

## Callbacks

### onCallLayoutChanged

Triggered when the call layout changes between Tile and Spotlight modes.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onCallLayoutChanged(layoutType: LayoutType) {
        Log.d(TAG, "Layout changed to: $layoutType")
        
        when (layoutType) {
            LayoutType.TILE -> {
                // Update UI for tile layout
                updateLayoutIcon(R.drawable.ic_grid_view)
            }
            LayoutType.SPOTLIGHT -> {
                // Update UI for spotlight layout
                updateLayoutIcon(R.drawable.ic_spotlight)
            }
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onCallLayoutChanged(LayoutType layoutType) {
        Log.d(TAG, "Layout changed to: " + layoutType);
        
        switch (layoutType) {
            case TILE:
                // Update UI for tile layout
                updateLayoutIcon(R.drawable.ic_grid_view);
                break;
            case SPOTLIGHT:
                // Update UI for spotlight layout
                updateLayoutIcon(R.drawable.ic_spotlight);
                break;
        }
    }
    ```
  </Tab>
</Tabs>

**LayoutType Values:**

| Value       | Description                                    |
| ----------- | ---------------------------------------------- |
| `TILE`      | Grid layout showing all participants equally   |
| `SPOTLIGHT` | Focus on active speaker with others in sidebar |

**Use Cases:**

* Update layout toggle button icon
* Adjust custom UI overlays
* Log layout preference analytics

***

### onParticipantListVisible

Triggered when the participant list panel becomes visible.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onParticipantListVisible() {
        Log.d(TAG, "Participant list opened")
        // Track analytics
        analytics.logEvent("participant_list_opened")
        // Adjust UI if needed
        adjustUIForParticipantList(isVisible = true)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onParticipantListVisible() {
        Log.d(TAG, "Participant list opened");
        // Track analytics
        analytics.logEvent("participant_list_opened");
        // Adjust UI if needed
        adjustUIForParticipantList(true);
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Log analytics events
* Adjust custom UI elements
* Pause other UI animations

***

### onParticipantListHidden

Triggered when the participant list panel is hidden.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onParticipantListHidden() {
        Log.d(TAG, "Participant list closed")
        // Restore UI
        adjustUIForParticipantList(isVisible = false)
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onParticipantListHidden() {
        Log.d(TAG, "Participant list closed");
        // Restore UI
        adjustUIForParticipantList(false);
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Restore UI elements
* Resume animations
* Update button states

***

### onPictureInPictureLayoutEnabled

Triggered when Picture-in-Picture (PiP) mode is enabled.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onPictureInPictureLayoutEnabled() {
        Log.d(TAG, "PiP mode enabled")
        // Hide non-essential UI elements
        hideCallControls()
        // Track PiP usage
        analytics.logEvent("pip_enabled")
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onPictureInPictureLayoutEnabled() {
        Log.d(TAG, "PiP mode enabled");
        // Hide non-essential UI elements
        hideCallControls();
        // Track PiP usage
        analytics.logEvent("pip_enabled");
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Hide call control buttons
* Simplify UI for small window
* Track PiP feature usage

***

### onPictureInPictureLayoutDisabled

Triggered when Picture-in-Picture (PiP) mode is disabled.

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    override fun onPictureInPictureLayoutDisabled() {
        Log.d(TAG, "PiP mode disabled")
        // Restore full UI
        showCallControls()
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    @Override
    public void onPictureInPictureLayoutDisabled() {
        Log.d(TAG, "PiP mode disabled");
        // Restore full UI
        showCallControls();
    }
    ```
  </Tab>
</Tabs>

**Use Cases:**

* Restore call control buttons
* Show full call UI
* Resume normal layout

***

## Complete Example

Here's a complete example handling all layout events:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class CallActivity : AppCompatActivity() {
        private lateinit var callSession: CallSession
        private lateinit var layoutButton: ImageButton
        private lateinit var controlsContainer: View

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

            initViews()
            callSession = CallSession.getInstance()
            setupLayoutListener()
        }

        private fun initViews() {
            layoutButton = findViewById(R.id.layoutButton)
            controlsContainer = findViewById(R.id.controlsContainer)
        }

        private fun setupLayoutListener() {
            callSession.addLayoutListener(this, object : LayoutListener() {
                override fun onCallLayoutChanged(layoutType: LayoutType) {
                    runOnUiThread {
                        when (layoutType) {
                            LayoutType.TILE -> {
                                layoutButton.setImageResource(R.drawable.ic_grid_view)
                                layoutButton.contentDescription = "Switch to spotlight"
                            }
                            LayoutType.SPOTLIGHT -> {
                                layoutButton.setImageResource(R.drawable.ic_spotlight)
                                layoutButton.contentDescription = "Switch to tile"
                            }
                        }
                    }
                }

                override fun onParticipantListVisible() {
                    runOnUiThread {
                        Log.d(TAG, "Participant list visible")
                        // Dim background or adjust layout
                    }
                }

                override fun onParticipantListHidden() {
                    runOnUiThread {
                        Log.d(TAG, "Participant list hidden")
                        // Restore normal layout
                    }
                }

                override fun onPictureInPictureLayoutEnabled() {
                    runOnUiThread {
                        Log.d(TAG, "PiP enabled")
                        // Hide controls for PiP mode
                        controlsContainer.visibility = View.GONE
                    }
                }

                override fun onPictureInPictureLayoutDisabled() {
                    runOnUiThread {
                        Log.d(TAG, "PiP disabled")
                        // Show controls when exiting PiP
                        controlsContainer.visibility = View.VISIBLE
                    }
                }
            })
        }

        // Enable PiP when user presses home button
        override fun onUserLeaveHint() {
            super.onUserLeaveHint()
            if (callSession.isSessionActive()) {
                callSession.enablePictureInPictureLayout()
            }
        }

        companion object {
            private const val TAG = "CallActivity"
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class CallActivity extends AppCompatActivity {
        private static final String TAG = "CallActivity";
        private CallSession callSession;
        private ImageButton layoutButton;
        private View controlsContainer;

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

            initViews();
            callSession = CallSession.getInstance();
            setupLayoutListener();
        }

        private void initViews() {
            layoutButton = findViewById(R.id.layoutButton);
            controlsContainer = findViewById(R.id.controlsContainer);
        }

        private void setupLayoutListener() {
            callSession.addLayoutListener(this, new LayoutListener() {
                @Override
                public void onCallLayoutChanged(LayoutType layoutType) {
                    runOnUiThread(() -> {
                        switch (layoutType) {
                            case TILE:
                                layoutButton.setImageResource(R.drawable.ic_grid_view);
                                layoutButton.setContentDescription("Switch to spotlight");
                                break;
                            case SPOTLIGHT:
                                layoutButton.setImageResource(R.drawable.ic_spotlight);
                                layoutButton.setContentDescription("Switch to tile");
                                break;
                        }
                    });
                }

                @Override
                public void onParticipantListVisible() {
                    runOnUiThread(() -> {
                        Log.d(TAG, "Participant list visible");
                        // Dim background or adjust layout
                    });
                }

                @Override
                public void onParticipantListHidden() {
                    runOnUiThread(() -> {
                        Log.d(TAG, "Participant list hidden");
                        // Restore normal layout
                    });
                }

                @Override
                public void onPictureInPictureLayoutEnabled() {
                    runOnUiThread(() -> {
                        Log.d(TAG, "PiP enabled");
                        // Hide controls for PiP mode
                        controlsContainer.setVisibility(View.GONE);
                    });
                }

                @Override
                public void onPictureInPictureLayoutDisabled() {
                    runOnUiThread(() -> {
                        Log.d(TAG, "PiP disabled");
                        // Show controls when exiting PiP
                        controlsContainer.setVisibility(View.VISIBLE);
                    });
                }
            });
        }

        // Enable PiP when user presses home button
        @Override
        protected void onUserLeaveHint() {
            super.onUserLeaveHint();
            if (callSession.isSessionActive()) {
                callSession.enablePictureInPictureLayout();
            }
        }
    }
    ```
  </Tab>
</Tabs>

***

## Controlling Layout Programmatically

You can change the layout and PiP state programmatically:

### Change Layout

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Switch to tile layout
    callSession.setLayout(LayoutType.TILE)

    // Switch to spotlight layout
    callSession.setLayout(LayoutType.SPOTLIGHT)
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    // Switch to tile layout
    callSession.setLayout(LayoutType.TILE);

    // Switch to spotlight layout
    callSession.setLayout(LayoutType.SPOTLIGHT);
    ```
  </Tab>
</Tabs>

### Enable/Disable PiP

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Enable Picture-in-Picture
    callSession.enablePictureInPictureLayout()

    // Disable Picture-in-Picture
    callSession.disablePictureInPictureLayout()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    // Enable Picture-in-Picture
    callSession.enablePictureInPictureLayout();

    // Disable Picture-in-Picture
    callSession.disablePictureInPictureLayout();
    ```
  </Tab>
</Tabs>

***

## Initial Layout Configuration

Set the initial layout when joining a session:

<Tabs>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    val sessionSettings = CometChatCalls.SessionSettingsBuilder()
        .setLayout(LayoutType.TILE)  // or LayoutType.SPOTLIGHT
        .hideChangeLayoutButton(false)  // Allow users to change layout
        .build()
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    SessionSettings sessionSettings = new CometChatCalls.SessionSettingsBuilder()
        .setLayout(LayoutType.TILE)  // or LayoutType.SPOTLIGHT
        .hideChangeLayoutButton(false)  // Allow users to change layout
        .build();
    ```
  </Tab>
</Tabs>

***

## Callbacks Summary

| Callback                           | Parameter    | Description                          |
| ---------------------------------- | ------------ | ------------------------------------ |
| `onCallLayoutChanged`              | `LayoutType` | Call layout changed (TILE/SPOTLIGHT) |
| `onParticipantListVisible`         | -            | Participant list panel opened        |
| `onParticipantListHidden`          | -            | Participant list panel closed        |
| `onPictureInPictureLayoutEnabled`  | -            | PiP mode was enabled                 |
| `onPictureInPictureLayoutDisabled` | -            | PiP mode was disabled                |

## Next Steps

<CardGroup cols={2}>
  <Card title="Layout & UI" icon="table-cells" href="/calls/android/layout-ui">
    Control layout programmatically
  </Card>

  <Card title="Session Settings" icon="gear" href="/calls/android/session-settings">
    Configure initial layout settings
  </Card>
</CardGroup>
