1. 程式人生 > >是時候來了解android7了:多視窗支援

是時候來了解android7了:多視窗支援

本文已授權微信公眾號:鴻洋(hongyangAndroid)在微信公眾號平臺原創首發。

這篇文章開始, 我們來了解一下android 7的一些新特性, 話說今年android 7預覽版本來的比以往都稍早一些, 這樣對於我們開發者來說算是一個好訊息, 我們可以有充足的時間來看新版android的一些特性, 讓我們的應用更快的支援到android 7. 前段時間android 7傳送了最終預覽版本, 這也表示現在的sdk已經是最終的sdk了, 所以我們從現在開始, 完全可以讓應用支援到android 7了.

今天的這篇文章我們來介紹一下在android 7上最為直觀的一個特性-多視窗支援, 當然也可以叫他分屏模式. 有了這個特性媽媽再也不用擔心我應用間切換的煩惱了, 那什麼多視窗模式呢? 其實在很多國產機器上早就已經支援多視窗了, 只不過這次android 7標準化了多視窗模式, 這對我們開發者來說, 可以算是天大的好訊息. 廢話那麼說, 我們還沒看到多視窗模式什麼樣呢? 下面一張圖來體驗一下.

讓我們的應用支援多視窗模式

如何讓我們的應用支援多視窗模式呢? 其實android 7是預設開啟多視窗模式的, 不過如果你用低於android 7的sdk構建的應用, 會在多視窗模式下發出一個警告. 那如何讓我們的應用禁用多視窗模式呢? 畢竟好多人還是不喜歡讓自己的應用和別人分享螢幕的(比如QQ), 這個也很簡單, 只需要在清單檔案的application或者activity中新增android:resizeableActivity="false"就ok了(目測, 接下來大多數國產APP中都會有這條屬性).

多視窗模式的一些配置

禁用歸禁用, 但是對於我們開發者來說, 還是要繼續瞭解一下多視窗模式的, 那接下來我們來看一下, 在多視窗模式中又會多哪些屬性. 在清單檔案中我們配置activity的地方, 又多了一個layout

節點, 這個節點的屬性不多, 主要是用來配置多視窗模式下的一些屬性的. 下面我們首先來看看如何配置, 然後來說說都是什麼作用:

<activity android:name=".MyActivity">
    <layout
          android:defaultHeight="500dp"
          android:defaultWidth="500dp"
          android:gravity="bottom|end"
          android:minimalHeight="200dp"
          android:minimalWidth
="200dp" />
</activity>

很簡單,就是多了一個layout節點, 我們來看看他的屬性.

  1. android:defaultHeight 這條是配置多視窗模式下預設的高度.
  2. android:defaultWidth 這條是配置多視窗模式下預設的寬度.
  3. android:gravity 這條是配置多視窗模式下activity的初始位置. (注意:這條語句在我測試過程中發現貌似沒起到作用)
  4. android:minimalHeight 這條是配置多視窗模式下最小的高度. (注意:這條語句在我測試過程中發現配置後直接編譯不了)
  5. 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是否在多視窗模式下. 接下來, 我們來演示一下生命週期吧.

首先是進入多視窗模式(進入多視窗模式的方法是長按手機上的overview鍵)

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重啟了.

那退出多視窗模式呢?

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中暫停視訊播放, 在這種情況下, 失去焦點後就暫停了, 顯然這不是很好的使用者體驗, 我們需要把視訊的暫停和繼續放到onStoponStart中.

啟動activity

現在我們在來學習下如何在多視窗模式下啟動activity. 這樣分兩種情況了, 一種在是當前棧中啟動, 另一種是在新的棧中啟動.
對於第一種情況, 很簡單, 就是在當前視窗中啟動新的activity, 而第二種情況, 我們可以指定在同級視窗下啟動, 只需要給intent設定一個FLAG_ACTIVITY_LAUNCH_ADJACENTflag就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());

跨activity拖拽

從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"就可以了.

相關推薦

是時候android7:視窗支援

本文已授權微信公眾號:鴻洋(hongyangAndroid)在微信公眾號平臺原創首發。 這篇文章開始, 我們來了解一下android 7的一些新特性, 話說今年android 7預覽版本來的比以往都稍早一些, 這樣對於我們開發者來說算是一個好訊息, 我

是時候android7:通知直接回復

本文已授權微信公眾號:鴻洋(hongyangAndroid)在微信公眾號平臺原創首發。 這是<是時候來了解android7>系列的第三篇文章了, 前面兩篇分別介紹了多視窗模式和shortcut功能, 今天我們來點簡單的, 說一說通知直接回復功能. 可能很多朋

是時候android7:shortcuts(快捷方式)

本文已授權微信公眾號:鴻洋(hongyangAndroid)在微信公眾號平臺原創首發。 就在前幾天的一個晚上, Google召開了它的秋季釋出會, 毫無懸念的宣佈了它的最新手機品牌Pixel, 與此同時我的nexus裝置也從親兒子降級成為乾兒子. 不過還好Google並

Android OkHttp完全解析 是時候OkHttp

JD rect eat serve 功能 sessions 文件名 -h 適合 一、概述 最近在群裏聽到各種討論okhttp的話題,可見okhttp的口碑相當好了。再加上Google貌似在6.0版本裏面刪除了HttpClient相關API,對於這個行為不做評價。為了更好的在

Android7.0新特性介紹(一)——視窗支援

Android7.0新特性 1 多視窗支援 (在手機和平板中叫分屏模式,最多就倆視窗) 在 Android N 中,Google引入了一個新的而且非常需要的多工處理功能 — 多視窗支援。 1.1 進入多視窗模式 啟動App,長按系統導航欄右

Android7.0視窗實現原理(一)

概述 在Android N(7.0)版本開始,系統支援了多視窗功能。在有了多視窗支援之後,使用者可以同時開啟和看到多個應用的介面。並且系統還支援在多個應用之間進行拖拽。在大螢幕裝置上,這一功能非常實用。 在Android N中多視窗有三種表現形式: 分屏模式 該模式主要

Android7.0 視窗特性

直接複製過來圖片不能顯示 想看圖片 請點選下面的連線 在以往的Android系統上,所有Activity都是全屏的,如果不設定透明效果,一次只能看到一個Activity介面。 但是從Android N(7.0)版本開始,系統支援了多視窗功能。在有了多視窗支援之後,使

Android7.0視窗實現原理(二)

    從上文可以知道當開始分屏時從SystemUI呼叫到ActivityStackSupervisor中的startActivityFromRecentsInner函式,當要分屏的Activity已經存在了,屬於熱啟動分屏。 在anyTaskForIdLocked函式

Android與H5互調(通過實例Hybrid App)

ext 傳感器 顯示 相同 blank show ima 一次 點擊 前些日子,Android原生開發將被取締的吵得火熱,JavaScript是能做一個完全的APP,但只使用JavaScript做出來的APP也不會牛逼到哪裏去。最好的是混合(Hybrid)開發,在需要的

VR全景加盟-VR就全景智慧城市

購物 這一 動作 為什麽 快速 cor 平臺 進行 這不 關於什麽是真正的VR說了這麽多,面對剛剛起步的VR,如何辨別判斷一個真正的VR形式呢。除了我們所說幾個參數或者大家關註的眩暈感、臨場感,真正的VR究竟帶給大家什麽樣的特性呢?這個就要從VR的本質談起。虛擬現實作為一種

今天做項目用CSS偽類選擇器“before”,就它怎麽使用,又如何用?

偽類選擇器 line ref n) ima cnblogs hello 了解 nbsp 我不知道有沒有小夥伴以前跟我一樣,在一個元素內部想要添加一個小圖標或者小東西的時候, 直接在HTML文檔裏自己加上<span>標簽,或者其他的。亦或者用javascript在

C#線程基礎,適合新手

net 應用程序 sin pri rgs 工作 而在 了解 thread 一、創建線程   在整個系列文章中,我們主要使用Visual Studio 2015作為線程編程的主要工具。在C#語言中創建、使用線程只需要按以下步驟編寫即可: 1、啟動Visual Studio

從node.js模塊化開發javascript閉包

js模塊 efi 使用 ict node cau class 無法訪問 完成   之前看過很多關於javascript閉包的解釋,只有短短幾個demo,一大段晦澀難懂的介紹,巴拉巴拉一大段閉包的概念,但是到最後也沒看懂閉包到底是什麽意思,起什麽作用,直到昨晚淩晨,我在學習n

進程(),守護進程,互斥鎖,信號量,進程Queue與線程queue

生產 模塊 多進程 異常 參數 進程池 數據 div ssi 一、守護進程   主進程創建守護進程,守護進程的主要的特征為:①守護進程會在主進程代碼執行結束時立即終止;②守護進程內無法繼續再開子進程,否則會拋出異常。 實例: from multiprocessing im

[py]你真的核處理器嗎? 線程

註意 董事會 fusion 整體 用戶 繼續 高速 多核處理器 真的 你真的了解多核處理器嗎? 1.雙核≠雙性能 多核不一定會使你的手機或電腦速度更快,但它將提高你的PC的整體性能,這是一個有所不同的細微的技術特色。多核處理器的性能提升並不是簡單CPU核心的倍數,因為受到

動癥發病病因一下

心態 生活 ont 功能 維生素 自己 動作 寂寞 span 多動癥發病病因了解一下 給孩子制定一定合理的膳食,是預防兒童多動癥的好方法,專家指出,導致孩子患上兒童多動癥的罪魁禍首,就是家長自己,因為有很多家長只是顧著自己的工作,讓孩子感到寂寞無聊,所以才會出現兒童多動癥的

線程池你真不一下嗎?

java並發編程 新建 out 沒有 在線 dex keepal AD 定性 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這麽簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQS簡簡單單過一

通過一個輪播圖插件構造函數

num 類型 bsp 函數的原型 size cti type屬性 箭頭 true 例子:https://github.com/wayaha/rotateChart 在ES5中,構造函數的使用可以說是很能體現面向對象的編程思想,有學過c的同學,可以很明顯體會到面向過程和面向對

從列表和實例python叠代器

name color font spl 第一次 () 圖片 IT 實現 什麽是叠代器?它是一個帶狀態的對象,在你調用next()方法的時候返回容器中的下一個值,任何實現了__iter__和__next__()(python2中實現next())方法的對象都是叠代器,__it

線程通訊輪詢賣票一下

import getname tar args void TE equals 輪詢 In package com.xp.test; import java.util.concurrent.locks.Condition;import java.util.concurrent