我们都知道,在最新的Android N系统中,加入了一个新的功能,就是多窗口模式。多窗口模式允许我们在屏幕上显示两个窗口,每个窗口显示的内容不同,也就是说,我们可以一遍看电视剧,一边聊微信。

这里我们通过官方提供的一个Demo来了解一下,作为开发者,怎么给我们的App也适配多窗口模式。

这里给出代码github地址,需要的话可以clone下来边看边了解:

https://github.com/googlecodelabs/getting-ready-for-android-n

根据指导文档这里分为几个部分:

1. 多窗口模式的开关

2. 多窗口模式适配

3. 多窗口模式中打开新的窗口处理

我们一个一个来了解下:

1. 多窗口模式的开关

默认情况下,我们的App都是允许多窗口的,但是,如果没有进行属性的设置,会系统会抛出一个提示这个应用可能不支持多窗口模式

那么,如果我们的应用要支持这个模式并且不让这个消息弹出来,要怎么做呢?

很简单,只需要在Activity声明的时候加入一个属性resizeableActivity,并且设置其值为true即可

<activity
android:name=".MainActivity"
android:resizeableActivity="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

这个属性的设置会导致三种情况:

① 如果不声明这个属性,那么默认允许进入多窗口模式,但是会有上面图片的提示(第一次运行的时候)

② 如果声明了这个属性,并设置值为true,那么允许进入多窗口模式,并且不会提示

③ 如果声明了这个属性,并设置值为false,那么不允许进入多窗口模式,只允许全屏显示

2. 多窗口模式的适配

当我们允许App进入多窗口模式之后,App只能占据屏幕的一部分,假设我们的App运行的界面如下(官方Demo):

可以看到,在App的上半部分是一个蓝色的图片背景,在上面显示了当前的天气状况,但是如果我们不进行适应,那么进入了多窗口模式之后,这个部分的内容就会几乎占满整个窗口,这个时候我们就需要进行一下适配,当进入多窗口模式之后更换掉这一个布局,将内容进行重新排版,以便显示更多的内容。

默认情况下的布局:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:background="@drawable/today_touch_selector"> <LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="7"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_marginLeft="60dp"
android:orientation="vertical"> <TextView
android:id="@+id/list_item_date_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceLarge"
android:fontFamily="sans-serif-condensed"
android:textColor="@color/white" /> <TextView
android:id="@+id/list_item_high_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="72sp"
android:fontFamily="sans-serif-light"
android:textColor="@color/white" /> <TextView
android:id="@+id/list_item_low_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="36sp"
android:layout_marginLeft="8dp"/>
</LinearLayout> <LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="5"
android:layout_marginRight="16dp"
android:orientation="vertical"
android:gravity="center_horizontal|bottom"> <ImageView
android:id="@+id/list_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/> <TextView
android:id="@+id/list_item_forecast_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed"
android:layout_gravity="center_horizontal"
android:textAppearance="?android:textAppearanceLarge"
android:textColor="@color/white"/>
</LinearLayout>

这里主要看到,根布局中设置了背景图,这个图片就是那个我们看到蓝色的那一张,里面定义了一些TextView来显示信息,定义了一个ImageView来显示天气的图标,简单了解下布局即可。

因为这里用到Fragment,可能直接看工程不会很清晰,我们打开res下的values-sw400dp,然后打开里面的refs.xml文件,内容如下:

<resources>
<item type="layout" name="fragment_detail">@layout/fragment_detail_wide</item>
<item type="layout" name="list_item_forecast_today">@layout/list_item_forecast_today_big</item>
</resources>

我们将光标移动到第二个Item的name属性的值中,然后按下Alt+F7找到项目中用到这个value的地方:

可以看到,只有一个地方使用了这个value,我们点进去可以看到,这个布局其实是被用在了一个CursorAdapter中,这里应该就知道了,这个布局是被当作一个ListView的头部来使用。

我们先不管工程是如何实现的,我们只需要知道这个布局会被用在界面中的ListView中的头部中就可以了。这个时候我们再看看这个folder的文件名values-sw400dp,sw400dp就表明了这个value是在屏幕最短边大于等于400dp的时候生效(前提是有其他不同的value文件夹)。

因为在多窗口模式的情况下,每个窗口分的大小是允许用户控制的(可以通过中间的滑动来改变两个窗口的大小),而当用户将滑块向上滑动,有可能会会导致最短边小于400dp,因此,我们可以在工程的res下创建一个更小的values文件名为values-sw220dp,接着再创建一个布局文件(里面的控件id必须和上面的布局一致,这里Demo中已经给出了一个布局,名字是list_item_forecast),接着在values-sw220dp下创建一个refs.xml的文件,文件内容如下:

<resources>
<item type="layout" name="list_item_forecast_today">@layout/list_item_forecast</item>
</resources>

运行的效果如下所示,可以看到,当屏幕最短边大于220dp而小于400dp的时候,会显示如右图的布局:

  

这里还要注意一个问题,如果我们按照上面定义的220dp来命名,那么如果屏幕被继续向上拉,会导致最小边小于220dp,这个时候又会恢复到左边的这个布局,这里解决办法是把220dp设置的更小(如100dp)即可。

这里补充一下效果:

 

3. 在多窗口中打开一个Activity

在官方的Demo中,可以通过右上角的菜单中的“Map Location”来打开地图App,这个时候如果不加以设置,地图App会在当前的这个小窗口中打开。

那么我们可不可以让系统在下面的这个窗口打开呢?因为考虑到用户可以不用跳出我们的App而对地图App进行操作,谷歌官方也是提供了这个功能,而且比较简单。

我们找到ForecastFragment.class这个类,定位到206行,代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(geoLocation);

很明显这里是要打开一个Activity,接着我们只需要给这个Intent设置一个标签,完整代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(geoLocation);
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);

这个时候,我们再此运行App并打开地图App,会发现,地图App会在另一个窗口中被打开。

Android开发学习之路-Android N新特性-多窗口模式的更多相关文章

  1. Android开发学习之路--Android Studio cmake编译ffmpeg

      最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...

  2. Android开发学习之路--Android系统架构初探

    环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...

  3. Android开发学习之路-Android Studio开发小技巧

    上一次发过了一个介绍Studio的,这里再发一个补充下. 我们都知道,Android Studio的功能是非常强大的,也是很智能的.如果有人告诉你学Android开发要用命令行,你可以告诉他Andro ...

  4. Android开发学习之路-Android中使用RxJava

    RxJava的核心内容很简单,就是进行异步操作.类似于Handler和AsyncTask的功能,但是在代码结构上不同. RxJava使用了观察者模式和建造者模式中的链式调用(类似于C#的LINQ). ...

  5. Android开发学习之路-Android Design Support Library使用(CoordinatorLayout的使用)

    效果图: 上面的这个图有两个效果是,一个是顶部的图片,在上滑之后会隐藏起来并且显示出一个ToolBar(ToolBar类似于ActionBar,但是只有ToolBar是兼容Material Desig ...

  6. Android开发学习之路--Android Studio项目目录结构简介

    既然已经搭建好环境了,那就对Android Studio中项目目录结构做个简单的了解了,这里以最简单的Hello工程为例子,新建好工程后看如下三个工程视图: 1.Android工程 manifests ...

  7. Android开发学习之路-Android Studio真神器!

    放假之后电脑配置升级就开始用Android Studio(下面简称AS)了,那个酸爽真的不是一般的啊,这里开一篇博客来记录下AS里面各种酷炫的功能,有更好玩的,大家不要吝啬,评论告诉我吧! 最近And ...

  8. Android开发学习之路--Activity之初体验

    环境也搭建好了,android系统也基本了解了,那么接下来就可以开始学习android开发了,相信这么学下去肯定可以把android开发学习好的,再加上时而再温故下linux下的知识,看看androi ...

  9. Android开发学习之路--基于vitamio的视频播放器(二)

      终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...

随机推荐

  1. 使用Mysql 5.5数据库Hibernate自动建表创建表出错table doesn't exist

    在mysql 5.0版本以后不支持 type=InnoDB 关键字,需要使用 engine=InnoDB 配置文件方言改成如下即可 <property name="dialect&qu ...

  2. C# 发送邮件中包含图片

    List<string> To = new List<string>(); To.Add("jake_ge@askey.com.tw"); List< ...

  3. VS2015 RTM与ASP.NET 5 RC1之坑

    最近Asp.Net 5的RC1出来了 VS2015的Update1也开始进入RC阶段 嗯,微软尿性,是时候转移到VS2015了 开始踩坑之旅 装好VS2015后,当然是开始折腾ASP.Net 5嘛 建 ...

  4. 【尺取】POJ 3320

    POJ 3320 Jessica's Reading Problem 题意:一本书P页,第i页有ai知识点,问你至少从某一处开始连续要翻多少页才能复习完所有的知识点,不能跨页翻. 思路:<挑战程 ...

  5. windows消息机制详解(转载)

    消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.消息本身是作为一个记录传递给应用程序的 ...

  6. MSSQL数据库表加锁

    所指定的表级锁定提示有如下几种: 1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁. 2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可 ...

  7. display:none与visible:hidden的区别

    display:none和visible:hidden都能把网页上某个元素隐藏起来,但两者有区别: display:none ---不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失,通俗来说就 ...

  8. day01-1 常用dos命令

    计算机 = 硬件 + 软件 硬件: cpu 计算机中的运算核心与控制核心.负责了解析计算机的指令与计算机运算的执行. 内存 数据与cpu交互的桥梁.程序所需要的数据都会先加载到内存中.cpu直接读取内 ...

  9. java学习中的一些疑惑解答

    一.java中的枚举类型: 在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的.例如星期一到星期日七个数据元素 ...

  10. jquery 回到顶部,简洁大方

    效果