Android onConfigurationChanged not called for Landscape and Reverselandscape

當螢幕方向改變時,我們通常會在Activity中Override function : onConfigurationChanged 的方式來接收變化。

但目前只有當 Landscape 與 Portrait 之間互轉時才會收到event.
所以landscape轉成reverse landscape並不會由onConfigurationChanged收到變化.

onConfigurationChanged

onConfigurationChanged接收orientation變化的方式如下

在AndroidManifest.xml的填入android:configChanges

AndroidManifest.xml
1
2
3
4
5
6
<application ... >
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape"
android:configChanges="orientation|screenSize|keyboardHidden"/>
</application>

在MainActivity.java中增加Override function : onConfigurationChanged 。

AndroidManifest.xml
1
2
3
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
}

以上的方式無法得知 landscape轉成reverse landscape的訊息。

我們可監聽Ratation的變化來實現此功能。

Rotation Changed Listener

Step 1: 建立callback : RotationCallback

新增kotlin interface : RotationCallback

RotationCallback.kt
1
2
3
interface RotationCallback {
fun onRotationChanged(lastRotation: Int, newRotation: Int)
}

Step 2: 建立Listerner : RotationListener

新增kotlin class : RotationListener
其中mOrientationEventListener監聽Rotation的變化,並透過mCallback傳遞給上層

RotationListener.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class RotationListener {
private var mOrientationEventListener: OrientationEventListener? = null
private var mCallback: RotationCallback? = null

private var lastRotation: Int = 0

constructor(callback: RotationCallback) {
mCallback = callback
}

fun listen(context: Context) {
mOrientationEventListener = object : OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
override fun onOrientationChanged(orientation: Int) {
val localWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
if (null != localWindowManager && null != mCallback) {
val newRotation = localWindowManager.defaultDisplay.rotation
if (newRotation != lastRotation) {
mCallback!!.onRotationChanged(lastRotation, newRotation)
lastRotation = newRotation
}
}
}
}
mOrientationEventListener!!.enable()

lastRotation = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation
}

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

Step 3: MainActivity監聽與解除接聽

MainActivity繼承RotationCallback且實現其onRotationChanged function,並在onCreate時建立監聽Rotation變化, 而在onDestroy時取消監聽

MainActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class MainActivity : AppCompatActivity(), RotationCallback {
private val TAG = "MainActivity "

private var mRotationListener : RotationListener? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

mRotationListener = RotationListener(this)
mRotationListener!!.listen(this.applicationContext)
}

override fun onDestroy() {
super.onDestroy()
Log.e(TAG, "onDestroy()")

mRotationListener!!.stop()
mRotationListener = null
}

//RotationCallback
override fun onRotationChanged(lastRotation: Int, newRotation: Int) {
Log.d(TAG, "onRotationChanged: last " + (lastRotation) +" new " + (newRotation));
}
}

這樣就可以得知landscape與reverse landscape的變化了。

Android onConfigurationChanged not called for Landscape and Reverselandscape

https://nickcarter9.github.io/2019/11/21/2019/2019_11_21-reverselandscape-event/

作者

Nick Lin

發表於

2019-11-21

更新於

2023-01-18

許可協議


評論