Android-0.Android8.0(Oreo) 画中画(pip)功能简介

Android 8.0 Oreo 画中画模式

最简单的demo

1.AndroidManifest.xmlActivity增加 android:supportsPictureInPicture="true",如下

<activity android:name=".MainActivity"
			 android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
            android:supportsPictureInPicture="true">

页面从全屏模式切换到画中画模式,Activity生命周期也会经历销毁后重建的过程,如果开发者想保持页面不被重建,则需要加上android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"

smallestScreenSize|screenLayout这两个会影响到在PIP模式下action的响应,比如测试发现,如果没有smallestScreenSize|screenLayout这两个,BroadcastReceiver收不到广播的消息!

2.为主窗口增加一个按钮:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">
    <Button android:id="@+id/pip_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击进入PIP">
    </Button>
</LinearLayout>

3.点击按钮事件中调用public boolean enterPictureInPictureMode(PictureInPictureParams params)

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.pip_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testPIP();
            }
        });
    }
    
    void testPIP() {
        if (Build.VERSION.SDK_INT >= 26) {
            PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
            enterPictureInPictureMode(builder.build());
        }
    }
}

效果如下:
在这里插入图片描述

PIP相关函数简介

enterPictureInPictureMode (PictureInPictureParams args)

进入画中画模式。操作组件的纵横比和其他配置设置均由 args 指定。如果 args 中的任何字段为空,系统将使用您上次调用 setPictureInPictureParams() 时所设置的值。

PictureInPictureParams

Android 8.0(API Level 26) 引入了一个新的对象 PictureInPictureParams,它可以指定PIP的一些特定属性

PictureInPictureParams.setAspectRatio

第一个参数为分子,第二个为分母,指定宽高比,必须在 2.39:11:2.39 之间,否则会抛出IllegalArgumentException异常。

我们将前面的testPIP稍做修改一下,设置宽高比为2:1

    void testPIP() {
        if (Build.VERSION.SDK_INT >= 26) {
            PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
            builder.setAspectRatio(new Rational(2,1));// 宽高比2:1
            enterPictureInPictureMode(builder.build());
        }
    }

效果如下:可以看到坚屏和横屏切换时,PIP窗口相应做了变化
在这里插入图片描述

PictureInPictureParams.setActions

PIP中增加一组控制按钮RemoteAction,点击这个控制按钮进入某种操作,比如广播消息

    public RemoteAction(@NonNull Icon icon, @NonNull CharSequence title,
            @NonNull CharSequence contentDescription, @NonNull PendingIntent intent) {

参数为:icon、标题、描述、点击图标的反应
我们将前面的testPIP稍做修改一下, 让Action点击后跳到主页面:

    void testPIP() {
        if (Build.VERSION.SDK_INT >= 26) {
            PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
            builder.setAspectRatio(new Rational(2,1));// 宽高比2:1
            
            RemoteAction remoteAction = new RemoteAction(Icon.createWithResource(this, R.mipmap.ic_launcher),
                    "标题", "描述",
                    PendingIntent.getActivity(this, 100, getIntent(), PendingIntent.FLAG_UPDATE_CURRENT));
            final ArrayList<RemoteAction> actions = new ArrayList<>();
            actions.add(remoteAction);
            builder.setActions(actions);
            enterPictureInPictureMode(builder.build());
        }
    }

实现后会增加一个小按钮在这里插入图片描述,按钮的图标就是 代码中指定的R.mipmap.ic_launcher

效果如下:
在这里插入图片描述

setPictureInPictureParams

更新画中画活动的属性,或将其设置为稍后在enterPictureInPictureMode()调用时使用

isInPictureInPictureMode

isInPictureInPictureMode返回true表示处于画中画模式,返回false表示处于全屏模式。

onPictureInPictureModeChanged

每当进入或退出PIP模式,都会触发Activity页面的onPictureInPictureModeChanged方法。通过重载该方法,应用可以实时收到画中画与全屏的切换通知,并在此控制控件的展示。

PIP注意点

当一个Activity在画中画模式,它处于暂停状态,但可能需要继续展示内容(如视频播放)。出于这个原因,如果是一个视频播放程序,不能在 onpause 中暂停播放。相反,您应该在 onstop 中暂停播放·,在 onstart 中继续播放。

PIP详细的demo

扩展上面的demo, 增加一个Action用来广播消息,每次广播把controlType增加1,代码如下:

public class MainActivity extends Activity {

    private static final String ACTION_BROADCAST_CONTROL = "broadcast_control";
    private static final String EXTRA_CONTROL_TYPE = "control_type";
    private PictureInPictureParams.Builder mPictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
    private BroadcastReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        updatePIPActions(R.mipmap.ic_launcher, "描述", 100, 100);
        findViewById(R.id.pip_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testPIP();
            }
        });
    }

    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
        if (isInPictureInPictureMode) {
            mReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent == null || !ACTION_BROADCAST_CONTROL.equals(intent.getAction())) {
                        return;
                    }

                    //这就是我们从画中画模式的操作回调的地方
                    int controlType = intent.getIntExtra(EXTRA_CONTROL_TYPE, 0);
                    Toast.makeText(MainActivity.this, "控制码" + controlType, Toast.LENGTH_SHORT).show();
                    controlType ++;
                    updatePIPActions(R.mipmap.ic_launcher, "描述", controlType, controlType);
                }
            };
            registerReceiver(mReceiver, new IntentFilter(ACTION_BROADCAST_CONTROL));
        } else {
            // 当我们不在画中画模式时,停止接收广播
            unregisterReceiver(mReceiver);
            mReceiver = null;

        }
    }

    void testPIP() {
        if (Build.VERSION.SDK_INT >= 26) {
            mPictureInPictureParamsBuilder.setAspectRatio(new Rational(2, 1)).build();// 宽高比2:1
            enterPictureInPictureMode(mPictureInPictureParamsBuilder.build());
        }
    }

    // 注意当controlType改变时,requestCode也必须要变,同一个requestCode会使用第一次关联的controlType
    void updatePIPActions(int iconId, String title, int controlType, int requestCode) {
        final ArrayList<RemoteAction> actions = new ArrayList<>();

        Intent intent = new Intent(ACTION_BROADCAST_CONTROL);
        intent.putExtra(EXTRA_CONTROL_TYPE, controlType);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, intent, 0);
        final Icon icon = Icon.createWithResource(this, iconId);

        actions.add(new RemoteAction(icon, title, title, pendingIntent));

        mPictureInPictureParamsBuilder.setActions(actions);
        setPictureInPictureParams(mPictureInPictureParamsBuilder.build());
    }
}

效果如下:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值