行业知识
【Android】获取屏幕方向的几种方式和最优解
2026-11-03 08:44:48
来源:互联网转载
Android获取屏幕方向的几种方式和最优解
- 1.前言
- 2.正文
- 方式一: 通过系统配置的方式(有缺陷)
- 方式二: 通过显示的旋转角的方式(准确)
- 方式三: 通过宽高的方式(联合方式二判断)
- 方式四: 通过传感器的方式(有局限)
- 总结
1.前言
2.正文
有时我们需要获取屏幕的方向去加载布局, 但是方向不是一成不变的, 如果没有固定screenOritention, 那么就需要我们要知道当前的方向是什么, 特别是我们对DecorView做操作的时候
下面, 列举三个方式去获取屏幕的方向
方式一: 通过系统配置的方式(有缺陷)
//是否为竖屏(系统配置) @JvmStatic fun isOrientationPortrait_ofSysConfig(): Boolean = Resources.getSystem().configuration.orientation == Configuration.Orientation.PORTRAIT
方式二: 通过显示的旋转角的方式(准确)
//是否为竖屏(更为准确) @JvmStatic fun isOrientationPortrait_ofDefDisplay(context: Context): Boolean = getDefOrientation(context) == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT @JvmStatic fun getDefOrientation(context: Context): Int = when (getDefRotation(context)) { Surface.ROTATION_90, Surface.ROTATION_270 -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } //获取旋转 @JvmStatic fun getDefRotation(context: Context): Int = (getSystemService(context, CContext.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation方式三: 通过宽高的方式(联合方式二判断)
为什么会通过这种呢, 因为在某些平板设备中, 会带有桌面模式, 例如三星的dex模式, 还有小米的桌面模式, 这时候用户是可以调节窗口的大小的, 但是通过方式二, 还是判断为竖屏, 但是窗口已经被拉伸到类似横屏的样式了
//是否为竖屏(通过宽高的方式) @JvmStatic fun isOrientationPortrait_ofSysMetrics(): Boolean = getSysHeightPixels() >= getSysWidthPixels() @JvmStatic fun getSysHeightPixels(): Int = Resources.getSystem().displayMetrics.heightPixels @JvmStatic fun getSysWidthPixels(): Int = Resources.getSystem().displayMetrics.widthPixels
方式四: 通过传感器的方式(有局限)
这种方式比较适合相机开发, 不仅可以判断横竖屏, 还可以知道当前已经旋转到哪个角度了, 结合Lifecycle, 我们写一个角度变化监听的代理类, 并且可以自动disable
@OptInApiInit_ByLazy@OptInApiCall_BindLifecycleclass ScreenOrientationOfSensorProxy(private val _activity: A) : BaseWakeBefDestroyLifecycleObserver() where A : Activity, A : LifecycleOwner { companion object { private val SENSOR_ANGLE = 10 } interface IScreenOrientationChangedListener { fun onOrientationChanged(degree: Int){} fun onDegreeChanged(degree: Int){} } private var _orientationEventListener: OrientationEventListener? = null private var _screenOrientationChangedListener: IScreenOrientationChangedListener? = null init { _activity.runOnMainThread(::startObserveScreen) } fun setScreenOrientationChangedListener(listener: IScreenOrientationChangedListener) { _screenOrientationChangedListener = listener } override fun onDestroy(owner: LifecycleOwner) { _screenOrientationChangedListener = null disableOrientationListener() super.onDestroy(owner) } private fun startObserveScreen() { disableOrientationListener() Log.d(TAG, "startObserveScreen: ") _orientationEventListener = object : OrientationEventListener(_activity, CSensorManager.SENSOR_DELAY_NORMAL) { override fun onOrientationChanged(orientation: Int) {// Log.v(TAG, "startObserveScreen: onOrientationChanged " + orientation); if (orientation == ORIENTATION_UNKNOWN) return //手机平放时,检测不到有效的角度 _screenOrientationChangedListener?.onDegreeChanged(orientation) if (orientation > 360 - SENSOR_ANGLE || orientation 90 - SENSOR_ANGLE && orientation 180 - SENSOR_ANGLE && orientation 270 - SENSOR_ANGLE && orientation任何去使用
class ElemKAndroidViewActivity : AppCompatActivity() { @OptIn(OptInApiInit_ByLazy::class, OptInApiCall_BindLifecycle::class) private val _screenOrientationOfSensorProxy: ScreenOrientationOfSensorProxy by lazy { ScreenOrientationOfSensorProxy(this) } @OptIn(OptInApiInit_ByLazy::class, OptInApiCall_BindLifecycle::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) _screenOrientationOfSensorProxy.apply { bindLifecycle(this@ElemKAndroidViewActivity) setScreenOrientationChangedListener(object : ScreenOrientationOfSensorProxy.IScreenOrientationChangedListener { override fun onDegreeChanged(degree: Int) { //角度改变(更加灵活) } override fun onOrientationChanged(degree: Int) { //角度改变(0,90,180,270) } }) } }}相关代码, 可以查看这个开源项目
https://github.com/mozhimen/SwiftKit/blob/master/basick/src/main/java/com/mozhimen/basick/elemk/android/view/ScreenOrientationOfSensorProxy.kt
总结
如果你希望获取最全面的横竖屏信息, 你可以 方式二 or 方式三, 但是如果你希望获取最全面的传感器角度信息, 那么方式四也加上, 那么为什么不全用方式四呢, 因为你平放手机, 手机传感器就无法通过加速度计算除角度, 从而获取不到了.