溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android怎么監(jiān)聽(tīng)屏幕旋轉(zhuǎn)

發(fā)布時(shí)間:2021-03-17 14:06:57 來(lái)源:億速云 閱讀:188 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹Android怎么監(jiān)聽(tīng)屏幕旋轉(zhuǎn),文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

背景

關(guān)于個(gè)人,前段時(shí)間由于業(yè)務(wù)太忙,所以一直沒(méi)有來(lái)得及思考并且沉淀點(diǎn)東西;同時(shí)組內(nèi)一個(gè)個(gè)都在業(yè)務(wù)上能有自己的思考和總結(jié),在這樣的氛圍下,不由自主的驅(qū)使周末開(kāi)始寫(xiě)點(diǎn)東西,希望自己除了日常忙于業(yè)務(wù),可以沉淀點(diǎn)東西,加上自己的成長(zhǎng)..

關(guān)于切入點(diǎn),最近在做應(yīng)?內(nèi)懸浮球功能時(shí),需要監(jiān)聽(tīng)屏幕旋轉(zhuǎn)事件來(lái)對(duì)懸浮球的位置進(jìn)?調(diào)整,發(fā)現(xiàn)有些情況下并不能收到系統(tǒng)回調(diào),思考了?翻,做了?個(gè)屏幕旋轉(zhuǎn)的模擬監(jiān)聽(tīng),基本上能達(dá)到?的。

問(wèn)題

懸浮球在停?拖拽后,需要貼邊到?機(jī)屏幕的左右兩側(cè)。

在豎屏狀態(tài)下,x坐標(biāo)為0即為左邊緣,x坐 標(biāo)為屏幕寬度即為右邊緣。

但是在橫屏狀態(tài)下,情況就?較復(fù)雜了?,F(xiàn)在?部分Android?機(jī)都是劉 海屏的設(shè)計(jì),在全屏狀態(tài)下,懸浮球貼邊時(shí)不能收到劉海下?去,不然就點(diǎn)不到了。

所以此時(shí)需要算 出劉海的寬度,以此寬度作為懸浮球左邊的起始位置,這樣懸浮球貼邊的時(shí)候就不會(huì)躲到劉海下? 去。 如下圖所示

Android怎么監(jiān)聽(tīng)屏幕旋轉(zhuǎn)

但是在屏幕旋轉(zhuǎn)之后,劉海到了右邊,左邊就不應(yīng)該以劉海的寬度作為懸浮球的起點(diǎn)了。 這樣的話(huà)就需要監(jiān)聽(tīng)屏幕的旋轉(zhuǎn)了,配合屏幕?向的?度,就能正確判斷。監(jiān)聽(tīng)屏幕的旋轉(zhuǎn)只需要重 寫(xiě)Activity的onConfiguratuonChanged?命周期。

override fun onConfigurationChanged(newConfig: Configuration) {
 super.onConfigurationChanged(newConfig)
 Log.i(TAG, "on configuration changed")
}

在AndroidManifest中配置

android:configChanges="orientation|screenSize"

此時(shí)發(fā)現(xiàn)了?個(gè)問(wèn)題,當(dāng)把Activity的screenOrientation設(shè)置成sensorLandscape時(shí),即使屏幕旋轉(zhuǎn) 也收不到這個(gè)回調(diào)(這個(gè)和之前的理解有點(diǎn)不?樣)。于是將screenOrientation設(shè)置成sensor,屏 幕旋轉(zhuǎn)就能正?;卣{(diào)到這?,多試?次發(fā)現(xiàn),只有在橫屏和豎屏之間切換時(shí)才能收到回調(diào),如果直接 將橫屏倒過(guò)來(lái),就是橫屏狀態(tài)不變,?向調(diào)轉(zhuǎn),此時(shí)也不會(huì)收到回調(diào)。

解決思路

既然onConfigurationChanged收不到回調(diào),還有另外?個(gè)辦法,就是監(jiān)聽(tīng)屏幕?向度數(shù),代碼如下

mOrientationEventListener = object : OrientationEventListener(this) {
 override fun onOrientationChanged(orientation: Int) {
 Log.i(TAG, "on orientation changed angle is $orientation")
 if (orientation > 340 || orientation < 20) {
 //0
 } else if (orientation in 71..109) {
 //90
 } else if (orientation in 161..199) {
 //180
 } else if (orientation in 251..289) {
 //270
 }
 }
}

通過(guò)度數(shù)來(lái)判斷劉海是在左邊還是在右邊,即270度時(shí)在左邊,90度時(shí)在右邊。這種?式看起來(lái)可以 解決問(wèn)題,但是多旋轉(zhuǎn)?次就發(fā)現(xiàn)?有其他問(wèn)題。按照正常思維,屏幕的顯示?向應(yīng)該和這個(gè)度數(shù)? 致才對(duì),即屏幕的顯示應(yīng)該是?上?下的。但是下圖就不是這樣。

Android怎么監(jiān)聽(tīng)屏幕旋轉(zhuǎn)

此時(shí)度數(shù)為90,屏幕卻倒?著顯示的,并沒(méi)有旋轉(zhuǎn)成正?狀態(tài),但是按照上?的代碼,會(huì)將90度判定 為正常90度正?顯示的狀態(tài),此時(shí)去修改懸浮球的位置就是錯(cuò)誤的。

那如果在收到onOrientationChanged這個(gè)回調(diào)時(shí)能判斷?下屏幕顯示的?向呢,就是在度數(shù)達(dá)到90 度范圍時(shí),同時(shí)判斷屏幕的顯示?向,即兩個(gè)條件同時(shí)滿(mǎn)?才判定成屏幕旋轉(zhuǎn)了。

?下?的代碼判定屏幕顯示?向

val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as
WindowManager
val rotation = windowManager.defaultDisplay?.rotation
//rotation為常量0、1、2、3,分別表示屏幕的四個(gè)?向

通過(guò)這樣的判斷基本上能將屏幕旋轉(zhuǎn)事件監(jiān)聽(tīng)準(zhǔn)確了,onOrientationChanged這個(gè)回調(diào)很靈敏,? 機(jī)屏幕稍微動(dòng)?下就會(huì)回調(diào)。那我希望模擬正常的屏幕旋轉(zhuǎn)事件來(lái)修改懸浮球的位置,總不能很頻繁 的刷新吧。這?做?下控制就好,全部代碼如下:

object ScreenOrientationHelper {
 val ORIENTATION_TYPE_0 = 0
 val ORIENTATION_TYPE_90 = 90
 val ORIENTATION_TYPE_180 = 180
 val ORIENTATION_TYPE_270 = 270
 private var mOrientationEventListener: OrientationEventListener? = null
 private var mScreenOrientationChangeListener:
   ScreenOrientationChangeListener? = null
 private var currentType = ORIENTATION_TYPE_0

 fun init(context: Context, listener: ScreenOrientationChangeListener) {
  mScreenOrientationChangeListener = listener
  mOrientationEventListener = object :
    OrientationEventListener(context) {
   override fun onOrientationChanged(orientation: Int) {
    if (mScreenOrientationChangeListener == null) {
     return
    }
    if (orientation > 340 || orientation < 20) {
     //0
     if (currentType == 0) {
      return
     }
     if (getScreenRotation(context) == Surface.ROTATION_0) {
      mScreenOrientationChangeListener!!.onChange(ORIENTATION_TYPE_0)
      currentType = ORIENTATION_TYPE_0
     }
    } else if (orientation in 71..109) {
     //90
     if (currentType == 90) {
      return
     }
     val angle = getScreenRotation(context)
     if (angle == Surface.ROTATION_270) {
      mScreenOrientationChangeListener!!.onChange(ORIENTATION_TYPE_90)
      currentType = ORIENTATION_TYPE_90
     }
    } else if (orientation in 161..199) {
     //180
     if (currentType == 180) {
      return
     }
     val angle = getScreenRotation(context)
     if (angle == Surface.ROTATION_180) {
      mScreenOrientationChangeListener!!.onChange(ORIENTATION_TYPE_180)
      currentType = ORIENTATION_TYPE_180
     }
    } else if (orientation in 251..289) {
     //270
     if (currentType == 270) {
      return
     }
     val angle = getScreenRotation(context)
     if (angle == Surface.ROTATION_90) {
      mScreenOrientationChangeListener!!.onChange(ORIENTATION_TYPE_270)
      currentType = ORIENTATION_TYPE_270
     }
    }
   }
  }
  register()
 }

 private fun getScreenRotation(context: Context): Int {
  val windowManager =
    context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
  return windowManager.defaultDisplay?.rotation ?: 0
 }

 fun register() {
  if (mOrientationEventListener != null) {
   mOrientationEventListener!!.enable()
  }
 }

 fun unRegister() {
  if (mOrientationEventListener != null) {
   mOrientationEventListener!!.disable()
  }
 }

 interface ScreenOrientationChangeListener {
  /**
   *
   * @param orientation
   */
  fun onChange(orientation: Int)
 }
}

使?的話(huà),直接這樣:

ScreenOrientationHelper.init(this, object :
ScreenOrientationHelper.ScreenOrientationChangeListener {
 override fun onChange(orientation: Int) {
  when(orientation) {
   ScreenOrientationHelper.ORIENTATION_TYPE_0 -> {}
   ScreenOrientationHelper.ORIENTATION_TYPE_90 -> {}
   ScreenOrientationHelper.ORIENTATION_TYPE_180 -> {}
   ScreenOrientationHelper.ORIENTATION_TYPE_270 -> {}
  }
 }
})

通過(guò)上?的代碼發(fā)現(xiàn),在onOrientationChanged回調(diào)90度范圍內(nèi)時(shí),判定屏幕顯示?向是和 Surface.ROTATION_270?較的,?270范圍內(nèi)時(shí)是和Surface.ROTATION_90?較的??吹贸鰜?lái)?度 是順時(shí)針遞增的,?屏幕?向是逆時(shí)針計(jì)算度數(shù)的。

其他問(wèn)題

在測(cè)試過(guò)程中,上?的?案還存在另外?個(gè)問(wèn)題,雖然onOrientationChanged這個(gè)回調(diào)很靈敏,但 是也有度數(shù)不變?屏幕?向旋轉(zhuǎn)的情況發(fā)?,即保持屏幕?向不變,?是增加屏幕的坡度(將?機(jī)? 邊貼在桌?,慢慢?起來(lái)),在坡度達(dá)到?定時(shí),屏幕會(huì)發(fā)?旋轉(zhuǎn),此時(shí)onOrientationChanged是 不會(huì)回調(diào)的,因?yàn)闆](méi)有變化。這樣就收不到屏幕旋轉(zhuǎn)的回調(diào)了,但是在實(shí)際??機(jī)的場(chǎng)景中,這種情 況是?較少的,可以親身試試看。

以上是“Android怎么監(jiān)聽(tīng)屏幕旋轉(zhuǎn)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI