今天的這篇文章咱們來介紹一下在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"
就能夠了.