You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android获取视口尺寸时触发java.lang.NoSuchMethodError异常,启动屏背景适配失败求助

解决Android实体设备getMaximumWindowMetrics()方法找不到异常,实现启动屏适配

问题原因

你遇到的NoSuchMethodError是因为WindowManager.getMaximumWindowMetrics()是Android 11(API级别30)才新增的API,你的实体设备系统版本低于Android 11,所以无法找到这个方法;而模拟器大概率用的是高版本系统,所以能正常运行。

解决方案

下面分两步解决:先修复版本兼容问题,再优化适配逻辑让代码更健壮。


1. 兼容低版本的屏幕尺寸获取

我们需要根据系统版本选择不同的获取方式,在API 30及以上用新方法,低版本用传统的DisplayMetrics方式:

private fun getScreenSize(): Pair<Int, Int> {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // Android 11+ 用新API
        val windowMetrics = windowManager.maximumWindowMetrics
        val bounds = windowMetrics.bounds
        bounds.width() to bounds.height()
    } else {
        // Android 10及以下 用旧方法
        val displayMetrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(displayMetrics)
        displayMetrics.widthPixels to displayMetrics.heightPixels
    }
}

然后在onCreate里调用这个方法获取尺寸,替换原来直接调用maximumWindowMetrics的代码即可。


2. 优化启动屏适配逻辑(推荐)

你现在用硬编码尺寸范围的方式非常脆弱——不同设备的屏幕像素可能有细微差异,而且后续新增设备尺寸时要不断修改代码。更推荐用Android原生的资源限定符,让系统自动匹配最合适的启动屏图片:

  • 在res目录下创建对应屏幕尺寸的drawable子目录,比如:

    • drawable-sw1080dp-h2160dp(对应宽1080dp、高2160dp的设备)
    • drawable-sw1080dp-h2220dp
    • drawable-sw1440dp-h2880dp
    • 以此类推,对应你需要适配的所有尺寸
  • 把每个尺寸对应的启动屏图片统一命名为splashscreen.png,放入对应的目录中

  • 最后在布局文件里直接设置背景,不需要任何代码判断:

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/splashscreen">
</androidx.constraintlayout.widget.ConstraintLayout>

这样系统会自动根据当前设备的屏幕尺寸选择对应的图片,不仅代码更简洁,适配也更可靠。


完整修正后的代码(兼容版)

如果你暂时不想改用资源限定符,以下是修复了版本兼容问题的完整代码:

package com.example.appName

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import android.os.Build
import android.util.DisplayMetrics

class MainActivity : AppCompatActivity() {
    private lateinit var constraintLayout: ConstraintLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
        constraintLayout = findViewById(R.id.constraintLayout)

        // 兼容不同版本获取屏幕尺寸
        val (width, height) = getScreenSize()
        Log.i("MainActivity", "屏幕尺寸:$width x $height")

        // 根据尺寸设置背景(建议后续替换为资源限定符方式)
        when {
            width in 1075..1085 && height in 2155..2165 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1080x2160)
            }
            width in 1075..1085 && height in 2215..2225 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1080x2220)
            }
            width in 1075..1085 && height in 2275..2285 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1080x2280)
            }
            width in 1275..1285 && height in 1915..1925 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1280x1920)
            }
            width in 1435..1445 && height in 2555..2565 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1440x2560)
            }
            width in 1435..1445 && height in 2875..2885 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1440x2880)
            }
            width in 1435..1445 && height in 2955..2965 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1440x2960)
            }
            width in 1435..1445 && height in 3035..3045 -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1440x3040)
            }
            else -> {
                constraintLayout.setBackgroundResource(R.drawable.splashscreen_1280x1920)
            }
        }

        android.os.Handler().postDelayed({
            val intent = Intent(this@MainActivity, HomeActivity::class.java)
            startActivity(intent)
            finish()
        }, 3500)
    }

    private fun getScreenSize(): Pair<Int, Int> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val windowMetrics = windowManager.maximumWindowMetrics
            val bounds = windowMetrics.bounds
            bounds.width() to bounds.height()
        } else {
            val displayMetrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(displayMetrics)
            displayMetrics.widthPixels to displayMetrics.heightPixels
        }
    }
}

内容的提问来源于stack exchange,提问作者Ahmed Anwer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:17:31