??????Android SDK 提供了Display類咪奖,實現(xiàn)在主屏幕之外的擴展屏幕上顯示不同于主屏幕的UI,而擴展屏幕上的UI顯示笛厦,實質(zhì)上是顯示了一個系統(tǒng)級別的Dialog餐茵,我們可以將自已的View加入到此Dialog中進行顯示。
??????擴展屏可以有一個或超過一個辆苔,實際的應用中需要底層驅(qū)動的支持算灸。在官方的模擬器中我們可以模擬出一個副屏,進行調(diào)試(當然除了模擬器驻啤,我們的手機也可以進行模擬)
??????以Android10官方模擬器為例菲驴,來說明如何進行雙屏異顯的調(diào)試。
一骑冗、設置Simulate secondary displays
??????模擬器中打開"設置-開發(fā)者選項"界面赊瞬,在列表中找到"Simulate secondary displays"條目。
點擊后贼涩,在彈出的對話框中選擇副屏的分辨率:
??????比如我們選中720p巧涧,模擬器屏幕的左上角上會立即呈現(xiàn)出副屏的窗口,其顯示內(nèi)容默認為與主屏顯示一致:
??????副屏窗口就是一個Dialog遥倦,可以拖動谤绳,讓其顯示在合適的位置。
二袒哥、實現(xiàn)副屏異顯
??????因為副屏默認顯示與主屏一致缩筛,如果要實現(xiàn)雙屏異顯,我們需要在APP中進行開發(fā)堡称,將自定義布局加入到副屏中進行顯示瞎抛。
1、申請權(quán)限
AndroidManifest.xml中添加兩個權(quán)限:
<uses-permission android:name= "android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name= "android.permission.SYSTEM_OVERLAY_WINDOW"/>
因為android 6.0及之后 android.permission.SYSTEM_OVERLAY_WINDOW需要系統(tǒng)動態(tài)授權(quán)才能啟用却紧,所以在APP啟動時加入如下代碼進行動態(tài)授權(quán):
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
//啟動Activity讓用戶授權(quán)
if (!Settings.canDrawOverlays(this)) {
val intent: Intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse( "package:$packageName"))
startActivityForResult(intent, 1010)
}
}
系統(tǒng)會彈出授權(quán)窗口桐臊,開啟即可:
2、獲取副屏的Display對象
//獲取顯示管理服務代理對象
val displayManger = activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager?
//當前副屏的Display
private var currentDisplay: Display? = null
displayManger?.run {
//取所有副屏對應的Display列表
val displays = getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION)
if (!displays.isEmpty()){
val display = displays.find { it.isValid } //取第一個有效的Display
//無副屏到接入新的副屏
if (currentDisplay == null) {
//保存副屏的Display
currentDisplay = display
}
}
}
第一步"設置Simulate secondary displays"中我們已經(jīng)設置過副屏了晓殊,所以currentDisplay不會為空断凶。
3、初始化Context與WindowManager
//副屏Context
private var presentationContext: Context? = null
//副屏窗口管理器
private var presentationWindowManager:WindowManager? = null
val displayContext: Context = activity.createDisplayContext(display)
val wm = displayContext.getSystemService(WINDOW_SERVICE) as WindowManager
presentationContext = object :ContextThemeWrapper(displayContext, android.R.style.Theme){
override fun getSystemService(name: String): Any {
if (WINDOW_SERVICE == name) {
return(wm)
}
return super.getSystemService(name)
}
}
presentationWindowManager =
(presentationContext as ContextThemeWrapper).getSystemService(Context.WINDOW_SERVICE) as WindowManager
4挺物、向副屏添加View
實現(xiàn)一個只顯示純藍色背景的布局:default.xml
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_dark"/>
以下是向副屏窗口加入View的參考代碼:
//通過布局id生成View
val inflater = LayoutInflater.from(presentationContext!!)
val view = inflater.inflate(R.layout.default, null)
//最終副屏會顯示default.xml的內(nèi)容
presentationWindowManager?.addView(view,buildLayoutParams())
buildLayoutParams函數(shù):
@SuppressLint("InlinedApi")
private fun buildLayoutParams():WindowManager.LayoutParams {
if(Build.VERSION.SDK_INT >= 26){
return WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
0,
0,
TYPE_APPLICATION_OVERLAY, //FIRST_SYSTEM_WINDOW + 38
0, PixelFormat.TRANSPARENT
)
} else {
return WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
0,
0,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
0, PixelFormat.TRANSPARENT
)
}
}
說明一下:
Android8.0及以后只能使用TYPE_APPLICATION_OVERLAY窗口類型來創(chuàng)建懸浮窗懒浮。(其它窗口類型在8.0已經(jīng)被廢棄掉)
看一下最終的效果:
副屏還可以顯示其它更復雜的布局飘弧,也可以顯示圖片與播放視頻识藤,如下是播放視頻的截圖:
最后的問題:
副屏是否支持觸摸砚著?
目前我了解所知,原生并不支持副屏觸摸動作痴昧,但是修改源碼是可以達到的(主要是修改觸控事件的向上分發(fā)邏輯稽穆,因為分發(fā)時只有一個主屏)。
可以參考:http://www.reibang.com/p/572eaa37ddd3
另外Android自帶一個系統(tǒng)組件Presentation赶撰,可以簡化多屏異顯舌镶,其實質(zhì)也是封裝了上面的過程。