是时候学习Android分屏开发了
nxqw0344
8年前
<p>今年Google发布了Android N,Android N新增了不少功能,最受关注的自然就是分屏了。</p> <p>这一功能对国内的很多手机用户并不陌生,其实很多第三方系统早已经实现了这一功能,如EMUI,Flyme等等。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/24db25615c21c3c3e7dfb3c7d9dab13f.png" alt="是时候学习Android分屏开发了" width="1502" height="884"></p> <p style="text-align:center">分屏操作</p> <p>在我的手机中,就可以一边看视频,一边浏览简书。Android N分屏功能的更新,似乎并不会对我国第三方Android系统带来多大的影响。毕竟厂商有自己实现这一功能的套路。</p> <p>然而,谷歌反应的“缓慢”真的没有价值吗?其实不是的,<strong>Android N新增的功能是为其他第三方系统作出一个“标杆”。</strong></p> <p>这里举个例子,首先是分屏多任务,如今不同Android ROM实现该功能的方式不一,而且对软件的兼容也大有不同,所以体验也就可能差天共地(不能达到该有的标准),而Android N新增分屏多任务的支持,除了让第三方ROM开发商可以参照这个“模板”进行二次开发之外,软件开发人员也能根据Android N分屏多任务功能的实现方式去进行软件的开发。从而大大减少了自己摸索的时间,加快开发速度,由此支持该功能的软件会更多,兼容性也会更好。</p> <p><strong>分屏模式在Android电视中就变成了更为强大的画中画模式</strong>,终于可以一边看比赛直播,一边追电视剧了。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/c6bf3255750c9175611c09cd1b508c59.png" alt="是时候学习Android分屏开发了" width="700" height="394"></p> <p style="text-align:center">画中画</p> <h2>如何分屏呢</h2> <p>如果您的应用是使用 N Preview SDK 构建的,且未禁用多窗口支持,则应用默认支持分屏操作。</p> <pre> <code class="language-java"> compileSdkVersion 'android-N' buildToolsVersion "24.0.0 rc4" defaultConfig { applicationId "com.yll520wcf.myapplication" minSdkVersion 14 targetSdkVersion 'N' versionCode 1 versionName "1.0" }</code></pre> <p>用户可以通过以下方式切换到多窗口模式:</p> <ol> <li>若用户打开最近任务列表(Overview 屏幕),并长按 Activity 标题,则可以拖动该 Activity 至屏幕突出显示的区域,使 Activity 进入多窗口模式。</li> <li>若用户长按菜单按键(Overview 按钮),设备上的当前 Activity 将进入多窗口模式,同时将打开 最近任务列表(Overview 屏幕),用户可在该屏幕中选择要共享屏幕的另一个 Activity。</li> </ol> <p>用户居然还可以在两个 Activity 共享屏幕的同时在这两个 Activity 之间拖放数据 (在此之前,用户只能在一个 Activity 内部拖放数据)。想想以后微博的图片直接拖到微信朋友圈中是不是很屌啊。</p> <h2>多窗口生命周期</h2> <p>还需要注意的是多窗口不会影响Activity的生命周期。</p> <p>在多窗口模式中,在指定时间只有最近与用户交互过的 Activity 为活动状态。 该 Activity 将被视为顶级 Activity。 所有其他 Activity 虽然可见,但均处于暂停状态。 但是,这些已暂停但可见的 Activity 在系统中享有比不可见 Activity 更高的优先级。 如果用户与其中一个暂停的 Activity 交互,该 Activity 将恢复,而之前的顶级 Activity 将暂停。</p> <p><strong>在多窗口模式中,用户仍可以看到处于暂停状态的应用。 应用在暂停状态下可能仍需要继续其操作。</strong><br> 例如,处于暂停模式但可见的视频播放应用应继续显示视频。因此,我们建议播放视频的 Activity 不要在 onPause()方法中暂停视频,应在onStop()暂停视频播放,并在 onStart()中恢复视频播放。</p> <p>用户使用多窗口模式显示应用时,系统将通知 Activity 发生配置变更。 该变更与系统通知应用设备从纵向模式切换到横向模式时的 Activity 生命周期影响基本相同,但设备不仅仅是交换尺寸,而是会变更尺寸。您的 Activity 可以自行处理配置变更,或允许系统销毁 Activity,并以新的尺寸重新创建该 Activity。</p> <p>给Activity加上如下配置可以保证切换成多屏模式或者画中画模式时Activity不会销毁重建。</p> <pre> <code class="language-java">android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"></code></pre> <h2>针对多窗口进行配置</h2> <p>在清单文件的 <activity>或 <application>节点中设置该属性,启用或禁用多窗口显示:</p> <pre> <code class="language-java">android:resizeableActivity=["true" | "false"]</code></pre> <p>如果该属性设置为 true,Activity 将能以分屏和自由形状模式启动。 如果此属性设置为 false,Activity 将不支持多窗口模式。 如果该值为 false,且用户尝试在多窗口模式下启动 Activity,该 Activity 将全屏显示。</p> <p>如果您的应用面向 Android N,但未对该属性指定值,则该属性的值默认设为 true。<br> 如果做电视开发或其它特殊需求,还有一个属性需要注意:</p> <pre> <code class="language-java">android:supportsPictureInPicture=["true" | "false"]</code></pre> <p>在清单文件的 <activity>节点中设置该属性,指明 Activity 是否支持画中画显示。如果 android:resizeableActivity为 false,将忽略该属性。</p> <p>当然你还可以指定在自由形状模式时 Activity 的默认大小、位置和最小尺寸:</p> <pre> <code class="language-java"><activity android:name=".MainActivity"> <layout android:defaultHeight="500dp" android:defaultWidth="600dp" android:gravity="top|end" android:minimalSize="450dp" /> </activity></code></pre> <p>对于 Android N,<layout>清单文件元素支持以下几种属性,这些属性影响 Activity 在多窗口模式中的行为:</p> <ol> <li>android:defaultWidth 以自由形状模式启动时 Activity 的默认宽度。</li> <li>android:defaultHeight 以自由形状模式启动时 Activity 的默认高度。</li> <li>android:gravity 以自由形状模式启动时 Activity 的初始位置。</li> <li>android:minimalSize 分屏和自由形状模式中 Activity 的最小高度和最小宽度。 如果用户在分屏模式中移动分界线,使 Activity 尺寸低于指定的最小值,系统会将 Activity 裁剪为用户请求的尺寸。</li> </ol> <h2>多窗口模式中运行应用注意事项</h2> <p>在设备处于多窗口模式中时,某些功能会被禁用或忽略,因为这些功能对与其他 Activity 或应用共享设备屏幕的 Activity 而言没有意义。 此类功能包括:</p> <ol> <li>某些自定义选项将被禁用;例如,在非全屏模式中,应用无法隐藏状态栏。</li> <li>系统将忽略对 android:screenOrientation属性所作的更改</li> </ol> <p><strong>Activity类中添加了以下新方法,以支持多窗口显示。</strong></p> <ol> <li><strong>Activity.inMultiWindow()</strong> 调用该方法以确认 Activity 是否处于多窗口模式。</li> <li><strong>Activity.inPictureInPicture()</strong> 调用该方法以确认 Activity 是否处于画中画模式。<strong>注</strong>:画中画模式是多窗口模式的特例。 如果 myActivity.inPictureInPicture()返回 true,则 myActivity.inMultiWindow()也返回 true。</li> <li><strong>Activity.onMultiWindowChanged()</strong> Activity 进入或退出多窗口模式时系统将调用此方法。 在 Activity 进入多窗口模式时,系统向该方法传递 true 值,在退出多窗口模式时,则传递 false 值。</li> <li><strong>Activity.onPictureInPictureChanged()</strong> Activity 进入或退出画中画模式时系统将调用此方法。 在 Activity 进入画中画模式时,系统向该方法传递 true 值,在退出画中画模式时,则传递 false 值。</li> </ol> <p>每个方法还有 Fragment版本,例如 Fragment.inMultiWindow()。</p> <h2>在多窗口模式中启动新 Activity</h2> <p>在启动新 Activity 时,用户可以提示系统如果可能,应将新 Activity 显示在当前 Activity 旁边。 要执行此操作,可使用标志Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT。传递此标志将请求以下行为:</p> <ol> <li>如果设备处于分屏模式,系统会尝试在启动系统的 Activity 旁创建新 Activity,这样两个 Activity 将共享屏幕。 系统并不一定能实现此操作,但如果可以,系统将使两个 Activity 处于相邻的位置。</li> <li>如果设备不处于分屏模式,则该标志无效。 <pre> <code class="language-java"> public void click(View v){ Intent intent=new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent); }</code></pre> </li> </ol> <p style="text-align:center"><img src="https://simg.open-open.com/show/c0e612300b88b187e9ec46f09047eea7.png" alt="是时候学习Android分屏开发了" width="429" height="811"></p> <p style="text-align:center">Paste_Image.png</p> <h2>支持拖放</h2> <p>用户可以在两个 Activity 共享屏幕的同时在这两个 Activity 之间拖放。因此,如果您的应用目前不支持拖放功能,您可以在其中添加此功能。</p> <ol> <li><strong>android.view.DropPermissions</strong>令牌对象,负责指定对接收拖放数据的应用授予的权限。</li> <li><strong>View.startDragAndDrop()</strong> View.startDrag()的新别名。要启用跨 Activity 拖放,请传递新标志 View.DRAG_FLAG_GLOBAL。如需对接收拖放数据的 Activity 授予 URI 权限,可根据情况传递新标志 <code>View.DRAG_FLAG_GLOBAL_URI_READ</code>或 <code>View.DRAG_FLAG_GLOBAL_URI_WRITE。</code></li> <li><strong>View.cancelDragAndDrop()</strong> 取消当前正在进行的拖动操作。只能由发起拖动操作的应用调用。</li> <li><strong>View.updateDragShadow()</strong> 替换当前正在进行的拖动操作的拖动阴影。只能由发起拖动操作的应用调用。</li> <li><strong>Activity.requestDropPermissions()</strong> 请求使用 DragEvent中包含的 ClipData传递的内容 URI 的权限。</li> </ol> <h2>参考文献</h2> <p><a href="/misc/goto?guid=4959673482022706271">https://developer.android.com/preview/features/multi-window.html#running</a></p> <p><br> </p> <p>文/<a href="/misc/goto?guid=4959673482105895671">于连林520wcf</a>(简书)<br> </p> <p> </p>