Skip to main content
Version: Next

Picture in Picture (PiP)

VideoView API Reference: UI.VideoView

Since the Smartphones dominate the technology market, more people started to use their Smartphone as their daily driver for almost everything and consuming media is not an exception.

Users might want to watch a Live Stream or a long video while doing their other tasks in another apps on their Smartphone. This becomes more important when the users are using a tablet, since tablets are designed to be used for multi-tasking.

iOS Supported Versions

As it is stated on iOS 14 Usage Guide by Apple, Picture in Picture mode is supported on iOS 14 or above.

For iOS 13 or below, audio-only mode is supported.

Android Supported Versions

As it is stated on Android Development Document by Google, Picture in Picture mode is supported on Android API 26 (Oreo) or above.

For Android API 25 or below, audio-only mode is supported.

info

Currently, Smartface does not support Picture in Picture mode on Android and we are working on to implement the feature. However, audio of your video contents will be played on the background.

Get Started with Picture in Picture

Before you start to implement the page code, there are a few things you should do in order to inform the platform that you are going to use Picture in Picture mode.

iOS Prerequisites

To allow your application to go into PiP mode, you should add this key into your info.plistfile.

<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>

Here is how it should like on your info.plist file

config/iOS/info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
</dict>
<? Your other plist configurations go here ?>
</dict>
</plist>


Android Prerequisites

There is no prerequisites to be done on Android.

Edit Your VideoView to Support Picture in Picture

API Reference: UI.VideoView.backgroundModeEnabled

Picture in Picture mode is managed through VideoView. Therefore, there is a few changes to make depending on how it is created. First, we need to set backgroundModeEnabled value to true.

info

This property only has a meaning when it is set from constructor of VideoView. Assigning the property on runtime will have no effect on the view.

VideoView is Created on Smartface UI Editor

If the VideoView is added to the page via Drag&Drop method, you should assign the property via its constructor:

  • Open the desired page via Smartface UI Editor.
  • Click on an empty space and click on Open with Code Editor
  • After the .pgx file is open, find the properties of your VideoView . You can do that by typing VideoView to Search box
  • After you find your VideoView, add this property into both userProps and props fields
"backgroundModeEnabled": true
  • The result should look like this
.ui/page1.pgx
{
"components": [
{
"className": ".sf-page",
"id": "e891b86d",
"initialized": true,
"props": {
"children": [
"42b807d1",
"b7d28cff",
"96a5-1dba-d9b2-6d48"
],
"isRemovable": true,
"name": "page1",
"orientation": "PORTRAIT",
"parent": null,
"safeAreaEnabled": true
},
"type": "Page",
"userProps": {
"flexProps": {
"justifyContent": "SPACE_BETWEEN",
"alignItems": "STRETCH"
},
"orientation": "PORTRAIT",
"paddingBottom": 20,
"paddingLeft": 16,
"paddingRight": 16,
"safeAreaEnabled": true
},
"version": "6.15.1"
},
{
"className": ".sf-statusBar",
"id": "42b807d1",
"props": {
"children": [],
"isRemovable": false,
"name": "statusBar",
"parent": "e891b86d"
},
"type": "StatusBar",
"userProps": {
"visible": true
}
},
{
"className": ".sf-headerBar",
"id": "b7d28cff",
"props": {
"children": [],
"isRemovable": false,
"name": "headerBar",
"parent": "e891b86d",
"title": "Page1"
},
"type": "HeaderBar",
"userProps": {
"title": "Page1",
"visible": true
}
},
{
"className": ".sf-videoView",
"id": "96a5-1dba-d9b2-6d48",
"props": {
"children": [],
"name": "videoPlayer",
"parent": "e891b86d",
"usePageVariable": true,
"backgroundModeEnabled": true // <-- Added value
},
"type": "VideoView", // <--- This indicates that the component is VideoView
"userProps": {
"testId": "fvdVkxraT",
"usePageVariable": true,
"backgroundModeEnabled": true // <-- Added value
}
}
]
}

VideoView is Created on Code

As we strongly recommend using Smartface UI Editor, sometimes it might be necessary to create your UI Views from the page code. Worry not, it will not prevent to use Picture in Picture mode!

Assume that your VideoView is created like this:

scripts/pages/page1.ts
import Page1Design from "generated/pages/page   ";
import { Route, Router } from "@smartface/router";
import System from "@smartface/native/device/system";
import VideoView from "@smartface/native/ui/videoview";
import Application from "@smartface/native/application";


//You should create new Page from UI-Editor and extend with it.
export default class Page1 extends Page1Design {
videoPlayer: VideoView;
constructor(private router?: Router, private route?: Route) {
super({});
}

// The page design has been made from the code for better
// showcase purposes. As a best practice, remove this and
// use WYSIWYG editor to style your pages.
centerizeTheChildrenLayout() {
this.dispatch({
type: "updateUserStyle",
userStyle: {
flexProps: {
flexDirection: 'COLUMN',
justifyContent: 'CENTER',
alignItems: 'CENTER'
}
}
})
}

initVideoView(): void {
this.videoPlayer = new VideoView({
height: 343,
backgroundModeEnabled: true,
});
this.addChild(this.videoPlayer); // A second or third parameter might be there.
this.videoPlayer.page = this;
this.videoPlayer.loadURL(
"https://multiplatform-f.akamaihd.net/i/multi/will/bunny/big_buck_bunny_,640x360_400,640x360_700,640x360_1000,950x540_1500,.f4v.csmil/master.m3u8"
);
this.videoPlayer.onReady = () => this.videoPlayer.play();
}

onShow() {
super.onShow();
const { headerBar } = System.OS === System.OSType.ANDROID ? this : this.parentController;
Application.statusBar.visible = true;
headerBar.visible = true;
}

onLoad() {
super.onLoad();
this.centerizeTheChildrenLayout();

this.initVideoView();
}
}

You can enable Picture in Picture support by adding backgroundModeEnabled property in your VideoView constructor like this:

this.myVideoView = new VideoView({ backgroundModeEnabled: true });
this.layout.addChild(this.myVideoView);
this.myVideoView.page = this;
// Your VideoView code goes here

Now you have Picture in Picture support. Note that this will not work:

this.videoPlayer = new VideoView();
this.layout.addChild(this.videoPlayer);
this.videoPlayer.page = this;
// Your VideoView code goes here
this.videoPlayer.backgroundModeEnabled = true; // Wrong implementation

Implement Picture in Picture Mode for iOS

To demonstrate the feature, test video of Apple was used.

info

The code below will assume that VideoView is created from Smartface UI Editor. Same steps apply for the VideoView which is created from code.

scripts/pages/page1.ts
import Page1Design from "generated/pages/page1";

export default class Page1 extends Page1Design {
router: any;
constructor() {
super();
this.onShow = onShow.bind(this, this.onShow.bind(this));
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
}

initVideoView() {
this.videoPlayer.page = this;
this.videoPlayer.loadURL(
"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
);
this.videoPlayer.onReady = () => this.videoPlayer.play();
}
}

function onShow(superOnShow: () => void) {
superOnShow();
}

function onLoad(superOnLoad: () => void) {
superOnLoad();
this.initVideoView();
}

After we set backgroundModeEnabled property, on iOS our video should have an extra button like this:

Existence of this button indicates that Picture in Picture mode is enabled and ready to use. If this button is not present:

  • Check your page code for backgroundModeEnabled property.
  • Make sure that your changes are generated and compiled.
  • Your iOS version of device is not supported. Refer to the start of document.

Without any configuration, your VideoView will look like this:

Restoring the Picture in Picture Mode

You can click the marked icon to re-open the app.

Moving the Picture in Picture Video

By default, iOS allows us to move, enlarge or show/hide the Picture in Picture video.

  • Drag the Picture in Picture to move it at the top or bottom of the screen.
  • Double click the Picture in Picture to enlarge/shrink.
  • Swipe to the corner to hide and swipe back to show it again.