android oreo

Ever wanted to watch videos on your Android phone while you browse the web? Everyone always desires this. Thanks to Android Oreo, we now have Picture In Picture feature to develop awesome Android Applications.

您是否曾经想在浏览网络时在Android手机上观看视频? 每个人都一直渴望这一点。 感谢Android Oreo,我们现在有了画中画功能,可以开发出色的Android应用程序。

In this tutorial, we’ll be developing an application where we can view a Video in a preview while we browse through the list of our videos or other applications on our smartphone. You would see this behavior in YouTube or FaceBook app while watching videos and doing other things at the same time in the app.

在本教程中,我们将开发一个应用程序,在浏览视频列表或智能手机上的其他应用程序时,可以预览视频。 您会在YouTube或FaceBook应用程序中同时观看视频和执行其他操作时看到此行为。

Android画中画 (Android Picture In Picture)

Picture In Picture support came up for Android TV with the Android Nougat update. So it was expected to be there for phones in Oreo. By default, Picture In Picture (PiP) feature isn’t enabled for activities.

随着Android Nougat更新,对Android TV进行了画中画支持。 因此,预计在奥利奥(Oreo)中会有电话。 默认情况下,活动未启用画中画(PiP)功能。

So you need to set the following attributes in the AndroidManifest.xml file for the activity which requires PiP.

因此,您需要在AndroidManifest.xml文件中为需要PiP的活动设置以下属性。

<activityandroid:name=".PiPActivity"android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"android:label="@string/title_activity_pi_p"android:launchMode="singleTask"android:resizeableActivity="true"android:supportsPictureInPicture="true"android:theme="@style/AppTheme.NoActionBar" />

android:configChanges must be set to make sure that the Activity does not lose any data while changing the screen size particularly.

必须设置android:configChanges ,以确保在更改屏幕尺寸时,活动不会丢失任何数据。

android:resizeableActivity makes sure that the activity can be resized when the PiP is triggered.

android:resizeableActivity确保在触发画中画时可以调整活动的大小。

In our Activity there are three major methods for PiP support:

在我们的活动中,有三种主要的画中画支持方法:

  • enterPictureInPictureMode(): We pass an instance of the PiP builder in here. This method is what starts the PiP.enterPictureInPictureMode() :我们在此处传递PiP构建器的实例。 此方法就是启动PiP的方法。
  • onPictureInPictureModeChanged(): gets triggered when the PiP has occurred. Here we can hide the UI elements which we don’t what in the PiP enabled mode.onPictureInPictureModeChanged() :发生画中画时触发。 在这里,我们可以隐藏在PiP启用模式下没有的UI元素。
  • onUserLeaveHint(): This gets triggered when the user presses home/recents options to come outside the application. We can set the PiP inside it. We need to make sure that we don’t pause/stop the video in the onPause()/onStop() methods.onUserLeaveHint() :当用户按下主页/最近的选项进入应用程序外部时,将触发此事件。 我们可以在其中设置画中画。 我们需要确保不要在onPause()/ onStop()方法中暂停/停止视频。

Now let the code do the rest of the talking. In the following section, we’ll create a RecyclerView which contains a list of Videos. The Videos would be played in the VideoView.

现在让代码完成其余的讨论。 在以下部分中,我们将创建一个RecyclerView,其中包含视频列表。 视频将在VideoView中播放。

We’ve used a public set of video urls available here

我们使用的公共集视频的网址提供点击这里

Android画中画项目结构 (Android Picture in Picture Project Structure)

Android画中画代码 (Android Picture in Picture Code)

The code for the activity_main.xml layout is given below:

下面给出了activity_main.xml布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"xmlns:app="https://schemas.android.com/apk/res-auto"xmlns:tools="https://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><android.support.v7.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent" /></RelativeLayout>

Each row of the RecyclerView is populated from cardview_item_row.xml file:

RecyclerView的每一行都是从cardview_item_row.xml文件填充的:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:id="@+id/cardView"android:layout_height="wrap_content"><LinearLayoutandroid:id="@+id/ll"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="16dp"><TextViewandroid:id="@+id/txtName"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout></android.support.v7.widget.CardView>

The code for the MainActivity.java class is given below:

MainActivity.java类的代码如下:

package com.journaldev.androidpictureinpicture;import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;import java.util.ArrayList;public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.ItemListener {private ArrayList<Model> videoList = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);RecyclerView recyclerView = findViewById(R.id.recyclerView);recyclerView.setItemAnimator(new DefaultItemAnimator());recyclerView.setLayoutManager(new LinearLayoutManager(this));populateArrayList();RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(videoList, this);recyclerView.setAdapter(recyclerViewAdapter);}private void populateArrayList() {videoList.add(new Model("Big Buck Bunny", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"));videoList.add(new Model("We are going on bull run", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WeAreGoingOnBullrun.mp4"));videoList.add(new Model("Volkswagen GTI Review", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/VolkswagenGTIReview.mp4"));videoList.add(new Model("For Bigger Blazes", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"));videoList.add(new Model("Subaru Outback On Street And Dirt", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/SubaruOutbackOnStreetAndDirt.mp4"));videoList.add(new Model("What care can you get for ten grand?", "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WhatCarCanYouGetForAGrand.mp4"));}@Overridepublic void onItemClick(Model model) {startActivity(new Intent(this, PiPActivity.class).putExtra("videoUrl", model.videoUrl));}
}

We’ve created a Model.java class which holds the data for the RecyclerViewAdapter class.

我们创建了一个Model.java类,其中包含RecyclerViewAdapter类的数据。

package com.journaldev.androidpictureinpicture;public class Model {public String name, videoUrl;public Model(String name, String videoUrl) {this.name = name;this.videoUrl = videoUrl;}}

The code for the RecyclerViewAdapter.java class is given below:

下面给出了RecyclerViewAdapter.java类的代码:

package com.journaldev.androidpictureinpicture;import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.CryptoViewHolder> {private ArrayList<Model> videoList;private ItemListener mItemListener;public class CryptoViewHolder extends RecyclerView.ViewHolder {private TextView mName;private CardView cardView;public CryptoViewHolder(View itemView) {super(itemView);mName = itemView.findViewById(R.id.txtName);cardView = itemView.findViewById(R.id.cardView);}}public RecyclerViewAdapter(ArrayList<Model> videoList, ItemListener itemListener) {this.videoList = videoList;this.mItemListener = itemListener;}@Overridepublic CryptoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_item_row, parent, false);return new CryptoViewHolder(itemView);}@Overridepublic void onBindViewHolder(CryptoViewHolder holder, final int position) {holder.mName.setText(videoList.get(position).name);holder.cardView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mItemListener.onItemClick(videoList.get(position));}});}@Overridepublic int getItemCount() {return videoList.size();}public interface ItemListener {void onItemClick(Model model);}}

onItemClick triggers a call to the PiPActivity with the videoUrl being passed.

onItemClick通过videoUrl触发对PiPActivity的调用。

The code for the activity_pip.xml class is given below:

下面给出了activity_pip.xml类的代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"xmlns:app="https://schemas.android.com/apk/res-auto"xmlns:tools="https://schemas.android.com/tools"android:id="@+id/coordinatorLayout"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".PiPActivity"><android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/AppTheme.AppBarOverlay"><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="?attr/colorPrimary"app:popupTheme="@style/AppTheme.PopupOverlay" /></android.support.design.widget.AppBarLayout><include layout="@layout/content_pi_p" /><android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="@dimen/fab_margin"app:srcCompat="@android:drawable/ic_menu_set_as" /></android.support.design.widget.CoordinatorLayout>

The code for the content_pi_p.xml is given below:

下面给出了content_pi_p.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"xmlns:app="https://schemas.android.com/apk/res-auto"xmlns:tools="https://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"tools:context=".PiPActivity"tools:showIn="@layout/activity_pip"><VideoViewandroid:id="@+id/videoView"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></android.support.constraint.ConstraintLayout>

The code for the PiPActivity.java class is given below:

PiPActivity.java类的代码如下:

package com.journaldev.androidpictureinpicture;import android.app.PictureInPictureParams;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Rational;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;@RequiresApi(api = Build.VERSION_CODES.O)
public class PiPActivity extends AppCompatActivity {VideoView videoView;FloatingActionButton fab;PictureInPictureParams.Builder pictureInPictureParamsBuilder = new PictureInPictureParams.Builder();Toolbar toolbar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pip);toolbar = findViewById(R.id.toolbar);setSupportActionBar(toolbar);videoView = findViewById(R.id.videoView);fab = findViewById(R.id.fab);final MediaController mediacontroller = new MediaController(this);mediacontroller.setAnchorView(videoView);String videoUrl = getIntent().getStringExtra("videoUrl");videoView.setMediaController(mediacontroller);videoView.setVideoURI(Uri.parse(videoUrl));videoView.requestFocus();fab.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startPictureInPictureFeature();}});videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {@Overridepublic void onVideoSizeChanged(MediaPlayer mp, int width, int height) {videoView.setMediaController(mediacontroller);mediacontroller.setAnchorView(videoView);}});}});}private void startPictureInPictureFeature() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {Rational aspectRatio = new Rational(videoView.getWidth(), videoView.getHeight());pictureInPictureParamsBuilder.setAspectRatio(aspectRatio).build();enterPictureInPictureMode(pictureInPictureParamsBuilder.build());}}@Overridepublic void onUserLeaveHint() {if (!isInPictureInPictureMode()) {Rational aspectRatio = new Rational(videoView.getWidth(), videoView.getHeight());pictureInPictureParamsBuilder.setAspectRatio(aspectRatio).build();enterPictureInPictureMode(pictureInPictureParamsBuilder.build());}}@Overridepublic void onPictureInPictureModeChanged(boolean isInPictureInPictureMode,Configuration newConfig) {if (isInPictureInPictureMode) {fab.setVisibility(View.GONE);toolbar.setVisibility(View.GONE);} else {fab.setVisibility(View.VISIBLE);toolbar.setVisibility(View.VISIBLE);}}@Overridepublic void onNewIntent(Intent i) {updateVideoView(i);}private void updateVideoView(Intent i) {String videoUrl = i.getStringExtra("videoUrl");videoView.setVideoURI(Uri.parse(videoUrl));videoView.requestFocus();}}

In the startPictureInPictureFeature() we change the width and height of the VideoView to a preview size before starting the picture in picture mode.

startPictureInPictureFeature()我们在以图片模式启动图片之前将VideoView的宽度和高度更改为预览大小。

Inside the onNewIntent() method, we update the VideoView.

onNewIntent()方法中,我们更新了VideoView。

Inside the onPictureInPictureModeChanged we hide the toolbar as well as the FloatingActionButton.

onPictureInPictureModeChanged内部,我们隐藏了工具栏以及FloatingActionButton。

onNewIntent gets triggered when an intent to an existing activity is done. In this example, it makes sense to keep a single instance of the PiP Activity.
当完成对现有活动的意图时,将触发onNewIntent。 在此示例中,保留一个PiP活动实例是有意义的。

Our AndroidManifest.xml file is defined below:

我们的AndroidManifest.xml文件定义如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"package="com.journaldev.androidpictureinpicture"><uses-permission android:name="android.permission.INTERNET" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name=".PiPActivity"android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"android:label="@string/title_activity_pi_p"android:launchMode="singleTask"android:resizeableActivity="true"android:supportsPictureInPicture="true"android:theme="@style/AppTheme.NoActionBar" /></application></manifest>
PictureInPicture feature provides an inbuilt icon to resize the preview and as well as drag it on the screen anywhere.
PictureInPicture功能提供了一个内置图标,可以调整预览的大小并将其拖到屏幕上的任何位置。

The output of the above application in action is given below:

上面应用程序的输出如下:

Just double tap the VideoView to enable MediaControls.

只需双击VideoView以启用MediaControls。

Look how easy it is to implement PictureInPicture in your Android Application!

看看在您的Android应用程序中实现PictureInPicture多么容易!

This brings an end to this tutorial. You can download the project from the link below:

本教程到此结束。 您可以从下面的链接下载项目:

AndroidPictureInPictureAndroidPictureInPicture
GitHub Repository.GitHub Repository下载源代码。

翻译自: https://www.journaldev.com/20907/android-oreo-picture-in-picture

android oreo

android oreo_Android Oreo画中画相关推荐

  1. android oreo_Android Oreo隐式和显式广播接收器

    android oreo In this tutorial, we'll discuss the changes in Broadcast Receiver since Android Oreo. W ...

  2. android 画中画模式自定义,Android 8.0 Oreo 画中画模式

    Android 8.0 Oreo(API Level 26)允许活动启动画中画 Picture-in-picture(PIP)模式.PIP 是一种特殊类型的多窗口模式,主要用于视频播放.PIP 模式已 ...

  3. android 8 不更新,[已解决]您可能遇到的Android 8 Oreo更新问题

    第三部分:10个Android Oreo更新的常见问题以及如何修复 每次Android更新都会带来各种琐碎的问题.这些问题在大多数Android设备中很常见,包括三星,LG,华为,小米等. 问题1:随 ...

  4. android x86 oreo,Android-x86 8.1 RC1发布:PC上运行Android Oreo

    IT之家6月19日消息 在PC上运行Android系统的方式很多,但最可靠的还是Android-x86项目,现在其最新版已经发布,基于Android 8.1 Oreo. Android-x86是在PC ...

  5. Android悬浮窗口-画中画功能

    效果展示 前言 从 Android 8.0(API 级别 26)开始,Android 允许活动以画中画 (PiP) 模式启动.PiP 是一种特殊类型的多窗口模式,主要用于视频播放.它允许用户在固定在屏 ...

  6. Android 8.0 学习(21)---Oreo的画中画模式学习

    Android 8.0 Oreo的画中画模式学习 本文主要是对谷歌开发者官方微信公众号发布的Android 8.0 Oreo 画中画模式一文的学习记录.  画中画模式Picture-in-pictur ...

  7. Android开发周报:Google 推出AR SDK、Android 8.0 Oreo 最终版发布

    \ <Android漏洞扫描工具Code Arbiter>:目前 Android 应用代码漏洞扫描工具种类繁多,效果良莠不齐,这些工具有一个共同的特点,都是在应用打包完成后对应用进行解包扫 ...

  8. android8.0于与ios,android 8.0 oreo抄袭苹果吗 android oreo和ios 11对比

    在开发Android Oreo时,谷歌被传android 8.0 oreo抄袭了苹果iOS的部分创意,例如应用图标通知角标.表情符号.画中画.自动填写等. 谷歌刚刚公布了Android Oreo,它提 ...

  9. Android Oreo 常见问题 2.0 | Android 开发者 FAQ Vol.9

    在第一期 Android Oreo 8.0 开发者 FAQ 中,我们为了尽快让大家快速了解 Android Oreo 的新特性,以及它与之前版本 Android 的区别,我们针对 Android Or ...

最新文章

  1. Cloudera Manager 5.3 和 CDH5.3.0 本地(离线)
  2. 实战SSM_O2O商铺_41【前端展示】店铺列表页面Dao+Service+Controller层的实现
  3. 获取字段 命名空间和类_系统架构之命名规范
  4. yum删除mysql数据库_MySQL数据库之Centos中彻底删除Mysql(rpm、yum安装的情况)
  5. C语言使用时间创建随机数
  6. idea上传新项目至svn仓库
  7. SAP 工单报工批次确定自动带出批次并拆分
  8. Leetcode——495. Teemo Attacking
  9. 程序人生 - 错过等一年!杭州人独属的惠民福利,还有最后三天
  10. 周凯:如何利用数据挖掘让RTB广告效果倍增?
  11. 支持网络和局域网共享文件的windows pe
  12. mac要装anaconda吗_在Mac OS X上安装Anaconda
  13. 英语caement单词caement水泥
  14. Tuner及工作原理介绍
  15. 静电场点电荷matlab,基于MATLAB的点电荷的静电场模拟
  16. 筛查肌肉病变,首选磁共振
  17. 陈晨博士|可见光通信LiFi技术简介
  18. ZEMAX光学系统导入和CAD导出
  19. 计算机电缆设计规范,DJYPVP计算机电缆安装规范和设计原则
  20. Spring Security(1) 入门体验

热门文章

  1. linux下proc里关于磁盘性能的参数
  2. Java实践(五)——类的声明与引用
  3. [转载] 用pandas或numpy处理数据中的空值(np.isnan()/pd.isnull())
  4. [转载] python中numpy库的使用举例
  5. [转载] Java static关键字详解
  6. OpenQA.Selenium.Chrome Action滑动操作
  7. jQuery读取和设定KindEditor值的方法
  8. linux分享二:Linux如何修改字符集
  9. Java零基础系列001——第一个程序
  10. 程序执行系统VC++程序出现“试图执行系统不支持的操作”