UIWebView и дисплей сетчатки iPhone 4

У меня есть UIWebView, который отображает локальный текст и изображения. Либо я где-то ошибся, либо UIWebView не обрабатывает автоматически суффикс @2x для изображений с высоким разрешением.

Итак, мой вопрос: кто-нибудь еще успешно загрузил @2x изображения в UIWebView обычными средствами, или мне нужно сделать что-то особенное? Могу ли я как-то определить, есть ли у моего пользователя дисплей сетчатки?


person Ben Williams    schedule 16.09.2010    source источник


Ответы (6)


Согласно вашему запросу...

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

if([[UIScreen mainScreen] respondsToSelector:@selector(scale)] &&
   [[UIScreen mainScreen] scale] == 2.0)
{
    /* We have a retina display. */
}
else
{
    /* We do not. */
}

Этот код безопасен на момент написания, на всех моделях и на всех версиях прошивки. Это будет безопасно и в будущих версиях, пока Apple не откажется от метода scale, чего может никогда не произойти.

Подробнее о вашем вопросе: я не знаю, как это сделать в веб-просмотре, не имея заранее местоположения изображения сетчатки и изображения без сетчатки. Когда у меня есть эта информация, я (в прошлом) использовал ее для замены некоторого известного дозорного текста, который веб-страница ожидала от меня, например, я добавлял в HTML что-то, что говорило: {{{image_location}}}, где я мог загрузить HTML данные, преобразуйте их в строковый формат, затем выполните замену этой строки, заменив этот текст, URL-адресом изображения @2x, если мы находимся на дисплее сетчатки, с соответствующим коэффициентом масштабирования или изображением нормального размера, если нет ( используя приведенный выше код).

Надеюсь, это поможет, если никто не предложит лучшее решение.

person jer    schedule 16.09.2010
comment
Учитывая, что лучших ответов не поступало, я принимаю это как работоспособное решение. В идеале UIWebView должен обрабатывать это сам для локальных изображений, но проверка масштаба экрана устройства и соответствующая настройка HTML работают. - person Ben Williams; 19.09.2010
comment
На iPad в режиме 2x масштаб тоже 2.0. - person occulus; 27.05.2011
comment
Конечно, но это в любом случае относится к приложениям для iPhone. Приложения для iPad не работают в режиме масштабирования. Поэтому, если вы правильно справитесь с этим случаем в своем приложении для iPhone, это не проблема. :) - person jer; 27.05.2011
comment
Так что же происходит на iPhone 6, когда шкала достигает 7.0? Нет больше сетчатки? :-P Как насчет того, чтобы просто получить коэффициент масштабирования, а затем запросить у (веб- или другого) приложения соответствующие изображения. - person Jonny; 20.10.2011

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

Установите display: none, а затем сбросьте его при загрузке изображения, чтобы исправить мерцание. Также обратите внимание, что этот код, вероятно, несовместим с другими браузерами, кроме WebKit.

document.addEventListener("DOMContentLoaded", function() {
  var scale = window.devicePixelRatio;
  // might want this to be scale != 2
  if (scale == undefined || scale == 1) {
    return;
  }

  var re = /^(.*)(\..*)$/;
  var images = document.getElementsByTagName("img");
  for (var i =  0; i < images.length; i++) {
    var img = images[i];
    var groups = re.exec(img.src);
    if (groups == null) {
      continue;
    }

    img.style.setProperty("display", "none");
    img.addEventListener("load", function(event) {
      event.target.width /= scale;
      event.target.style.setProperty("display", "");
    });
    img.src = groups[1] + "@" + scale + "x" + groups[2];
  }
});

Советы - добавить это в файл с именем, например. scaledimages.js, а затем используйте

<script type="text/javascript" src="scaledimages.js"></script>

Убедитесь, что js-файл указан в «Ресурсах копирования пакета», а не в «Скомпилированных источниках» в ваших целях «Фазы сборки». Швы Xcode по умолчанию определяют файлы Javascript как нечто, что ему нравится компилировать. Также обратите внимание, что текущий скрипт может сломаться, если в будущем devicePixelRatio окажется равным 3 или больше, в качестве меры предосторожности может быть изменение (scale == undefined || scale == 1) на scale != 2, пока загружайте только @2x.

Обновление. Существует также jQuery-Retina-Display-Plugin, который делает что-то похожее, но требует, чтобы вы установили атрибут width и швы, чтобы также использовать запрос HEAD, чтобы увидеть, существует ли изображение, не уверен, как это будет работать для локальных файлов.

person Mattias Wadman    schedule 12.10.2011
comment
Я не понимаю, почему за это проголосовали. Я сам использовал это в приложении, и оно отлично работает, по крайней мере, с небольшими HTML-страницами с небольшим количеством изображений. Но я признаю, что это уродливый хак :) - person Mattias Wadman; 16.04.2012
comment
Прости, это был я. Я думал, что проголосовал за это, но случайно, должно быть, нажал кнопку «Вниз», и stackoverflow больше не позволяет мне это изменить. Пожалуйста, обновите ответ, даже если у вас есть лишний пробел :) Думаю, это позволит мне изменить статус. Я проверил это на себе, и это работает как шарм. Я также использовал его с небольшими HTML-страницами. - person Mustafa; 17.04.2012
comment
:) Я сам сделал ту же ошибку. Попробуй сейчас. - person Mattias Wadman; 17.04.2012
comment
Сделанный :). Спасибо, что поделились решением. - person Mustafa; 17.04.2012

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

HTML-файл

<link href="default.css" rel="stylesheet" media="screen" type="text/css" />
<link href="highresolution.css" media="screen and (-webkit-min-device-pixel-ratio:2)" type="text/css" rel="stylesheet" />

...

<img src="image.png"    width="..."   height="..."    class="normalRes" />    
<img src="[email protected]" width="..."   height="..."    class="highRes" />

Файл CSS: default.css

.normalRes { display:block } /* or anything else */
.highRes   { display:none  }

CSS-файл: highresolution.css

.normalRes { display:none  }
.highRes   { display:block }  /* or anything else */

Я немного протестировал его, и он работал хорошо. Сейчас нужно больше тестов. Я нашел решение здесь: http://www.mobilexweb.com/blog/iphone4-ios4-detection-safari-viewport

ОБНОВЛЕНИЕ 2012-06-24

Вот еще одно решение, не требующее файла highresolution.css.
Добавьте следующий код в default.css.

@media all and (-webkit-min-device-pixel-ratio: 2) {

   .normalRes { display:none  }
   .highRes   { display:block }

   ...
person Dominique Vial    schedule 29.12.2010
comment
Атрибуты width и height для тега img должны иметь значения сохранения для обычных изображений и изображений Retina. Другими словами, только имя файла src и значение класса изменяются с обычного изображения на изображение сетчатки. - person Dominique Vial; 24.06.2012

Просто всегда делайте:

<img src="[email protected]" width={half-width} />

для фоновых изображений, на которые ссылается CSS, используйте -webkit-background-size, чтобы уменьшить их вдвое.

Недостаток: устройства без сетчатки будут загружать изображения слишком большого размера.

person Hafthor    schedule 01.10.2010

Лучшее решение — использовать изображения с высоким разрешением как для сетчатки, так и для веб-представлений без сетчатки. Затем установите размер изображения (в пунктах), используя атрибуты ширины и высоты.

<img src="hi-res-icon.png" width="10px" height="10px" />
person mc7h    schedule 20.07.2011
comment
эээ, извините! Я в значительной степени продублировал ответы Хафтора - person mc7h; 20.07.2011

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

person zoul    schedule 16.09.2010
comment
-1 за рекомендацию кода, который проверяет устройство, а не функциональность. Рекомендую проверить, что UIScreen отвечает на scale, и если да, то вызвать scale на UIScreens mainScreen и проверить, равно ли его значение 2.0. Если эти условия верны, дисплей сетчатки. - person jer; 16.09.2010
comment
Ну в этом случае ложного срабатывания получить нельзя, чтобы я не сомневался. А вот скрин чек лучше, да. - person zoul; 16.09.2010
comment
Отменил отрицательный голос за признание выше. Просто чтобы добавить еще одну вещь, причина, по которой я проголосовал за нее, заключается в том, что эти типы проверок оборудования отлично работают в определенный момент времени, но через 5 месяцев, когда Apple выпустит новое устройство (вероятно, с дисплеем Retina), нам придется отредактировать нашу код, чтобы заставить его работать там, тогда как если мы проверим масштаб, он будет работать автоматически. - person jer; 16.09.2010
comment
Спасибо, но я все еще надеюсь, что кто-нибудь найдет способ сделать это автоматически в UIWebView. Проверка устройства — неуклюжее решение, каким бы способом оно ни выполнялось. Тем не менее, @jer, не могли бы вы опубликовать свое решение в другом комментарии, чтобы я мог принять его в качестве ответа, если это единственный хороший вариант, который у меня есть? - person Ben Williams; 16.09.2010