onConfigurationChanged for View in WindowManager not working reliable
Asked Answered
L

1

7

I'm adding a View to the WindowManager and overwrite it's onConfigurationChanged function like following:

View Code

// onConfigurationChanged should be called after config change has finished
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // also tried executing following in the `GlobalLayoutListener` without any difference
    onConfigOrSystemUIChanged(newConfig)
}

fun onConfigOrSystemUIChanged(newConfig: Configuration?) {
    val screen = getScreenSize(this)

    // screen should hold current screen size
    // but this sometimes contains the wrong size, the one from before the config change

    L.d("[%s] Config changed (%s)", logBaseInfo, screen)
}

Service Code

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    val screen = getScreenSize(this)
    L.d("Config changed in SERVICE: Screen: %s | newConfig: %s", screen, newConfig);
}

Problem

I can see that this works about 99% of the time. I rotate my device, turn it on, off and so on and everything works fine. But every now and then I see that it fails once, meaning my view reads the wrong screen size after the device has been rotated. Any ideas why?

Additonal info - logs

I added some logs to my service's onConfigurationChanged and to my view's onConfigurationChanged. I have 5 views added to the WindowManager and see following:

[OverlayService:168 onConfigurationChanged]: Config changed in SERVICE: Screen: Point(2076, 1080) | newConfig: {0 1.0 themeSeq = 0 showBtnBg = 0 232mcc1mnc [de_AT] ldltr sw360dp w692dp h336dp 480dpi nrml long hdr land finger -keyb/v/h -nav/h appBounds=Rect(144, 0 - 2220, 1080) s.839 mkbd/h desktop/d ?dc}
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 24]] Config changed (Point(2076, 1080))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 26]] Config changed (Point(2076, 1080))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 52]] Config changed (Point(2076, 1080))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 53]] Config changed (Point(2076, 1080))
=> [BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 65]] Config changed (Point(1080, 2076))
// ... here some time that wents by ...
[OverlayService:168 onConfigurationChanged]: Config changed in SERVICE: Screen: Point(1080, 2076) | newConfig: {0 1.0 themeSeq = 0 showBtnBg = 0 232mcc1mnc [de_AT] ldltr sw360dp w360dp h668dp 480dpi nrml long hdr port finger -keyb/v/h -nav/h appBounds=Rect(0, 0 - 1080, 2076) s.840 mkbd/h desktop/d ?dc}
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 26]] Config changed (Point(1080, 2076))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 52]] Config changed (Point(1080, 2076))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 53]] Config changed (Point(1080, 2076))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 65]] Config changed (Point(1080, 2076))
[BaseMviOverlayView:115 onConfigOrSystemUIChanged]: [MviHandleView[Index: 24]] Config changed (Point(1080, 2076))

Here you see that one view (marked with => at the beginning of the log line, the 6th line) does get the wrong screen size and I don't know why...

Additonal info - functions

fun getScreenSize(context: Context) {
    val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val outSize = Point()
    wm.getDefaultDisplay().getSize(outSize)
    return outSize
}
Lacewing answered 22/10, 2018 at 9:40 Comment(0)
C
0

This may be caused because view is measured while screen rotaion is not yet completed. Try setting a timeout.

clearTimeout(t)
t = setTimeout(function(){/*do your stuff here*/},200);

here t is a global variable -- to clearTimeout if the screen is rotated before screensize is measured. Try playing around with time in milliseconds (in my code 200) to optimize for the desired behaviour.

Creese answered 24/10, 2018 at 17:3 Comment(3)
In my comments I wrote that I tried using the views GlobalLayoutListener => this should have the same effect I think, but without guessing a constant. Still my problem is not the view's size, I need the screen size. But even if I wait for the view and only afterwards determine the screen size I still have problems in some cases...Lacewing
Thank you for the feedback. I don't know much about globalLayoutListener. If you don't mind, try using setTimeout in onConfiburation changed. I had similar problem with my android app and I could read the correct screensize with this approach. I hope same shall be applicable here too.Creese
Currently I'm trying to only use the event from the service and push it down to each view manually... Still log every event and have an eye on this, even sending an event to my views handler and checking there... Will check the logs when the problem occurs the next time, it's a rare problem though so it's hard to debug. Thanks for the idea thoughLacewing

© 2022 - 2024 — McMap. All rights reserved.