Android N 多窗口的应用——画中画

        Android N 预览版本支持画中画(Picture in Picture)模式进行视频的播放。画中画是多窗口模式的一种特殊类型,主要用于后台播放视频。Android TV设备早已经支持画中画模式。在多窗口模式中,用户仍然可以看到处于暂停状态的应用,而且应用在暂停状态下可能仍需要继续其他操作。例如,处于暂停模式但可见的视频播放应用应该继续显示视频。Android官方建议播放视频的Activity不要在onPause()暂停视频,应在onStop()暂停视频,在onStart()恢复播放。先看下画中画播放视频的情景:


        在Android N 版本中,你可以在manifest文件对Activity是否支持多窗口形式进行设置。根Activity的属性设置适用于其任务栈所有Activity。支持多窗口设置如下:

android:resizeableActivity="true"
        如果设为true,Activity将可以分屏和以自由模式启动;如果为false,则不支持分屏。该属性默认为true。如果需要 支持画中画模式,设置如下:

android:supportsPictureInPicture="true"

        和多窗口布局属性相关的包括:默认高度、默认宽度、初始位置、最小高度、最小宽度。具体如下:

<layout 
android:defaultHeight="500dp"//设置默认高度 
android:defaultWidth="600dp"//设置默认宽度 
android:gravity="top|end"//设置初始位置 
android:minimalHeight="450dp"//设置最小高度 
android:minimalWidth="300dp"//设置最小宽度
/>
        如果需要查询当前Activity是否处于多窗口模式,可以调用以下方法:
Activity.isInMultiWindowMode()
        如果需要查询当前Activity是否处于画中画模式,可以调用以下方法:
Activity.isInPictureInPictureMode()
        Activity 进入或退出多窗口模式时系统将调用如下方法。 在 Activity 进入多窗口模式时,系统向该方法传递 true 值,在退出多窗口模式时,则传递 false 值。
Activity.onMultiWindowModeChanged()
        Activity 进入或退出画中画模式时系统将调用如下方法。 在 Activity 进入画中画模式时,系统向该方法传递 true 值,在退出画中画模式时,则传递 false 值。
Activity.onPictureInPictureModeChanged()
        如果需要在画中画模式中启动Activity,可以调用如下方法:
Activity.enterPictureInPictureMode()
        在多窗口模式中启动新 Activity,可以使用标志 Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT。如果设备处于分屏模式,系统会尝试在启动系统的 Activity 旁创建新 Activity,这样两个 Activity 将共享屏幕。如果设备处于自由形状模式,则在启动新 Activity 时,用户可通过调用 ActivityOptions.setLaunchBounds() 指定新 Activity 的尺寸和屏幕位置。值得注意的是,如果您在任务栈中启动 Activity,该 Activity 将替换屏幕上的 Activity,并继承其所有的多窗口属性。 如果要在多窗口模式中以单独的窗口启动新 Activity,则必须在新的任务栈中启动此 Activity。Activity处于画中画模式时,生命周期应该这样操作:
@Override
protected void onStop() {
    super.onStop();
    //进入画中画模式,调用onPause方法,而不是onStop方法
    //暂停视频的播放
    mMovieView.pause();
}

@Override
protected void onRestart() {
    super.onRestart();
    //恢复视频的播放
    mMovieView.showControls();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //屏幕发生旋转,自适应全屏
    adjustFullScreen(newConfig);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {//window获得焦点,自适应全屏
        adjustFullScreen(getResources().getConfiguration());
    }
}
        Activity进入或者画中画时,需要重写onPitctureInPictureModeChanged方法:
@Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode);
        if (isInPictureInPictureMode) {
            // 开始接受来自画中画点击响应事件
            mReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent == null || !ACTION_MEDIA_CONTROL.equals(intent.getAction())) {
                        return;
                    }

                    // 点击后的回调
                    final int controlType = intent.getIntExtra(EXTRA_CONTROL_TYPE, 0);
                    switch (controlType) {
                        case CONTROL_TYPE_PLAY:
                            mMovieView.play();
                            break;
                        case CONTROL_TYPE_PAUSE:
                            mMovieView.pause();
                            break;
                    }
                }
            };
            registerReceiver(mReceiver, new IntentFilter(ACTION_MEDIA_CONTROL));
        } else {
            // 退出画中画 模式,注销广播,不再接收点击响应事件
            unregisterReceiver(mReceiver);
            mReceiver = null;
            if (mMovieView != null && !mMovieView.isPlaying()) {
                mMovieView.showControls();
            }
        }
    }
        视频状态发生改变时,调用以下方法按钮和文字的状态:
/**
 * 处于画中画模式,更新播放/暂停状态
 *
 * @param iconId      图标的id
 * @param title       标题
 * @param controlType 控制类型:播放/暂停
 * @param requestCode 使用PendingIntent的请求码
 */
void updatePictureInPictureActions(@DrawableRes int iconId, String title, int controlType,
        int requestCode) {
    final ArrayList<RemoteAction> actions = new ArrayList<>();

    //当用户点击控制按钮时,PendingIntent会被调用
    final PendingIntent intent = PendingIntent.getBroadcast(MainActivity.this,
            requestCode, new Intent(ACTION_MEDIA_CONTROL).putExtra(EXTRA_CONTROL_TYPE, controlType), 0);
    final Icon icon = Icon.createWithResource(MainActivity.this, iconId);
    actions.add(new RemoteAction(icon, title, title, intent));

    actions.add(new RemoteAction(
            Icon.createWithResource(MainActivity.this, R.drawable.ic_info_24dp),
            getString(R.string.info), getString(R.string.info_description),
            PendingIntent.getActivity(MainActivity.this, REQUEST_INFO,
                    new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.info_uri))),
                    0)));

    mPictureInPictureArgs.setActions(actions);

    //设置画中画参数
    setPictureInPictureArgs(mPictureInPictureArgs);
}
        视频播放回调,包括播放、暂停和最小会窗口,每个接口会调用上面介绍到的方法更新状态:
/**
 * 视频播放的回调
 */
private MovieView.MovieListener mMovieListener = new MovieView.MovieListener() {

    @Override
    public void onMovieStarted() {
        // 处于画中画模式,播放视频时,显示暂停按钮
        updatePictureInPictureActions(R.drawable.ic_pause_24dp, mPause, CONTROL_TYPE_PAUSE,
                REQUEST_PAUSE);
    }

    @Override
    public void onMovieStopped() {
        // 处于画中画模式,暂停视频时,显示播放按钮
        updatePictureInPictureActions(R.drawable.ic_play_arrow_24dp, mPlay, CONTROL_TYPE_PLAY,
                REQUEST_PLAY);
    }

    @Override
    public void onMovieMinimized() {
        // 进入画中画模式,播放窗口最小化
        minimize();
    }

};
        好了,以上是对Android N多窗口和画中画模式的介绍。如果这篇文章对你有帮助,可以点个赞。

发布了63 篇原创文章 · 获赞 179 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/68949628