how to handle android screens fragmentations?

2019-08-05 18:36发布

问题:

i wish to write the layout and code just once so that it would look good on all devices . i've tried many ways (yes, including what google suggests, to use DP and also add multiple layout files) , but none really solves the problem of having to deal with a new situation each time there is a new device with a random resolution and density. the DP usage is just an XML trick that lets the dimensions stay the same on all screens like a ruler (for example , 1cm stays 1cm on all screens) ,so it's really not a solution.

i've also used weights and and code tricks to set the correct sizes and positions, but it's just too much work for such a simple task.

i've heard that google was working on a solution for this matter as well as versions fragmentations for the new ice cream sandwich version , but i didn't hear/read anything new about this matter. not only that, but the chart of multiple densities&resolutions that android needs to support is getting bigger and bigger : http://developer.android.com/guide/practices/screens_support.html

it's a shame that so many other technologies already had a solution for this problem : apple has it (automatically scaled the apps from iphone 3g to iphone 4) , adobe has it (flash) and even microsoft has it (using viewbox , on silverlight, wpf and WP) . even TVs have to handle this problem , and they do it just fine.

i'm not asking for magic, just for a way to scale everything . if a view was the size of W%,H% of the screen , and was on position of X%,Y% of the screen , it should stay this way on all screens , and also allow us to keep aspect ratio if it's important enough for us. why do we need to bother with resolutions and densities? it's just confusing , both us and the graphics teams .

so in conclusion, i think and hope that many think like me, and maybe someone made a nice sdk that solves it all ?


@chubbard : DP doesn't work well since it will let things stay exactly the same for all screens just as a ruler . if something was in the 3/4 of the screen it won't be so on another screen (it might even be outside of the screen or have other weird things going on , depending on which layout you've chosen). DP is a fixed value which only being translated to pixels on each device based on the density alone. so , for the difference between wvga800 (hdpi-480x800) and wvga854(hdpi-480x854) , the DP won't change anything, and you get 54 pixels that you don't know what to do with them. if you want to put there something for the wvga854 , it won't be shown for the wvga800 . even worse , there is no difference between those 2 screens when talking about android layouts - they both sit under the same category of normal-hdpi.

also, if you use DP , on one screen the image/button looks ok , but on other screens they look so tiny compared to the rest of the screen , so it really can't be a good solution. i also don't get why we have multiple drawable folders usually set to be depending on density . it only makes more work for the graphics teams and make the app to be in a much larger size than it is , and because of this , the market might not accept it (because of too large size) or even worse - devices won't be able to download the app (old OS versions on galaxy S , for example , cannot download&install apps that are more than 30MB size).

@adamp : i didn't say anything about absoluteLayout . it has the exact bad behavior that i wish to overcome as the rest of the layouts . the only layout that somehow allows scaling is linearLayout (using weights) , but it takes a lot of tags and writings to do a simple task . about what i want, i already wrote it: i want that everything would scale . there are tons of examples on the internet where you can see that it works fine , even on flash . just open a full window flash/silverlight content and resize the window . if the programmer has set things right, everything in it will scale according to the new size compared to the original size. btw, thank you for the note of gridlayout . i didn't know of it . however, it seems that it, too can't scale anything .

@andreasg : now this is interesting . how did you handle images? can you please try out the next "riddle" ? suppose you have an image of a human face (or of android :) ) that should fit the screen (and keep its aspect ratio) , and you have another image of its eyes colored in a different color , how would you put them one on top of the other (probably using framelayout) so that it would look the same (scaled) on all of the devices , no matter if you are on landscape or portrait modes ?

回答1:

You should only be using completely different layouts for large changes in how you want your app to behave, not for minor variances in screen size within a single device class such as phones. You might provide a -land variant of your layouts that are optimized for landscape mode, or you might provide a -sw600dp variant to present a different information architecture for tablets of around 7" or larger. You should not use this to provide different layouts for a WVGA vs. a qHD phone display. Doing so will only create a lot of extra work for yourself.

dp is a tool for working with different densities, it will not help for variances in size and aspect ratio. The solution for working with variance in screen size and aspect ratio is to use the layout managers provided in the framework to adapt to the current device. You can quite easily write your own by extending ViewGroup and overriding the onMeasure and onLayout methods if you come to a situation where you truly need custom behavior. API 14 added GridLayout, which offers further options as well.

Designing for these variances does require a different approach to the problem. You cannot approach the problem by thinking in absolute screen coordinates unless you want to make a lot of work for yourself. Think about how the components in your layout fit together relative to one another, and which pieces should expand to consume more space than your minimum configuration when it is available.

Thinking in terms of percentages is a good start and that's exactly the kind of results you'll get by using LinearLayout's weight feature. But if you want to specify that a certain view should maintain a specific aspect ratio you will need to think about how that should be bounded, what will fill any excess space, and whether or not those decisions will produce a good user experience for your app. (For example, no user wants to use an app that letterboxes itself and only shows real content in a fixed aspect ratio box in the middle.)

There is no magic solution to this since only you know how these things should behave in your app. Android will help you but you have to tell it what you want.

Perhaps you could post a question about a specific design that you are having trouble with and someone here on stackoverflow could offer some suggestions.



回答2:

my way to draw custom views with the right scale for each screen size is to get the actual screen density:

float density = context.getResources().getDisplayMetrics().density;

and for example setting a font size for a custom view with 16 density independent pixels

paint.setTextSize(density * 16);

Thats the whole magic. I hope this will solve your problem.