小工具知识网

当前位置: 首页 > 行业知识 > 【Android】获取屏幕方向的几种方式和最优解

行业知识

【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 方式三, 但是如果你希望获取最全面的传感器角度信息, 那么方式四也加上, 那么为什么不全用方式四呢, 因为你平放手机, 手机传感器就无法通过加速度计算除角度, 从而获取不到了.

上一篇:人麻了,刚面试入职就遇到MySQL亿级大表调优...

下一篇:至强服务器大小怎么选的?