Пользовательский визуализированный виджет приложения Android - PullRequest
7 голосов
/ 22 мая 2011

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

Однако в процессе я столкнулся с несколькими трудностями.

1) Есть ли способ найти максимально доступное пространство для виджета приложения? (ИЛИ: Можно ли правильно рассчитать размеры для минимального пространства, доступного в случаях WVGA (или аналогичных широких)?

Я не знаю, как рассчитать максимально доступное пространство для виджета приложения. С обычным виджетом приложения возможно заполнить_парень, и все пространство будет использовано. Однако при отображении виджета в виде растрового изображения и во избежание растяжения необходимо рассчитать правильные размеры. В документации описано, как рассчитать минимальные размеры, но для таких случаев, как WVGA, в ландшафтном режиме будет неиспользуемое пространство, в результате чего виджет будет выглядеть короче, чем другие виджеты, которые растягиваются естественным образом.

float density = getResources().getDisplayMetrics().density;
int cx = ((int)Math.ceil(appWidgetInfo.minWidth / density) + 2) / 74;
int cy = ((int)Math.ceil(appWidgetInfo.minHeight / density) + 2) / 74;
int portraitWidth = (int)Math.round((80.0f * cx - 2.0f) * density);
int portraitHeight = (int)Math.round((100.0f * cy - 2.0f) * density);
int landscapeWidth = (int)Math.round((106.0f * cx - 2.0f) * density);
int landscapeHeight = (int)Math.round((74.0f * cy - 2.0f) * density);

Расчет cx и cy дает количество горизонтальных и вертикальных ячеек. Вычитание - 2 из вычисленного значения dpi (например, 74 * cy - 2) позволяет избежать случаев, когда результирующее число пикселей округляется в меньшую сторону. (Например, в ландшафтном режиме на Nexus One высота составляет 110, а не 111 (74 * 1,5).

2) При назначении растрового изображения для ImageView, который используется как часть RemoteViews для просмотра изображения, существует 2 метода:

2.1) Используя setImageViewUri и сохраняя растровое изображение в файл PNG. Затем изображение подается с использованием реализации openFile () в ContentProvider:

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
    // Code to set up imageFileName
    File file = new File(getContext().getCacheDir(), imageFileName);
    return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}

Это работает, и это подход, который я сейчас использую. Однако, если я установил scaleType для ImageView на «center», который согласно документации должен «центрировать изображение в представлении, но не выполнять масштабирование», изображение будет неправильно масштабировано. Установка плотности растрового изображения в DENSITY_NONE или getResources (). GetDisplayMetrics (). DensityDpi не имеет никакого значения при сохранении растрового изображения в PNG, кажется, что игнорируется, когда файл загружается ImageView. В результате изображение уменьшается из-за проблем с разрешением dpi. Это, кажется, описывает случай:

http://code.google.com/p/android/issues/detail?id=6957&can=1&q=widget%20size&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

Поскольку невозможно использовать scaleType: center, единственный способ, который я нашел для работы, состоит в том, чтобы статически установить layout_width и layout_height ImageView для заданного числа dpis, а затем отобразить растровое изображение в том же dpi. Это требует использования scaleType: fitXY. Этот подход работает, но это очень статичная установка - и он не будет работать для виджетов приложения с изменяемым размером 3.1 (я еще не проверял это, но если onUpdate () не вызывается при каждом изменении размера, это верно).

Есть ли способ загрузить изображение в ImageView без масштабирования или это невозможно из-за ошибки в платформе?

2.1) Используя непосредственное использование setImageViewBitmap. Используя этот метод с настройкой Bitmap.DENSITY_NONE на растровом изображении, изображение может отображаться без правильного масштабирования. Проблема с этим подходом состоит в том, что есть ограничение на то, как большие изображения могут быть установлены с помощью механизма IPC:

http://groups.google.com/group/android-developers/browse_thread/thread/e8d84920b999291f/d12eb1d0eaca93ac#01d5c89e5e7b4060

(не разрешено больше ссылок) http://groups.google.com/group/android-developers/browse_thread/thread/b11550601e6b1dd3#4bef4fa8908f7e6a

Я попытался немного взломать, чтобы обойти эту проблему, разделив виджет на матрицу изображений, которые можно установить в блоках 100x100 пикселей. Это позволило работать большим виджетам, но в итоге оказалось очень тяжелым и не работало на больших виджетах (4x4).

Извините за очень длинный пост. Я попытался объяснить несколько разных проблем при попытке использовать виджет приложения с растровым изображением. Если кто-то попытался сделать то же самое и нашел больше решений этих проблем, или у вас есть полезные комментарии, это будет высоко оценено.

1 Ответ

0 голосов
/ 13 июля 2011

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

...