# Video This section describes how to render video. ## Render the video view The Video SDK for Flutter uses two different widgets to render video. - For Android it uses `AndroidView`. - For iOS it uses `UiKitView`. Define a `View` class to render the video view for both of these platforms: ```dart switch (defaultTargetPlatform) { case TargetPlatform.android: return AndroidView( viewType: 'the name of view type', layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); case TargetPlatform.iOS: return UiKitView( viewType: 'the name of view type', layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), ); default: throw UnsupportedError("Unsupported platform"); } ``` ## Separate full screen and horizontal scrolling list views To separate the full screen view and horizontal scrolling list view, define another class, `VideoView`, to render the `View` based on whether it is full screen or not: ```dart class VideoView extends HookWidget { final ZoomVideoSdkUser? user; final bool sharing; final bool preview; final bool focused; final bool hasMultiCamera; final String multiCameraIndex; final String? videoAspect; final bool fullScreen; const VideoView({ super.key, required this.user, required this.sharing, required this.preview, required this.focused, required this.hasMultiCamera, required this.multiCameraIndex, this.videoAspect, required this.fullScreen, }); } ``` In the example app file, `lib/call-screen.dart`, the function returns `VideoView` in two separate code blocks: - one for full screen visualization and - the other for a horizontally scrolling list of remote users in a video session at the bottom of the screen. ## Full screen visualization The full screen visualization, upon initialization with video enabled, renders what others participating in a video session see: ```dart fullScreenView = AnimatedOpacity( opacity: opacityLevel, duration: const Duration(seconds: 3), child: VideoView( user: fullScreenUser.value, hasMultiCamera: false, sharing: sharingUser.value == null ? false : (sharingUser.value?.userId == fullScreenUser.value?.userId), preview: false, focused: false, multiCameraIndex: "0", videoAspect: VideoAspect.Original, fullScreen: true, ), ); ``` ### Creation parameters passed to `View` This function passes the following parameters to `View`: - `user`: A `ZoomVideoSdkUser` type instantiated via an event listener for Video SDK session when a user creates, joins, or leaves a session. - `sharing`: A Boolean set to `true` if the current full screen user is currently the user who is sharing a screen with others. - `preview`: A Boolean set to `true` if the video view is for preview. - `hasMultiCamera`: A Boolean set to `true` if the user's device has more than one camera. - `multiCameraIndex`: The index of camera view that the `View` should render. - `videoAspect`: The aspect ratio. - `fullScreen`: A Boolean value that tells the `View` component to render itself full screen or horizontal `ListView`. ## Horizontally scrolling list At the bottom of the call-screen, users can see a horizontally scrolling list of other users in the call. Use `VideoView` in the horizontal `ListView` that renders this as well: ```dart Container( height: 110, margin: const EdgeInsets.only(left: 20, right: 20), alignment: Alignment.center, child: ListView.separated( scrollDirection: Axis.horizontal, itemCount: users.value.length, itemBuilder: (BuildContext context, int index) { return InkWell( onTap: () async { onSelectedUser(users.value[index]); }, child: Center( child: VideoView( user: users.value[index], hasMultiCamera: false, sharing: sharingUser.value == null ? false : sharingUser.value?.userId == users.value[index].userId, preview: false, focused: false, multiCameraIndex: "0", videoAspect: VideoAspect.Original, fullScreen: false, ), ), ); }, separatorBuilder: (BuildContext context, int index) => const Divider(), ), ); ``` The horizontally scrolling `ListView` at the bottom of the screen renders mini video screens for all users in a session. Tapping a remote user's screen sets that user to the full screen user. ## Use virtual background Use [`ZoomVideoSdkVirtualBackgroundHelper`](https://marketplacefront.zoom.us/sdk/custom/flutter/native_zoom_videosdk_virtual_background_helper/ZoomVideoSdkVirtualBackgroundHelper-class.html) to enable virtual backgrounds. First determine whether the device supports it using `isSupportVirtualBackground`. If the device supports it, use the helper functions to add, get, set, and remove virtual backgrounds. To add virtual backgrounds: 1. Use `addVirtualBackgroundItem` to add a virtual background item. 2. Use `getVirtualBackgroundItemList` to get a list of available virtual background items. 3. Choose a virtual background item from the list and use `setVirtualBackgroundItem` to set the virtual background. Use `removeVirtualBackgroundItem` to remove the virtual background or set the virtual background to None. Use `getSelectedVirtualBackgroundItem` to get the current selected background. ```dart // Check if virtual background is supported @override Future isSupportVirtualBackground() async { return await methodChannel .invokeMethod('isSupportVirtualBackground') .then((bool? value) => value ?? false); } // Add virtual background item @override Future addVirtualBackgroundItem(String filePath) async { var params = {}; params.putIfAbsent("filePath", () => filePath); var itemString = await methodChannel .invokeMethod('addVirtualBackgroundItem', params) .then((String? value) => value ?? ""); Map itemMap = jsonDecode(itemString!); var vbItem = ZoomVideoSdkVirtualBackgroundItem.fromJson(itemMap); return vbItem; } // Remove virtual background item @override Future removeVirtualBackgroundItem(String imageName) async { var params = {}; params.putIfAbsent("imageName", () => imageName); return await methodChannel .invokeMethod('removeVirtualBackgroundItem', params) .then((String? value) => value ?? ""); } // Get virtual background item list @override Future> getVirtualBackgroundItemList() async { var itemListString = await methodChannel .invokeMethod('getVirtualBackgroundItemList') .then((String? value) => value); var itemListJson = jsonDecode(itemListString!) as List; List itemList = itemListJson .map((languageJson) => ZoomVideoSdkVirtualBackgroundItem.fromJson(languageJson)) .toList(); return itemList; } // Set virtual background item @override Future setVirtualBackgroundItem(String imageName) async { var params = {}; params.putIfAbsent("imageName", () => imageName); return await methodChannel .invokeMethod('setVirtualBackgroundItem', params) .then((String? value) => value ?? ""); } // Get selected virtual background @override Future getSelectedVirtualBackgroundItem() async { } ```