> ## 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.

# Button Click Listener

Intercept UI button clicks with `ButtonClickListeners`. This listener provides callbacks when users tap buttons in the call UI, allowing you to implement custom behavior or show confirmation dialogs.

## Prerequisites

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

## Register Listener

Register a `ButtonClickListeners` to receive button click callbacks:

```dart theme={null}
final callSession = CallSession.getInstance();

callSession?.addButtonClickListener(ButtonClickListeners(
  onLeaveSessionButtonClicked: () {
    debugPrint("Leave button clicked");
  },
  onToggleAudioButtonClicked: () {
    debugPrint("Audio toggle button clicked");
  },
  onToggleVideoButtonClicked: () {
    debugPrint("Video toggle button clicked");
  },
  // Additional callbacks...
));
```

<Warning>
  Flutter listeners are **not** lifecycle-aware. You must manually remove listeners in your widget's `dispose()` method to prevent memory leaks.
</Warning>

***

## Callbacks

### onLeaveSessionButtonClicked

Triggered when the user taps the leave session button.

```dart theme={null}
onLeaveSessionButtonClicked: () {
  debugPrint("Leave button clicked");
  // Show confirmation dialog before leaving
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text("Leave Call"),
      content: const Text("Are you sure you want to leave this call?"),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text("Cancel"),
        ),
        TextButton(
          onPressed: () async {
            Navigator.pop(context);
            await CallSession.getInstance()?.leaveSession();
          },
          child: const Text("Leave"),
        ),
      ],
    ),
  );
}
```

**Use Cases:**

* Show confirmation dialog before leaving
* Log analytics event
* Perform cleanup before leaving

***

### onToggleAudioButtonClicked

Triggered when the user taps the audio mute/unmute button.

```dart theme={null}
onToggleAudioButtonClicked: () {
  debugPrint("Audio toggle clicked");
  // Track audio toggle analytics
}
```

**Use Cases:**

* Log analytics events
* Show tooltip on first use
* Implement custom audio toggle logic

***

### onToggleVideoButtonClicked

Triggered when the user taps the video on/off button.

```dart theme={null}
onToggleVideoButtonClicked: () {
  debugPrint("Video toggle clicked");
  // Track video toggle analytics
}
```

**Use Cases:**

* Log analytics events
* Check camera permissions
* Implement custom video toggle logic

***

### onSwitchCameraButtonClicked

Triggered when the user taps the switch camera button.

```dart theme={null}
onSwitchCameraButtonClicked: () {
  debugPrint("Switch camera clicked");
  // Track camera switch analytics
}
```

**Use Cases:**

* Log analytics events
* Show camera switching animation
* Track front/back camera usage

***

### onRaiseHandButtonClicked

Triggered when the user taps the raise hand button.

```dart theme={null}
onRaiseHandButtonClicked: () {
  debugPrint("Raise hand clicked");
  // Show hand raised confirmation
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text("Hand raised")),
  );
}
```

**Use Cases:**

* Show confirmation feedback
* Log analytics events
* Implement custom hand raise behavior

***

### onShareInviteButtonClicked

Triggered when the user taps the share invite button.

```dart theme={null}
onShareInviteButtonClicked: () {
  debugPrint("Share invite clicked");
  // Show custom share dialog
  Share.share("Join my call: https://example.com/call/$sessionId");
}
```

**Use Cases:**

* Show custom share sheet
* Generate and share invite link
* Copy link to clipboard

***

### onChangeLayoutButtonClicked

Triggered when the user taps the change layout button.

```dart theme={null}
onChangeLayoutButtonClicked: () {
  debugPrint("Change layout clicked");
  // Show layout options dialog
  showDialog(
    context: context,
    builder: (context) => SimpleDialog(
      title: const Text("Select Layout"),
      children: [
        SimpleDialogOption(
          onPressed: () async {
            Navigator.pop(context);
            await CallSession.getInstance()?.setLayout(LayoutType.tile);
          },
          child: const Text("Tile"),
        ),
        SimpleDialogOption(
          onPressed: () async {
            Navigator.pop(context);
            await CallSession.getInstance()?.setLayout(LayoutType.spotlight);
          },
          child: const Text("Spotlight"),
        ),
      ],
    ),
  );
}
```

**Use Cases:**

* Show custom layout picker
* Log layout change analytics
* Implement custom layout switching

***

### onParticipantListButtonClicked

Triggered when the user taps the participant list button.

```dart theme={null}
onParticipantListButtonClicked: () {
  debugPrint("Participant list clicked");
  // Track participant list views
}
```

**Use Cases:**

* Log analytics events
* Show custom participant list UI
* Track feature usage

***

### onChatButtonClicked

Triggered when the user taps the chat button.

```dart theme={null}
onChatButtonClicked: () {
  debugPrint("Chat button clicked");
  // Open custom chat UI
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => ChatScreen(sessionId: sessionId),
    ),
  );
}
```

**Use Cases:**

* Open custom chat interface
* Show in-call messaging overlay
* Navigate to chat screen

***

### onRecordingToggleButtonClicked

Triggered when the user taps the recording button.

```dart theme={null}
onRecordingToggleButtonClicked: () {
  debugPrint("Recording toggle clicked");
  // Show recording consent dialog
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text("Start Recording"),
      content: const Text(
        "All participants will be notified that this call is being recorded.",
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text("Cancel"),
        ),
        TextButton(
          onPressed: () async {
            Navigator.pop(context);
            await CallSession.getInstance()?.startRecording();
          },
          child: const Text("Start"),
        ),
      ],
    ),
  );
}
```

**Use Cases:**

* Show recording consent dialog
* Check recording permissions
* Log recording analytics

***

## Complete Example

Here's a complete example handling all button click events:

```dart theme={null}
import 'package:cometchat_calls_sdk/cometchat_calls_sdk.dart';
import 'package:flutter/material.dart';

class CallScreen extends StatefulWidget {
  final String sessionId;

  const CallScreen({super.key, required this.sessionId});

  @override
  State<CallScreen> createState() => _CallScreenState();
}

class _CallScreenState extends State<CallScreen> {
  CallSession? _callSession;
  ButtonClickListeners? _buttonClickListener;

  @override
  void initState() {
    super.initState();
    _callSession = CallSession.getInstance();
    _setupButtonClickListener();
  }

  void _setupButtonClickListener() {
    _buttonClickListener = ButtonClickListeners(
      onLeaveSessionButtonClicked: () {
        _showLeaveConfirmationDialog();
      },
      onToggleAudioButtonClicked: () {
        debugPrint("Audio toggle clicked");
      },
      onToggleVideoButtonClicked: () {
        debugPrint("Video toggle clicked");
      },
      onSwitchCameraButtonClicked: () {
        debugPrint("Switch camera clicked");
      },
      onRaiseHandButtonClicked: () {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("Hand raised")),
          );
        }
      },
      onShareInviteButtonClicked: () {
        _shareCallLink();
      },
      onChangeLayoutButtonClicked: () {
        _showLayoutOptionsDialog();
      },
      onParticipantListButtonClicked: () {
        debugPrint("Participant list opened");
      },
      onChatButtonClicked: () {
        _openChatScreen();
      },
      onRecordingToggleButtonClicked: () {
        _showRecordingConsentDialog();
      },
    );

    _callSession?.addButtonClickListener(_buttonClickListener!);
  }

  void _showLeaveConfirmationDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text("Leave Call"),
        content: const Text("Are you sure you want to leave?"),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text("Cancel"),
          ),
          TextButton(
            onPressed: () async {
              Navigator.pop(context);
              await _callSession?.leaveSession();
            },
            child: const Text("Leave"),
          ),
        ],
      ),
    );
  }

  void _shareCallLink() {
    // Use share_plus or similar package
    debugPrint("Share call link: ${widget.sessionId}");
  }

  void _showLayoutOptionsDialog() {
    showDialog(
      context: context,
      builder: (context) => SimpleDialog(
        title: const Text("Select Layout"),
        children: [
          SimpleDialogOption(
            onPressed: () async {
              Navigator.pop(context);
              await _callSession?.setLayout(LayoutType.tile);
            },
            child: const Text("Tile"),
          ),
          SimpleDialogOption(
            onPressed: () async {
              Navigator.pop(context);
              await _callSession?.setLayout(LayoutType.spotlight);
            },
            child: const Text("Spotlight"),
          ),
        ],
      ),
    );
  }

  void _openChatScreen() {
    // Navigate to chat screen
    debugPrint("Open chat for session: ${widget.sessionId}");
  }

  void _showRecordingConsentDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text("Start Recording"),
        content: const Text("All participants will be notified."),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text("Cancel"),
          ),
          TextButton(
            onPressed: () async {
              Navigator.pop(context);
              await _callSession?.startRecording();
            },
            child: const Text("Start"),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    // Must manually remove listener to prevent memory leaks
    if (_buttonClickListener != null) {
      _callSession?.removeButtonClickListener(_buttonClickListener!);
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text("Call UI"),
      ),
    );
  }
}
```

***

## Remove Listener

Remove the listener in your widget's `dispose()` method to prevent memory leaks:

```dart theme={null}
@override
void dispose() {
  if (_buttonClickListener != null) {
    _callSession?.removeButtonClickListener(_buttonClickListener!);
  }
  super.dispose();
}
```

***

## Callbacks Summary

| Callback                         | Description                         |
| -------------------------------- | ----------------------------------- |
| `onLeaveSessionButtonClicked`    | Leave session button was tapped     |
| `onToggleAudioButtonClicked`     | Audio mute/unmute button was tapped |
| `onToggleVideoButtonClicked`     | Video on/off button was tapped      |
| `onSwitchCameraButtonClicked`    | Switch camera button was tapped     |
| `onRaiseHandButtonClicked`       | Raise hand button was tapped        |
| `onShareInviteButtonClicked`     | Share invite button was tapped      |
| `onChangeLayoutButtonClicked`    | Change layout button was tapped     |
| `onParticipantListButtonClicked` | Participant list button was tapped  |
| `onChatButtonClicked`            | Chat button was tapped              |
| `onRecordingToggleButtonClicked` | Recording toggle button was tapped  |

## Hide Buttons

You can hide specific buttons using [SessionSettings](/calls/flutter/session-settings):

```dart theme={null}
final sessionSettings = CometChatCalls.SessionSettingsBuilder()
    .hideLeaveSessionButton(false)
    .hideToggleAudioButton(false)
    .hideToggleVideoButton(false)
    .hideSwitchCameraButton(false)
    .hideRaiseHandButton(false)
    .hideShareInviteButton(true)
    .hideChangeLayoutButton(false)
    .hideParticipantListButton(false)
    .hideChatButton(true)
    .hideRecordingButton(true)
    .build();
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Layout Listener" icon="table-cells" href="/calls/flutter/layout-listener">
    Handle layout change events
  </Card>

  <Card title="Session Settings" icon="gear" href="/calls/flutter/session-settings">
    Configure button visibility
  </Card>
</CardGroup>
