Android 多螢幕操作小技巧:DisplayId 那些事


Android 多螢幕操作小技巧:DisplayId 那些事

在開發 Android 應用程式時,特別是需要處理多螢幕顯示的情況,比如外接顯示器或投影機,了解如何管理不同的螢幕(Display)就變得非常重要。今天,我想跟大家分享一些關於如何取得和操作螢幕的 displayIdContextWindowManager,以及如何在指定的螢幕上啟動 Activity 或添加 View 的方法。

如何取得目前應用的 DisplayId?

主螢幕的 displayId 通常是 0。如果你想知道你的應用程式目前在哪個螢幕上運行,可以用 ContextWindowManager 來取得:

kotlin
複製程式碼
// 方法一:透過 Context 或 View
val displayId = context.display?.displayId ?: -1
val displayIdFromView = view.display.displayId

// 方法二:透過 WindowManager
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val displayIdFromWindowManager = windowManager.defaultDisplay.displayId

注意:如果 displaynull,那可能是因為 View 或 Activity 還沒初始化,或者還沒被加入到 ViewGroup 中。

了解 DisplayId 的分配方式

  • 主螢幕的 displayId 通常是 0
  • 其他外接螢幕的 displayId 可能是 123,依此類推。
  • 如果你拔掉再插回外接螢幕,displayId 可能會改變,不一定跟之前一樣。

不同螢幕的 Context 和 WindowManager

每個螢幕的 displayIdContextWindowManager 都不一樣,所以在操作時要特別小心。例如,當你想在不同的螢幕上做些事情,可以這樣取得對應的 ContextWindowManager

val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
for (display in displayManager.displays) {
    val displayId = display.displayId
    val displayContext = context.createDisplayContext(display)
    val displayWindowManager = displayContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    // 你可以在這裡用 displayContext 和 displayWindowManager 做你想做的事
}

獲取所有 Display 及其解析度

如果你想知道裝置上所有螢幕的資訊,包括它們的解析度,可以這樣做:

val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
for (display in displayManager.displays) {
    val metrics = DisplayMetrics()
    display.getRealMetrics(metrics)
    Timber.d("Display ID: ${display.displayId}, 解析度: ${metrics.widthPixels}x${metrics.heightPixels}")
}

這段程式碼會把所有螢幕的 displayId 和解析度都列出來。

在指定的 Display 上啟動 Activity

一般來說,當你啟動一個 Activity,它會在你應用程式當前所在的螢幕顯示。但如果你想讓它在指定的螢幕上出現,可以這樣做:

val options = ActivityOptions.makeBasic()
options.launchDisplayId = 2  // 這裡填你想指定的 DisplayId
val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent, options.toBundle())

注意:要確保你指定的 displayId 是存在的,否則可能會啟動失敗哦。

在指定的 Display 上添加 View

有時候,你可能想在特定的螢幕上添加一些 View。你可以這樣做:

val displayId = 2  // 指定你想要的 DisplayId
val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val display = displayManager.getDisplay(displayId)
val displayContext = context.createDisplayContext(display)
val displayWindowManager = displayContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager

// 創建你想要添加的 View
val myView = View(displayContext)
// 設定 LayoutParams
val params = WindowManager.LayoutParams(
    WindowManager.LayoutParams.MATCH_PARENT,
    WindowManager.LayoutParams.MATCH_PARENT
)
// 在指定的螢幕上添加 View
displayWindowManager.addView(myView, params)

知道你的應用佔用了多大的螢幕空間嗎?

有時候,我們需要知道應用程式實際佔用了多少螢幕空間。可以用以下方法取得:

fun Context.getCurrentScreenSize(): Size {
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // Android 11 以上
        val windowMetrics = windowManager.currentWindowMetrics
        val bounds = windowMetrics.bounds
        Size(bounds.width(), bounds.height())
    } else {
        // Android 11 以下
        val display = windowManager.defaultDisplay
        val displayMetrics = DisplayMetrics()
        display.getMetrics(displayMetrics)
        Size(displayMetrics.widthPixels, displayMetrics.heightPixels)
    }
}

取得螢幕的真實大小(包含狀態列、導航列)

如果你需要取得整個螢幕的實際解析度,包括狀態列和導航列,可以這樣做:

fun Context.getRealScreenSize(): Size {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && this is Activity) {
        // Android 11 以上
        val windowMetrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
        val bounds = windowMetrics.bounds
        Size(bounds.width(), bounds.height())
    } else {
        // Android 11 以下
        val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = windowManager.defaultDisplay
        val displayMetrics = DisplayMetrics()
        display.getRealMetrics(displayMetrics)
        Size(displayMetrics.widthPixels, displayMetrics.heightPixels)
    }
}

總結

在多螢幕的環境下開發 Android 應用程式,需要特別注意不同螢幕的 displayIdContextWindowManager 等資源。希望透過這些小技巧,你能更輕鬆地:

  • 取得當前應用的 displayId
  • 了解不同螢幕的 displayId 是如何分配的。
  • 為不同的螢幕建立對應的 ContextWindowManager
  • 獲取所有螢幕及其解析度。
  • 在指定的螢幕上啟動 Activity。
  • 在指定的螢幕上添加 View。
  • 知道應用程式實際佔用了多少螢幕空間。
  • 取得螢幕的真實大小。

希望這些內容對你有幫助,讓你在開發多螢幕應用程式時更得心應手!

參考資料:


WRITTEN BY
Aki

熱愛寫code的開發者,專注於 Android 手機 Native App 開發,對於 IOS 也有涉略。閒暇之餘也學習 JavaScript 等前端框架