Closed yokawaiik closed 7 months ago
Enable/disable sound from the user's device if you mean turn on/off microphone, just call
ZegoUIKit().turnMicrophoneOn()
Enable/disable video from the user's device if you mean turn on/off camera, just call
ZegoUIKit().turnCameraOn()
Adding a custom timer at the bottom of the call settting duration config in ZegoUIKitPrebuiltCallConfig:
/// hide countdown in UIKit
config.duration.isVisible = false;
/// show your custom countdown
config.duration.onDurationUpdate = (Duration duration) {
/// update your custom countdown value notifier
};
and you can add your countdown widget by ZegoUIKitPrebuiltCallConfig.foreground
containerRect: Specify the rect of the audio & video container. If not specified, it defaults to display full.
containerBuilder: Custom audio/video view. If you don't want to use the default view components, you can pass a custom component through this parameter. and if return null, will be display the default view
You can use containerBuilder and containerRect to draw anything you want in the specified area.
Like the layout below:
// Flutter imports:
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
// Package imports:
import 'package:zego_uikit_prebuilt_call/zego_uikit_prebuilt_call.dart';
class CallPage extends StatefulWidget {
const CallPage({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => CallPageState();
}
class CallPageState extends State<CallPage> {
final durationNotifier = ValueNotifier<Duration>(Duration.zero);
double get bottomBarHeight => 100;
double get topPadding => 100;
double get hangUpButtonSize => 50;
double get hangUpButtonPadding => 30;
double get audioVideoViewSize {
final size = MediaQuery.of(context).size;
final audioVideoViewSize = size.width / 5 * 2;
return audioVideoViewSize;
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: ZegoUIKitPrebuiltCall(
appID: yourAppID /*input your AppID*/,
appSign: yourAppSign /*input your AppSign*/,
userID: 'userID',
userName: 'userName',
callID: 'callID',
config: ZegoUIKitPrebuiltCallConfig.groupVideoCall()
..avatarBuilder = customAvatarBuilder
..background = Container(
color: Colors.black,
)
..foreground = foreground()
..turnOnCameraWhenJoining = false
..audioVideoView.showUserNameOnView = false
..audioVideoView.useVideoViewAspectFill = true
..audioVideoView.containerRect = () {
final size = MediaQuery.of(context).size;
final padding = MediaQuery.of(context).padding;
final height = size.height - padding.bottom - padding.top;
return Rect.fromLTWH(
0,
bottomBarHeight,
size.width,
height - topPadding - bottomBarHeight,
);
}
..audioVideoView.containerBuilder = (
context,
allUsers,
audioVideoUsers,
audioVideoViewCreator,
) {
return Column(
children: audioVideoUsers
.map((user) => audioVideoView(
user,
audioVideoViewCreator,
))
.toList(),
);
}
..duration.isVisible = false
..duration.onDurationUpdate = (Duration duration) {
durationNotifier.value = duration;
}
..topMenuBar.isVisible = false
..bottomMenuBar.isVisible = false,
),
);
}
Widget audioVideoView(
ZegoUIKitUser user,
ZegoAudioVideoView Function(ZegoUIKitUser) defaultViewCreator,
) {
final size = MediaQuery.of(context).size;
return SizedBox(
width: size.width / 3 * 2,
height: size.width / 3 * 2,
child: Stack(
children: [
Positioned(
left: 0,
right: 0,
child: ClipOval(
child: SizedBox(
width: audioVideoViewSize,
height: audioVideoViewSize,
child: avatarView(user),
),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: SizedBox(
width: size.width,
child: Text(
user.name,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
),
textAlign: TextAlign.center,
),
),
),
],
),
);
}
Widget avatarView(ZegoUIKitUser user) {
return CachedNetworkImage(
imageUrl:
'https://i.pinimg.com/736x/82/a1/74/82a174dc4b695259ba1ecb92204c6076.jpg',
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
shape: BoxShape.circle,
image: DecorationImage(
image: imageProvider,
fit: BoxFit.contain,
),
),
),
progressIndicatorBuilder: (context, url, downloadProgress) =>
CircularProgressIndicator(value: downloadProgress.progress),
errorWidget: (context, url, error) {
return Container();
},
);
}
Widget foreground() {
return Stack(
children: [
bottomBar(),
hangUpBackground(),
hangUpButton(),
duration(),
],
);
}
String durationFormatString(Duration elapsedTime) {
final hours = elapsedTime.inHours;
final minutes = elapsedTime.inMinutes.remainder(60);
final seconds = elapsedTime.inSeconds.remainder(60);
final minutesFormatString =
'${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
return hours > 0
? '${hours.toString().padLeft(2, '0')}:$minutesFormatString'
: minutesFormatString;
}
Widget duration() {
final size = MediaQuery.of(context).size;
const spacing = 150;
return Positioned(
bottom: bottomBarHeight + spacing,
left: 0,
right: 0,
child: ValueListenableBuilder<Duration>(
valueListenable: durationNotifier,
builder: (context, duration, _) {
return Center(
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(5),
),
child: Text(
durationFormatString(duration),
style: TextStyle(color: Colors.white),
),
),
);
},
),
);
}
Widget bottomBar() {
return Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: bottomBarHeight,
decoration: BoxDecoration(color: Colors.lightBlue.withOpacity(0.5)),
child: Stack(
children: [
bottomBarBackground(),
microphoneButton(),
moreButton(),
],
),
),
);
}
Widget microphoneButton() {
return Align(
alignment: Alignment.bottomLeft,
child: GestureDetector(
onTap: () {
ZegoUIKitPrebuiltCallController().audioVideo.microphone.switchState();
},
child: ValueListenableBuilder<bool>(
valueListenable: ZegoUIKitPrebuiltCallController()
.audioVideo
.microphone
.localStateNotifier,
builder: (context, isMicrophoneOn, _) {
return Container(
width: 30.0,
height: 30.0,
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(8.0),
),
child: Icon(
isMicrophoneOn ? Icons.mic : Icons.mic_off,
color: Colors.white,
),
);
},
),
),
);
}
Widget moreButton() {
return Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
onTap: () {},
child: Container(
width: 30.0,
height: 30.0,
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(8.0),
),
child: const Icon(Icons.more, color: Colors.white),
),
),
);
}
Widget bottomBarBackground() {
final size = MediaQuery.of(context).size;
return Align(
alignment: Alignment.topCenter,
child: Container(
width: size.width,
height: bottomBarHeight / 5 * 2,
color: Colors.black,
),
);
}
Widget hangUpBackground() {
final size = MediaQuery.of(context).size;
return Positioned(
bottom: bottomBarHeight - hangUpButtonSize - hangUpButtonPadding,
left: size.width / 2 - (hangUpButtonSize + hangUpButtonPadding) / 2,
right: size.width / 2 - (hangUpButtonSize + hangUpButtonPadding) / 2,
child: ClipOval(
child: Container(
width: hangUpButtonSize + hangUpButtonPadding,
height: hangUpButtonSize + hangUpButtonPadding,
color: Colors.black,
),
),
);
}
Widget hangUpButton() {
final size = MediaQuery.of(context).size;
return Positioned(
bottom: bottomBarHeight - hangUpButtonPadding * 2,
left: size.width / 2 - (hangUpButtonSize / 2),
right: size.width / 2 - (hangUpButtonSize / 2),
child: ClipOval(
child: GestureDetector(
onTap: () {
ZegoUIKitPrebuiltCallController().hangUp(
context,
showConfirmation: true,
);
},
child: Container(
width: hangUpButtonSize,
height: hangUpButtonSize,
decoration: const BoxDecoration(color: Colors.red),
child: const Icon(Icons.phone, color: Colors.white),
),
),
),
);
}
}
Enable/disable sound from the user's device
now you can use ZegoUIKitPrebuiltCallController().audioVideo.microphone.turnOn(isOn);
Enable/disable video from the user's device
now you can use ZegoUIKitPrebuiltCallController().audioVideo.camera.turnOn(isOn);
please use version more than v4.8.0
Hello, I need to make a custom UI, but at the moment it’s not clear how:
I have the following code now:
Code for video call with invitation
```dart import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:zego_uikit_prebuilt_call/zego_uikit_prebuilt_call.dart'; import 'package:zego_uikit_signaling_plugin/zego_uikit_signaling_plugin.dart'; import '../constants/videocalls_constants.dart'; import '../utils/get_doc_ref_by_doc_id.dart'; import '../actions/on_hang_up_confirmation_action.dart'; class VideocallsService { late final GlobalKey globalCallNavigatorKey;
String? _userID;
VideocallsService() {
globalCallNavigatorKey = GlobalKey();
// To add duration for video call
ZegoUIKitPrebuiltCallInvitationService()
.setNavigatorKey(globalCallNavigatorKey);
/// initialized ZegoUIKitPrebuiltCallInvitationService
}
void init({
required String userID,
required String userName,
}) {
if (ZegoUIKitPrebuiltCallInvitationService().isInit) {
return;
}
_userID = userID;
/// initialized ZegoUIKitPrebuiltCallInvitationService
/// when app's user is logged in or re-logged in
/// We recommend calling this method as soon as the user logs in to your app.
ZegoUIKitPrebuiltCallInvitationService().init(
appID: VideocallsConstants.kAppID /*input your AppID*/,
appSign: VideocallsConstants.kAppSign /*input your AppSign*/,
userID: _userID!,
userName: userName,
plugins: [
ZegoUIKitSignalingPlugin(),
],
notificationConfig: ZegoCallInvitationNotificationConfig(
androidNotificationConfig: ZegoCallAndroidNotificationConfig(
showFullScreen: true,
),
),
requireConfig: (ZegoCallInvitationData data) {
final config = ZegoUIKitPrebuiltCallConfig.oneOnOneVideoCall();
config.video = ZegoUIKitVideoConfig.preset540P();
// Modify your custom configurations here.
config.duration = ZegoCallDurationConfig(
// isVisible: true,
isVisible: false,
onDurationUpdate: (Duration duration) {
if (duration.inSeconds >=
VideocallsConstants.kHangUpCallAfterInSeconds) {
ZegoUIKitPrebuiltCallController()
// .hangUp(navigatorKey.currentState!.context);
.hangUp(globalCallNavigatorKey.currentState!.context);
}
},
);
config.layout = ZegoLayout.pictureInPicture();
// todo: maybe use inviter - data.inviter.
// Custom handlers
// todo: add handlers
config.bottomMenuBar = ZegoCallBottomMenuBarConfig(
backgroundColor: Colors.white,
hideAutomatically: false,
hideByClick: false,
buttons: List.empty(), // убрать стандартные кнопки
extendButtons: [
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size(60, 60),
shape: const CircleBorder(),
),
onPressed: () {
// ZegoUIKitPrebuiltCallController()
},
child: const Icon(
FFIcons.kcamera, // Icon(FFIcons.kcameraslash),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size(60, 60),
shape: const CircleBorder(),
),
onPressed: () {},
child: const Icon(
FFIcons.kmicrophone, // Icon(FFIcons.kmicrophoneslash),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size(60, 60),
shape: const CircleBorder(),
),
onPressed: () {
ZegoUIKitPrebuiltCallController().hangUp(
globalCallNavigatorKey.currentState!.context,
);
},
child: const Icon(
FFIcons.kphonedisconnect,
),
),
]);
return config;
},
uiConfig: ZegoCallInvitationUIConfig(
declineButton: ZegoCallButtonUIConfig(
visible: false,
),
acceptButton: ZegoCallButtonUIConfig(
visible: false,
),
cancelButton: ZegoCallButtonUIConfig(
visible: false,
),
callingBackgroundBuilder: (context, size, info) {
final callerRef = getDocRefByDocId(info.inviter.id, 'users');
debugPrint(
'-- ZegoUIKitPrebuiltCallInvitationService -- callingBackgroundBuilder: ${callerRef.id}');
return VideocallLobbyWidget(
userRef: callerRef,
acceptButtonCallback: () =>
ZegoUIKitPrebuiltCallInvitationService().accept(),
declineButtonCallback: () =>
ZegoUIKitPrebuiltCallInvitationService().reject(),
);
},
),
events: ZegoUIKitPrebuiltCallEvents(
onError: (ZegoUIKitError error) {
debugPrint(
'-- ZegoUIKitPrebuiltCallEvents -- onError: ${error.toString()}');
},
onHangUpConfirmation: (event, onHangUpConfirmation) async {
final result = await onHangUpConfirmationAction(
event.context,
);
return result;
},
onCallEnd: (event, onCallEnd) async {
// todo: maybe not await
await onCallEndAction(
getDocRefByDocId(_userID!, 'users'),
);
},
),
);
}
/// on App's user logout
void onUserLogout() {
ZegoUIKitPrebuiltCallInvitationService().uninit();
}
}
```
I'd like to get something near to image
I couldn’t find any information on how you can control sound and video through this package.
How can i to achieve to realize these features?