今天的这篇文章咱们来介绍一下在android 7上最为直观的一个特性-多窗口支持, 固然也能够叫他分屏模式. 有了这个特性妈妈不再用担忧我应用间切换的烦恼了, 那什么多窗口模式呢? 其实在不少国产机器上早就已经支持多窗口了, 只不过此次android 7标准化了多窗口模式, 这对咱们开发者来讲, 能够算是天大的好消息. 废话那么说, 咱们还没看到多窗口模式什么样呢? 下面一张图来体验一下.android
如何让咱们的应用支持多窗口模式呢? 其实android 7是默认开启多窗口模式的, 不过若是你用低于android 7的sdk构建的应用, 会在多窗口模式下发出一个警告. 那如何让咱们的应用禁用多窗口模式呢? 毕竟好多人仍是不喜欢让本身的应用和别人分享屏幕的(好比QQ), 这个也很简单, 只须要在清单文件的application或者activity中添加android:resizeableActivity="false"
就ok了(目测, 接下来大多数国产APP中都会有这条属性).app
禁用归禁用, 可是对于咱们开发者来讲, 仍是要继续了解一下多窗口模式的, 那接下来咱们来看一下, 在多窗口模式中又会多哪些属性. 在清单文件中咱们配置activity的地方, 又多了一个layout
节点, 这个节点的属性很少, 主要是用来配置多窗口模式下的一些属性的. 下面咱们首先来看看如何配置, 而后来讲说都是什么做用:ide
<activity android:name=".MyActivity"> <layout android:defaultHeight="500dp" android:defaultWidth="500dp" android:gravity="bottom|end" android:minimalHeight="200dp" android:minimalWidth="200dp" /> </activity>
很简单,就是多了一个layout节点, 咱们来看看他的属性.布局
android:defaultHeight
这条是配置多窗口模式下默认的高度.android:defaultWidth
这条是配置多窗口模式下默认的宽度.android:gravity
这条是配置多窗口模式下activity的初始位置. (注意:这条语句在我测试过程当中发现貌似没起到做用)android:minimalHeight
这条是配置多窗口模式下最小的高度. (注意:这条语句在我测试过程当中发现配置后直接编译不了)android:minimalWidth
这条是配置多窗口模式下最小的宽度. (注意:这条语句在我测试过程当中发现配置后直接编译不了)
其实, 就算咱们的应用要支持多窗口模式, 上面的layout
节点咱们也是彻底能够忽略的(并且我感受大部分状况下是要忽略的)学习
其实, 多窗口自己仍是很简单的, 咱们最关心的仍是activity在多窗口模式下的生命周期, 下面咱们就用一段demo来看一下在多窗口模式下activity的生命周期.测试
@Override protected void onCreate(Bundle savedInstanceState) { prntLog("onCreate"); } @Override protected void onStart() { prntLog("onStart"); super.onStart(); } @Override protected void onResume() { prntLog("onResume"); super.onResume(); } @Override protected void onPause() { prntLog("onPause"); super.onPause(); } @Override protected void onStop() { prntLog("onStop"); super.onStop(); } @Override protected void onDestroy() { prntLog("onDestory"); super.onDestroy(); } @Override protected void onSaveInstanceState(Bundle outState) { prntLog("onSaveInstanceState"); super.onSaveInstanceState(outState); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { prntLog("onRestoreInstanceState"); super.onRestoreInstanceState(savedInstanceState); } @Override public void onMultiWindowModeChanged(boolean isInMultiWindowMode) { prntLog("onMultiWindowModeChanged:" + isInMultiWindowMode); prntLog("isInMultiWindowMode:" + isInMultiWindowMode()); super.onMultiWindowModeChanged(isInMultiWindowMode); } private void prntLog(String log) { Log.d("MainActivity", log); }
在开始以前, 咱们发现有一个回调onMultiWindowModeChanged
是咱们不太熟悉的, 这个回调是为了多窗口模式新增的一个, 在进入或者退出多窗口模式, 这个回调会执行, 并且, 咱们还能够用过isInMultiWindowMode()
方法来判断当前activity是否在多窗口模式下. 接下来, 咱们来演示一下生命周期吧.ui
首先是进入多窗口模式(进入多窗口模式的方法是长按手机上的overview键)this
D/MainActivity: onMultiWindowModeChanged:true D/MainActivity: isInMultiWindowMode:true D/MainActivity: onPause D/MainActivity: onSaveInstanceState D/MainActivity: onStop D/MainActivity: onDestory D/MainActivity: onCreate D/MainActivity: onStart D/MainActivity: onRestoreInstanceState D/MainActivity: onResume D/MainActivity: onPause
从log中能够发现, 在进入多窗口模式时, 首先回调的是onMultiWindowModeChanged
方法, 而后很使人沮丧的是咱们的activity销毁了,而且调用了onSaveInstanceState
方法, 而后activit启动, 其实就是咱们activity重启了.spa
那退出多窗口模式呢?code
D/MainActivity: onSaveInstanceState D/MainActivity: onStop D/MainActivity: onDestory D/MainActivity: onCreate D/MainActivity: onStart D/MainActivity: onRestoreInstanceState D/MainActivity: onResume D/MainActivity: onPause D/MainActivity: onMultiWindowModeChanged:false D/MainActivity: isInMultiWindowMode:false D/MainActivity: onResume
首先是一个配置变化销毁的过程, 而后是一个恢复的过程, 而且回调了onMultiWindowModeChanged
方法, 此时的isInMultiWindowMode
是false.
继续看生命周期, 若是咱们的焦点从一个activity中切换到了和它同处于多窗口模式下的另一个activity呢?
D/MainActivity: onPause
D/SecondActivity: onResume
此时当前activity会暂停, 新获取角度的activity回调onResume
, 在这里官网还有一个notice, 好比咱们以前是在onPause
中暂停视频播放, 在这种状况下, 失去焦点后就暂停了, 显然这不是很好的用户体验, 咱们须要把视频的暂停和继续放到onStop
和onStart
中.
如今咱们在来学习下如何在多窗口模式下启动activity. 这样分两种状况了, 一种在是当前栈中启动, 另外一种是在新的栈中启动.
对于第一种状况, 很简单, 就是在当前窗口中启动新的activity, 而第二种状况, 咱们能够指定在同级窗口下启动, 只须要给intent设置一个FLAG_ACTIVITY_LAUNCH_ADJACENT
flag就ok.
例以下面的代码:
Intent intent = new Intent(this, SecondActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT|Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
上面的代码咱们会在另一个窗口启动新的activity
另外, 咱们还能够制定新启动的activity的大小.
Rect bounds = new Rect(500, 300, 100, 0); ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchBounds(bounds); Intent intent = new Intent(this, SecondActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT|Intent.FLAG_ACTIVITY_NEW_TASK); ActivityCompat.startActivity(this, intent, options.toBundle());
从android 4.0开始, android就已经支持activity内的内容拖拽了, 如今在多窗口模式下, android加强了拖拽功能, 另它在多窗口模式下能够在activity间实现内容的拖拽, 不过在activity间也仅限于内容的拖拽, 对view的跨activity拖拽仍是不能够的. 如今咱们在MainActivity和SecondActivity以前来模拟一下跨activity拖拽内容.
// MainActivity Button view = (Button) findViewById(R.id.button); view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { ClipData data = ClipData.newPlainText(view.getClass().getName(), ((Button) view).getText()); View.DragShadowBuilder builder = new View.DragShadowBuilder(view); view.startDragAndDrop(data, builder, view, View.DRAG_FLAG_GLOBAL); return true; } });
这里咱们监听button的长按事件, 在长按事件中, 首先咱们用button的文本构建一个ClipData
对象. 而后调用view.startDragAndDrop
方法来启动拖拽. 这里要注意一下最后一个参数View.DRAG_FLAG_GLOBAL
, 这个flag表示咱们能够跨activity进行拖拽.
接着咱们来看看SecondActivity如何处理拖拽事件.
final TextView content = (TextView) findViewById(R.id.content); findViewById(R.id.container).setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View view, DragEvent dragEvent) { switch (dragEvent.getAction()) { case DragEvent.ACTION_DRAG_STARTED: prntLog("drag started"); break; case DragEvent.ACTION_DRAG_ENTERED: prntLog("drag entered"); break; case DragEvent.ACTION_DROP: ClipData.Item item = dragEvent.getClipData().getItemAt(0); content.setText(item.getText()); break; case DragEvent.ACTION_DRAG_ENDED: prntLog("drag entered"); break; } return true; } });
这里首先咱们拿到根布局(这里就先不要纠结根布局究竟是谁了, 这里的根布局指的是content_view的根布局), 而后给它设置OnDragListener
的监听, 在ACTION_DROP
时候咱们经过dragEvent.getClipData().getItemAt(0)
拿到拖拽的item, 而后经过getText()
方法获取到内容, 而且设置到TextView
上显示.
来看看效果:
ok, 到如今为止android 7的多窗口模式咱们就介绍完了, 这些内容你们有点印象就能够, 毕竟在咱们平常的工做中基本一个android:resizeableActivity="false"
就能够了.