Android. Вывод изображений, различные способы

Android. Вывод изображений, различные способы

Эта статья будет полезна начинающим разработчикам, здесь я предложу несколько вариантов вывода изображений на Android. Будут описаны следующие способы:

Обычный метод – стандартный способ, используя ImageView. Рассмотрены варианты загрузки картинки из ресурса, а также из файла на SD карте устройства.

Продвинутый вариант — вывод изображения, используя WebView. Добавляется поддержка масштабирования и прокрутки картинки при помощи жестов.

“Джедайский” способ – улучшенный предыдущий вариант. Добавлен полноэкранный просмотр с автоматическим масштабированием изображения при показе и поддержкой смены ориентации устройства. Исходники тестового проекта на GitHub github.com/Voldemar123/andriod-image-habrahabr-example

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

Итак, задача — предположим, в нашем приложении необходимо вывести изображение на экран. Картинка может размерами превышать разрешение экрана и иметь различное соотношение сторон. Хранится она либо в ресурсах приложения, либо на External Storage — SD карте.

Также допустим, мы уже записали на карту памяти несколько изображений (в тестовом проекте – загружаем из сети). Храним их в каталоге данных нашего приложения, в кеше.

public static final String APP_PREFS_NAME = Constants.class.getPackage().getName(); public static final String APP_CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + APP_PREFS_NAME + "/cache/";

Layout, где выводится картинка

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >

<ImageView android:id="@+id/imageView1" android:layout_width="fill_parent" android:layout_height="fill_parent" />

Масштабирование по умолчанию, по меньшей стoроне экрана. В Activity, где загружаем содержимое картинки

private ImageView mImageView; mImageView = (ImageView) findViewById(R.id.imageView1);

Из ресурсов приложения (файл из res/drawable/img3.jpg)

Задавая Bitmap изображения

FileInputStream fis = new FileInputStream(Constants.APP_CACHE_PATH + this.image); BufferedInputStream bis = new BufferedInputStream(fis);

Bitmap img = BitmapFactory.decodeStream(bis);

Или передать URI на изображение (может хранится на карте или быть загружено из сети)

mImageView.setImageURI( imageUtil.getImageURI() ); Uri.fromFile( new File( Constants.APP_CACHE_PATH + this.image ) );

Этот способ стандартный, описан во множестве примеров и поэтому нам не особо интересен. Переходим к следующему варианту.

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >

<WebView android:id="@+id/webView1" android:layout_width="fill_parent" android:layout_height="fill_parent" />

В Activity, где загружаем содержимое

protected WebView webView; webView = (WebView) findViewById(R.id.webView1);

установка черного цвета фона для комфортной работы (по умолчанию – белый)

включаем поддержку масштабирования

больше места для нашей картинки

webView.setPadding(0, 0, 0, 0);

полосы прокрутки – внутри изображения, увеличение места для просмотра

загружаем изображение как ссылку на файл хранящийся на карте памяти

webView.loadUrl(imageUtil.getImageFileLink() ); "file:///" + Constants.APP_CACHE_PATH + this.image;

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

В AndroidManifest.xml для нашей Activity добавляем

В код Activity добавлен метод, который вызыватся при каждом повороте нашего устройства. @Override public void onConfigurationChanged(Configuration newConfig)

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

Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

int width = display.getWidth(); int height = display.getHeight();

Размеры изображения, выбранного для показа

Bitmap img = imageUtil.getImageBitmap();

int picWidth = img.getWidth(); int picHeight = img.getHeight();

Меняем масштаб изображения если его высота больше высоты экрана. Прокрутка теперь будет только по горизонтали.

if (picHeight > height) val = new Double(height) / new Double(picHeight);

Подбрасываем в WebView специально сформированный HTML файл, содержащий изображение.

webView.loadDataWithBaseURL("/", imageUtil.getImageHtml(picWidth, picHeight), "text/html", "UTF-8", null);

StringBuffer html = new StringBuffer();

Такой способ я применил из-того, что после загрузки изображения в WebView через метод loadUrl, как в прошлом варианте, setInitialScale после поворота устройства не изменяет масштаб картинки. Другими словами, показали картинку, повернули телефон, масштаб остался старый. Очень похоже на то, что изображение как-то кешируется.

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

📎📎📎📎📎📎📎📎📎📎