Установка ImageView ScaleType в «центр» не работает, как я ожидаю - PullRequest
4 голосов
/ 18 октября 2011

У меня есть следующий макет для моего ImageView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants">
    <ImageView
        android:id="@+id/imageview_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:scaleType="fitCenter" />
    (...)
</LinearLayout>

Те 48dp равны 36px, 48px и 72px в ldpi, mdpi и hdpi соответственно. Все изображения, которые будут использоваться в этом ImageView, в основном являются значками, и я нашел в Интернете, что я хочу для своего приложения (бесплатная лицензия). Но, к сожалению, это не идет с изображениями, размер которых превышает 48 пикселей, и использование других изображений исключено. Поэтому мне нужно новое решение ...

На данный момент у меня есть изображения размером 36px и 48px в папках ldpi и mdpi соответственно. Но у меня проблемы с hdpi. Что я хочу для устройств, работающих на hdpi, так это чтобы они использовали образ mdpi (больший из доступных) и использовали его как есть, без масштабирования. По сути, ImageView для hdpi составляет 72 пикселя, поэтому я хочу, чтобы изображение размером 48 пикселей находилось внутри 72 пикселей в центре без масштабирования. Для этого я просто попытался изменить scaleType в ImageView выше на center, но в любом случае изображение масштабируется.

Мой главный вопрос здесь: как правильно решить проблему, описанную выше? Как можно использовать изображения ldpi и mdpi с их соответствующей плотностью, но при этом устройства, работающие с hdpi, могут выбрать самое большое доступное изображение (это mdpi) и предотвратить любое масштабирование, просто подгоняя изображение в центре ImageView?

EDIT:
Я сам ответил на этот вопрос, но, возможно, это тот ответ, который ищут другие, приходящие сюда. Но я даю некоторое представление о том, что на самом деле происходит, и основной проблеме. Пожалуйста, посмотрите и предоставьте обходной путь / исправление, если можете. Смею вас :) 1036 *

Ответы [ 7 ]

13 голосов
/ 19 октября 2011

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

Чтобы было понятно, scaleType=centerInside работает как положено. То есть, если у вас есть изображение меньше, чем само ImageView, то это изображение не будет масштабировано до границ ImageView, оно останется в центре и будет немасштабировано.

Но чтобы вышеперечисленное работало должным образом, отрисовка должна быть помещена в папку nodpi. Я понимаю, что это не всегда приемлемо. Таким образом, когда этот объект рисования необходимо поместить в одну из папок плотности вместо папки nodpi, атрибут scaleType будет работать только в определенных ситуациях.

Когда это будет работать:

  • Вы запускаете приложение на устройстве / эмуляторе с Xdpi плотностью и в папке плотности Xdpi есть отрисовка (здесь X означает, l, m, h или даже xh).
  • Вы запускаете приложение устройства / эмулятор, например, с плотностью hdpi, но в hdpi, и система выбирает альтернативный Папка nodpi (не всегда известно, какую папку она выберет от).

Когда не будет работать:

  • Вы используете приложение / эмулятор приложения, например, с hdpi плотности, но в папке hdpi нет Система выбирает альтернативный оттягиваемый из любой другой плотности папок (не папка nodpi), масштабируемый будет масштабироваться до ImageView bounds и атрибут scaleType не подойдут что-нибудь.

В заключение, нет «правильного» ответа на мой вопрос, это действительно зависит от того, чего вы пытаетесь достичь. Ответ мой вопрос, мне просто нужно сделать 2 вещи: а) установить ImageView scaleType на centerInside и б) Дублировать все чертежи из папки mdpi в hdpi папка (как объяснено выше, scaleType=centerInside заработает).

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

Каков был бы тогда оптимальный ответ / решение?
По моему мнению, если устройство / эмулятор работает в hdpi, и в папке hdpi нет соответствующего рисунка, его следует выбрать из папки mdpi, не масштабируя его, что позволяет scaleType атрибут, чтобы сделать это вещь. Или, может быть, вынудите систему перейти в папку nodpi, если в соответствующей папке плотности не найден соответствующий чертеж, это тоже может помочь.

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

1 голос
/ 21 мая 2017

В моем случае я устанавливал изображение как android:background. когда я установил его как android:src, это сработало!

1 голос
/ 11 июля 2012

Я решил это так:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <!-- Here is where the money is -->
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:gravity="center_horizontal|center_vertical">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        ...
    </LinearLayout>
</LinearLayout>
0 голосов
/ 05 января 2016

Попробуйте с

imageview.setAdjustViewBounds(false);
0 голосов
/ 19 октября 2011

Создайте собственный ImageView:

package x;

public class MaxMDPIImageView extends ImageView {

    public MaxMDPIImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float density = getResources().getDisplayMetrics().density;
        if (density>1) {
            canvas.translate(getWidth()/2-getWidth()/density/2, getHeight()/2-getHeight()/density/2);
            canvas.scale(1/density, 1/density);
        }
        super.onDraw(canvas);
    }

}

Используйте его просто как:

<x.MaxMDPIImageView
    android:src="@drawable/icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
    />
0 голосов
/ 18 октября 2011

Попробуйте это:

<FrameLayout android:layout_width="48dp" android:layout_height="48dp">
<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"

    android:maxWidth="48px"
    android:maxHeight="48px"
    android:adjustViewBounds="true"
    android:src="..."
    />
</FrameLayout>

И обычно помещайте изображения в папки ldpi / mdpi.

Хотя я не рекомендую использовать значения пикселей.

0 голосов
/ 18 октября 2011

Попробуйте оставить его вне папки hdpi и поместить в папку drawable-nodpi.Я не уверен, какова иерархия (будет ли nodpi переопределять папки ldpi и mdpi), но это будет моей первой попыткой.

...