как обрабатывать фрагменты экранов Android?

#android #screen #scale #resolution

#Android #экран #масштаб #разрешение

Вопрос:

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

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

я слышал, что Google работает над решением этого вопроса, а также над фрагментами версий для новой версии ice cream sandwich, но я не слышал / не читал ничего нового по этому вопросу. не только это, но и диаграмма с несколькими плотностями и разрешениями, которые должен поддерживать 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-480×800) и wvga854 (hdpi-480×854) DP ничего не изменит, и вы получите 54 пикселя, которые вы не знаете, что с ними делать. если вы хотите поместить туда что-то для wvga854, это не будет показано для wvga800 . что еще хуже, между этими 2 экранами нет никакой разницы, когда речь идет о макетах Android — они оба относятся к одной и той же категории normal-hdpi.

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

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

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

Комментарии:

1. Я не могу связать ваши рассуждения, почему dp не является решением. Можете ли вы описать конкретную ситуацию, когда использование dp не дало ожидаемых результатов?

Ответ №1:

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

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

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

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

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

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

Ответ №2:

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

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

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

 paint.setTextSize(density * 16);
 

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