androidSystemUiVisibility = "ImmersiveSticky" works strange with adaptive scaling

So I’m testing immersiveSticky visibility mode on xperia Z2

I’m drawing circle and on screenshot below you can see how it stretches when bottom bar is hidden.

The issue is that in both cases display.contentHeight returns same value for me, but display.pixelHeight is changed.

(link to image - https://imgur.com/pdtv8NZ )

my config:

application = { content = { scale = "adaptive", fps = 30, }, }

main.lua code:

local circle local mode = "immersiveSticky" local function drawCircle() local c = display.newCircle(display.contentWidth \* 0.5, display.contentHeight \* 0.5, display.contentWidth \* 0.4) c:addEventListener("tap", function() if (mode == "immersiveSticky") then mode = "default" else mode = "immersiveSticky" end print("mode changed") end) return c end local function printSizes() print("===================== printSizes ============================") print("androidSystemUiVisibility = ", native.getProperty("androidSystemUiVisibility")) print("content", display.contentWidth, display.contentHeight) print("viewable content", display.viewableContentWidth, display.viewableContentHeight) print("actual content", display.actualContentWidth, display.actualContentHeight) print("pixel", display.pixelWidth, display.pixelHeight) print("===================== printSizes ends =======================") end printSizes() display.setStatusBar(display.HiddenStatusBar) display.setDefault("magTextureFilter", "nearest") display.setDefault("minTextureFilter", "nearest") printSizes() local function onSystemEvent(event) local eventType = event.type if (eventType == "applicationStart") then elseif (eventType == "applicationResume") then print("resume") native.setProperty("androidSystemUiVisibility", mode) end end local function onResize(event) print("resize2") printSizes() display.remove(circle) circle = drawCircle() end -- Add the "resize" event listener Runtime:addEventListener("resize", onResize) Runtime:addEventListener("system", onSystemEvent) print("set ui visibility mode", mode) native.setProperty("androidSystemUiVisibility", mode) --end circle = drawCircle()  

How can I utilize all screen and avoid stretch? I believe display.contentHeight different value after resize event

contentWidth/Height won’t change, but actualContentWidth/Height will (ie should)

Yeah, I should check it

But look at this circle on screenshot: I draw it using 

display.newCircle(display.contentWidth \* 0.5, display.contentHeight \* 0.5, display.contentWidth \* 0.4)

How it becomes ellipse on screen?

Is there a reason you’re using Adaptive for this? Adaptive is most useful for business style apps. I’m also unsure how immersivesticky should work with Adaptive scaling mode.

Rob

I’m using adaptive for my game for a few reasons:

  1. Using all screen area (no black regions like in letterbox with fixed scale)
  2. Content width and height match width & height in dp for android - I use pixel art and believe that only adaptive is suitable to make pixel-perfect graphics

Should I use other scaling mode for that?

Using “letterbox”, while it will create pillars if you use display.contentWidth/display.contentHeight, won’t if you use display.actualContentHeight/display.actualContentWidth in conjunction with display.screenOriginX, display.screenOriginY and understanding the basics of how the Corona content area works and how you want your game to work. 

The width/height you set in config.lua is your virtual content area and it’s a fixed shape box that will be centered on the screen (by default)  If your box is the recommended 1:1.5 aspect ratio (320x480) then the 320 will be the width of your device (on a phone) and you will have areas outside of your defined content area at the top and bottom of your screen. If you’re on a tablet (a device typically wider than the 1:1.5 aspect ratio, you will end up with space on the left and right of your content area.

In many cases you want to constrain your game play to your defined content area so that your game plays the same regardless of device. As an example if you think about Angry Birds, the distance from the sling shot to the pig buildings has to be the same from device to device or the game plays differently. In a card game like Solitaire, spreading the card stacks out to fill the screen makes more sense as it doesn’t affect game play.  

To get rid of the letterbox pillars, you just have to fill the screen with your background. If your content area is 320x480, typically you would make your background 360x570 (though the Samsung Galaxy S8 and iPhone X changes that due to their extreme aspect ratios).  Then you position things like scores, lives, controls around the edges using display.screenOriginX/Y and display.actualContentWidth/Height.  Now depending on the device, some of the background will get cut off, so it’s important to not build art elements into the background image, but have them be separate images that can be edge positioned.

One problem with Adaptive that falls out of this is that you may get a screen size of 320x570 on a phone, but on a tablet, you will get a screen size of 768x1024. Adaptive tries to assure that something like a switch will be the same size on every device instead of trying to make the smaller phone screen zoom to fill the larger tablet screen. This alone can cause a drastic change in how your game plays.

I can’t speak much to using Adaptive to achieve pixel perfection. Your Android DPI is going to vary quite a bit from device to device, so I’m not sure how you’re going to get your artwork to match the various DPI’s you’re going to see on different devices.

Rob

I don’t see why is it adaptive problem? In my game I don’t use hardcoded width & height for elements. Instead of it I calculate pixel size I need for phone/tablet and use it.

Two screenshots as an example:

  1. Simulator - Samsung Galaxy S3, 720x1280. With adaptive it gives me 360x640 content. My code pick pixel size 2 (in corona units) and small button width is 36

  2. Simulator - iPad Air 1536x2048. Adaptive content - 768x1024. Pixel size variable - 4. Button width -  72

So I don’t know what can go wrong, except of ImmersiveSticky mode

So I removed scaling at all from my test project and result was the same as on first screenshot.

Values from log:
 

androidSystemUiVisibility =  immersiveSticky

display.content(width/height) 1080 1776

display.viewableContent(width/height) 1080 1776

display.actualContent(width/height) 1080 1920

display.pixel(width/height) 1080 1920

And images are stretched

Only one configuration gives me what I want:

application = { content = { width = display.pixelWidth, height = display.pixelHeight, scale = "letterbox", fps = 60 } }

This actually shows same values in log, but content is re-positioned on device instead of stretching.

contentWidth/Height won’t change, but actualContentWidth/Height will (ie should)

Yeah, I should check it

But look at this circle on screenshot: I draw it using 

display.newCircle(display.contentWidth \* 0.5, display.contentHeight \* 0.5, display.contentWidth \* 0.4)

How it becomes ellipse on screen?

Is there a reason you’re using Adaptive for this? Adaptive is most useful for business style apps. I’m also unsure how immersivesticky should work with Adaptive scaling mode.

Rob

I’m using adaptive for my game for a few reasons:

  1. Using all screen area (no black regions like in letterbox with fixed scale)
  2. Content width and height match width & height in dp for android - I use pixel art and believe that only adaptive is suitable to make pixel-perfect graphics

Should I use other scaling mode for that?

Using “letterbox”, while it will create pillars if you use display.contentWidth/display.contentHeight, won’t if you use display.actualContentHeight/display.actualContentWidth in conjunction with display.screenOriginX, display.screenOriginY and understanding the basics of how the Corona content area works and how you want your game to work. 

The width/height you set in config.lua is your virtual content area and it’s a fixed shape box that will be centered on the screen (by default)  If your box is the recommended 1:1.5 aspect ratio (320x480) then the 320 will be the width of your device (on a phone) and you will have areas outside of your defined content area at the top and bottom of your screen. If you’re on a tablet (a device typically wider than the 1:1.5 aspect ratio, you will end up with space on the left and right of your content area.

In many cases you want to constrain your game play to your defined content area so that your game plays the same regardless of device. As an example if you think about Angry Birds, the distance from the sling shot to the pig buildings has to be the same from device to device or the game plays differently. In a card game like Solitaire, spreading the card stacks out to fill the screen makes more sense as it doesn’t affect game play.  

To get rid of the letterbox pillars, you just have to fill the screen with your background. If your content area is 320x480, typically you would make your background 360x570 (though the Samsung Galaxy S8 and iPhone X changes that due to their extreme aspect ratios).  Then you position things like scores, lives, controls around the edges using display.screenOriginX/Y and display.actualContentWidth/Height.  Now depending on the device, some of the background will get cut off, so it’s important to not build art elements into the background image, but have them be separate images that can be edge positioned.

One problem with Adaptive that falls out of this is that you may get a screen size of 320x570 on a phone, but on a tablet, you will get a screen size of 768x1024. Adaptive tries to assure that something like a switch will be the same size on every device instead of trying to make the smaller phone screen zoom to fill the larger tablet screen. This alone can cause a drastic change in how your game plays.

I can’t speak much to using Adaptive to achieve pixel perfection. Your Android DPI is going to vary quite a bit from device to device, so I’m not sure how you’re going to get your artwork to match the various DPI’s you’re going to see on different devices.

Rob

I don’t see why is it adaptive problem? In my game I don’t use hardcoded width & height for elements. Instead of it I calculate pixel size I need for phone/tablet and use it.

Two screenshots as an example:

  1. Simulator - Samsung Galaxy S3, 720x1280. With adaptive it gives me 360x640 content. My code pick pixel size 2 (in corona units) and small button width is 36

  2. Simulator - iPad Air 1536x2048. Adaptive content - 768x1024. Pixel size variable - 4. Button width -  72

So I don’t know what can go wrong, except of ImmersiveSticky mode

So I removed scaling at all from my test project and result was the same as on first screenshot.

Values from log:
 

androidSystemUiVisibility =  immersiveSticky

display.content(width/height) 1080 1776

display.viewableContent(width/height) 1080 1776

display.actualContent(width/height) 1080 1920

display.pixel(width/height) 1080 1920

And images are stretched

Only one configuration gives me what I want:

application = { content = { width = display.pixelWidth, height = display.pixelHeight, scale = "letterbox", fps = 60 } }

This actually shows same values in log, but content is re-positioned on device instead of stretching.