Is there an easy way to detect DPI? I need to layout icons slightly different depending on DPI. I can’t just looked at the model since on Android there are so many, and I can’t just look at the resolution since 1280x800 on a Galaxy Tab 10.1 is much lower DPI than 960x640 on an iPhone4.
[import]uid: 44812 topic_id: 14032 reply_id: 314032[/import]
There’s no way to do that at present, however could you consider checking for device for iPhone4 and checking screen res for others? [import]uid: 52491 topic_id: 14032 reply_id: 51721[/import]
Since I want to run on Android this won’t be possible, since there are dozens of HDPI Android handsets with DPI similar to the iPhone4. There’d be no way for me to differentiate between 1024x600 of the Nook Color/GTab (MDPI) vs. the 960x640 of an iPhone 4 (HDPI) or the 1024x768 (LDPI) of an iPad.
In my particular case the screen layout depends heavily on DPI since it corresponds to legibility (I need to provide somewhat fixed size UI elements in physical space, not in pixels).
My alternative is to provide two different apps, one that is for phones and one that is for tablets. That’s not the end of the world, it’s just somewhat inconvenient since the ONLY difference would be the layout.
[import]uid: 44812 topic_id: 14032 reply_id: 51769[/import]
We also ran into the same issue. We are developing an application for both mobiles and tablets and have a set of buttons in a top toolbar.
The problem is these buttons scale linearly with screen size and we cannot deduct the display physical size from the resolution. We found android API does support this in the form of xdpi,ydpi in DisplayMetrics.
multiplying these values by the screen width/height in pixels should give the size of the display.
We would then scale the button (or the whole toolbar) size in pixels according to the physical size of the display.
Exposing these in Corona (and setting constants for the few apple devices because I’m not sure apple has the equivalent functions Android has) would make it possible for us to release the same binary for both tablets and phones/pods without worrying about the buttons being ridiculously large on tablets or too small on mobile phones. [import]uid: 80469 topic_id: 14032 reply_id: 63390[/import]
I am encountering the exact same problem. With scaling=none, my app calculates the sizes of everything on the fly to present the (hopefully) most useable text/buttons/etc given what the device offers. Unfortunately this means that the text and buttons on the iPhone4 are tiny compared to the iPhone3 even though the screens are the same physical size. Testing for specific devices is only a workaround. Being able to get the DPI of the device would be very useful. If we can vote, this gets +1+ from me. [import]uid: 117477 topic_id: 14032 reply_id: 80762[/import]
This is really a bigger issue than I think the folks at Ansca appreciate. They seem to live in a “480x320” world, having put a ton of work into making it easy to have the same layout code work on lots of different devices. This was a great approach a couple of years ago when every device was approximately 4".
Unfortunately for Corona SDK users, we are now faced with a significant problem. Not only do we have 10" tablets (9.7" iPad and 10.1" for the larger Galaxy), but we also have intermediate tablet sizes (7" for Kindle Fire, Nook Color, Galaxy). So if your goal is not to have a scaled up iPhone app (which is marginally better than having no table app at all), but to have a real tablet app where things are scaled to the physical size of the device, you have to build at least THREE distributions.
Of course this could be solved in a few ways. It would be a lot easier for Ansca to do it, but I don’t know that they’re all that concerned about it. Exposing the dpi of the device would be a great approach. Android provides an easy way to get to PPI. In iOS it’s just a tiny bit more complicated, but the data is there:
(You have to use “scale” and do just a little bit of math)
So it would not be hard at all for Corona to provide a PPI/DPI for both platforms. Then it would at least be possible to have one app across all device sizes and have it look good on all of them.
This tends to be my biggest beef with Corona (as much as I like it). They make 90% of the hard stuff super easy, and the other 10% completely impossible (or 10x harder than it should be).
What I do right now, and I haven’t shipped this code, nor am I excited about having to test/maintain it across every possible device, is something like the following:
local function getDPI( )
-- http://en.wikipedia.org/wiki/List\_of\_displays\_by\_pixel\_density
local pixel\_width = (-display.screenOriginX \* 2 + display.contentWidth) / display.contentScaleX
local pixel\_height = (-display.screenOriginY \* 2 + display.contentHeight) / display.contentScaleY
print("screen pixel dimensions: " .. pixel\_width .. " x " .. pixel\_height)
local devices = {
{ model = "iPhone", diagonal\_size\_inches = 3.5, },
{ model = "iPad", diagonal\_size\_inches = 9.7, },
{ model = "iPod touch", diagonal\_size\_inches = 3.5, },
{ model = "Nexus One", diagonal\_size\_inches = 3.7, },
{ model = "Droid", diagonal\_size\_inches = 3.7, },
{ model = "Galaxy Tab", diagonal\_size\_inches = 7.0, },
{ model = "Kindle Fire", diagonal\_size\_inches = 7.0, },
{ model = "Nook Color", diagonal\_size\_inches = 7.0, },
}
local model = system.getInfo("model")
local size\_inches = 4.0 -- Our default "phone" size, close enough (\*IF\* it's a phone)
for \_, device in pairs(devices) do
if device.model == model then
print("Found device size for: " .. model)
size\_inches = device.diagonal\_size\_inches
end
end
local dpi = math.sqrt((pixel\_width^2) + (pixel\_height^2)) / size\_inches
print("model: " .. model .. ", dpi: " .. dpi)
return dpi
end
[import]uid: 111481 topic_id: 14032 reply_id: 84258[/import]
I updated this code to make it a little easier to use. It now returns a table with screen h/w in pixels, the pixels per inch (ppi) value for the device, the screen h/w in Corona units, the Corona units per inch (cpi), model name, and the physical screen size in inches.
local function getDeviceMetrics( )
-- See: http://en.wikipedia.org/wiki/List\_of\_displays\_by\_pixel\_density
local corona\_width = -display.screenOriginX \* 2 + display.contentWidth
local corona\_height = -display.screenOriginY \* 2 + display.contentHeight
--print("Corona unit width: " .. corona\_width .. ", height: " .. corona\_height)
-- I was rounding these, on the theory that they would always round to the correct integer pixel
-- size, but I noticed that in practice it rounded to an incorrect size sometimes, so I think it's
-- better to use the computed fractional values instead of possibly introducing more error.
--
local pixel\_width = corona\_width / display.contentScaleX
local pixel\_height = corona\_height / display.contentScaleY
--print("Pixel width: " .. pixel\_width .. ", height: " .. pixel\_height)
local model = system.getInfo("model")
local default\_device =
{ model = model, inchesDiagonal = 4.0, } -- Approximation (assumes average sized phone)
local devices = {
{ model = "iPhone", inchesDiagonal = 3.5, },
{ model = "iPad", inchesDiagonal = 9.7, },
{ model = "iPod touch", inchesDiagonal = 3.5, },
{ model = "Nexus One", inchesDiagonal = 3.7, },
{ model = "Nexus S", inchesDiagonal = 4.0, }, -- Unverified model value
{ model = "Droid", inchesDiagonal = 3.7, },
{ model = "Droid X", inchesDiagonal = 4.3, }, -- Unverified model value
{ model = "Galaxy Tab", inchesDiagonal = 7.0, },
{ model = "Galaxy Tab X", inchesDiagonal = 10.1, }, -- Unverified model value
{ model = "Kindle Fire", inchesDiagonal = 7.0, },
{ model = "Nook Color", inchesDiagonal = 7.0, },
}
local device = default\_device
for \_, deviceEntry in pairs(devices) do
if deviceEntry.model == model then
device = deviceEntry
end
end
-- Pixel width, height, and pixels per inch
device.pixelWidth = pixel\_width
device.pixelHeight = pixel\_height
device.ppi = math.sqrt((pixel\_width^2) + (pixel\_height^2)) / device.inchesDiagonal
-- Corona unit width, height, and "Corona units per inch"
device.coronaWidth = corona\_width
device.coronaHeight = corona\_height
device.cpi = math.sqrt(corona\_width^2 + corona\_height^2)/device.inchesDiagonal
print("Device: " .. device.model .. ", size: " .. device.inchesDiagonal .. " inches, ppi: " .. device.ppi .. ", cpi: " .. device.cpi)
return device
end
The way I use this is that for some objects that need to be a certain size (like a drag platform that needs to be .75 inches on all platforms) I just multiply my desired size in inches times the cpi value to get the number of Corona units needed to get the correct physical size.
[code]
– Make a circle that is big enough to grab with a touch. It should
– be 3/4" on all devices…
local device = getDeviceMetrics()
local dragRadius = display.newCircle(0, 0, 0.75 * device.cpi)
[/code] [import]uid: 111481 topic_id: 14032 reply_id: 85051[/import]
I posted the code above to the Code Exchange in case anyone wants to use it (note: I do not really advocate this as a good solution, but it’s the best I could do with the functionality provided by Corona):
http://developer.anscamobile.com/code/device-metrics-scaling-based-screen-size [import]uid: 111481 topic_id: 14032 reply_id: 85736[/import]