как справиться с фрагментацией экранов Android?

я хочу написать макет и код только один раз, чтобы он хорошо выглядел на всех устройствах. я пробовал много способов (да, включая то, что предлагает Google, использовать DP, а также добавлять несколько файлов макета), но ни один из них не решает проблему необходимости иметь дело с новой ситуацией каждый раз, когда появляется новое устройство со случайным разрешением и плотность. использование DP - это просто трюк XML, который позволяет размерам оставаться одинаковыми на всех экранах, таких как линейка (например, 1 см остается 1 см на всех экранах), поэтому это действительно не решение.

Я также использовал веса и трюки с кодом, чтобы установить правильные размеры и положения, но это слишком много работы для такой простой задачи.

Я слышал, что Google работает над решением этой проблемы, а также над фрагментацией версий для новой версии сэндвича с мороженым, но я не слышал/не читал ничего нового по этому вопросу. не только это, но и список различных плотностей и разрешений, которые должен поддерживать Android, становится все больше и больше: http://developer.android.com/guide/practices/screens_support.html

жаль, что у многих других технологий уже есть решение этой проблемы: у Apple оно есть (автоматическое масштабирование приложений с iphone 3g до iphone 4), оно есть у adobe (flash) и даже у microsoft (используя viewbox, на silverlight, wpf и WP). даже телевизоры должны справляться с этой проблемой, и они прекрасно с этим справляются.

я не прошу волшебства, просто способ все масштабировать. если вид был размером W%,H% экрана и находился на позиции X%,Y% экрана, он должен оставаться таким на всех экранах, а также позволяет нам сохранять соотношение сторон, если это важно достаточно для нас. зачем нам заморачиваться с разрешениями и плотностью? это просто сбивает с толку, как нас, так и графическую команду.

Итак, в заключение я думаю и надеюсь, что многие думают так же, как я, и, может быть, кто-то сделал хороший SDK, который решает все это?


@chubbard: DP не работает хорошо, так как он позволяет вещам оставаться одинаковыми для всех экранов, как линейка. если что-то было на 3/4 экрана, этого не будет на другом экране (это может быть даже за пределами экрана или происходить другие странные вещи, в зависимости от того, какой макет вы выбрали). DP — это фиксированное значение, которое преобразуется в пиксели на каждом устройстве только на основе плотности. так вот, за разницу между wvga800 (hdpi-480x800) и wvga854(hdpi-480x854) DP ничего не изменит, и вы получите 54 пикселя, которые вы не знаете, что с ними делать. если вы хотите поместить туда что-то для wvga854, оно не будет показано для wvga800. что еще хуже, нет никакой разницы между этими двумя экранами, когда речь идет о макетах Android — они оба относятся к одной и той же категории normal-hdpi.

Кроме того, если вы используете DP, на одном экране изображение/кнопка выглядит нормально, но на других экранах они выглядят настолько крошечными по сравнению с остальной частью экрана, что это действительно не может быть хорошим решением. я также не понимаю, почему у нас есть несколько папок с возможностью рисования, которые обычно устанавливаются в зависимости от плотности. это только увеличивает работу графических команд и делает приложение намного большего размера, чем оно есть, и из-за этого рынок может не принять его (из-за слишком большого размера) или, что еще хуже, устройства не будут иметь возможность загрузить приложение (например, старые версии ОС на Galaxy S не могут загружать и устанавливать приложения размером более 30 МБ).

@adamp: я ничего не говорил об absoluteLayout . у него точно такое же плохое поведение, которое я хочу преодолеть, как и у остальных макетов. единственный макет, который каким-то образом позволяет масштабировать, — это linearLayout (с использованием весов), но для выполнения простой задачи требуется много тегов и надписей. о том, что я хочу, я уже написал: я хочу, чтобы все масштабировалось. в Интернете есть множество примеров, где вы можете видеть, что это работает нормально, даже на флэш-памяти. просто откройте полноэкранное содержимое flash/silverlight и измените размер окна. если программист настроил все правильно, все в нем будет масштабироваться в соответствии с новым размером по сравнению с исходным размером. Кстати, спасибо за заметку о gridlayout. я не знал об этом. однако кажется, что он тоже ничего не может масштабировать.

@andreasg: вот это уже интересно. как вы обрабатывали изображения? не могли бы вы попробовать следующую "загадку" ? предположим, у вас есть изображение человеческого лица (или андроида :)), которое должно соответствовать размеру экрана (и сохранять соотношение сторон), и у вас есть другое изображение его глаз, окрашенных в другой цвет, как бы вы поместили их на один поверх другого (вероятно, с использованием фреймворка), чтобы он выглядел одинаково (в масштабе) на всех устройствах, независимо от того, находитесь ли вы в альбомном или портретном режимах?


person android developer    schedule 31.10.2011    source источник
comment
Я не могу связать ваши рассуждения, почему dp не является решением. Можете ли вы описать конкретную ситуацию, когда использование dp не дало ожидаемых результатов?   -  person chubbsondubs    schedule 31.10.2011


Ответы (2)


Вы должны использовать совершенно разные макеты только для больших изменений в том, как вы хотите, чтобы ваше приложение вело себя, а не для незначительных различий в размере экрана в пределах одного класса устройств, таких как телефоны. Вы можете предоставить вариант -land ваших макетов, оптимизированных для ландшафтного режима, или вы можете предоставить вариант -sw600dp, чтобы представить другую информационную архитектуру для планшетов размером около 7 дюймов или больше. Вы не должны использовать его для предоставления разных макетов для WVGA. по сравнению с дисплеем телефона qHD, Это только создаст много дополнительной работы для вас.

dp — это инструмент для работы с разной плотностью, он не поможет при разбросах по размеру и соотношению сторон. Решение для работы с разным размером экрана и соотношением сторон заключается в использовании менеджеров компоновки, предоставляемых в рамках, для адаптации к текущему устройству. Вы можете легко написать свой собственный, расширив ViewGroup и переопределив onMeasure и onLayout, если вы приходите к ситуации, когда вам действительно нужно индивидуальное поведение. В API 14 добавлен элемент GridLayout, который также предлагает дополнительные параметры.

Проектирование с учетом этих отклонений требует другого подхода к проблеме. Вы не можете подойти к проблеме, думая в абсолютных координатах экрана, если только вы не хотите сделать много работы для себя. Подумайте о том, как компоненты в вашем макете сочетаются друг с другом, и какие части должны расширяться, чтобы занимать больше места, чем ваша минимальная конфигурация, когда она доступна.

Мыслить в терминах процентов — хорошее начало, и именно такие результаты вы получите, используя LinearLayout. Но если вы хотите указать, что определенное представление должно поддерживать определенное соотношение сторон, вам нужно будет подумать о том, как это должно быть ограничено, что будет заполнять лишнее пространство и будут ли эти решения создавать хороший пользовательский интерфейс для вашего приложения. . (Например, ни один пользователь не захочет использовать приложение, которое само создает почтовые ящики и показывает реальное содержимое только в поле с фиксированным соотношением сторон посередине.)

Для этого нет волшебного решения, поскольку только вы знаете, как эти вещи должны вести себя в вашем приложении. Android поможет вам, но вы должны сказать ему, что вы хотите.

Возможно, вы могли бы опубликовать вопрос о конкретном дизайне, с которым у вас возникли проблемы, и кто-то здесь, в stackoverflow, мог бы предложить некоторые предложения.

person adamp    schedule 31.10.2011

мой способ рисовать пользовательские представления с правильным масштабом для каждого размера экрана - получить фактическую плотность экрана:

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

и, например, установка размера шрифта для пользовательского вида с 16 независимыми от плотности пикселями.

paint.setTextSize(density * 16);

Вот и вся магия. Я надеюсь, что это решит вашу проблему.

person andreasg    schedule 31.10.2011