Подтвердить что ты не робот

Почему мое векторное масштабируемое масштабирование не ожидается?

Я пытаюсь использовать векторные чертежи в своем приложении для Android. Из http://developer.android.com/training/material/drawables.html (выделение мое):

В Android 5.0 (API Level 21) и выше вы можете определить векторные чертежи, , которые масштабируются без потери определения.

Используя эту возможность:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="@color/colorPrimary" android:pathData="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />

и этот ImageView:

<ImageView
    android:layout_width="400dp"
    android:layout_height="400dp"
    android:src="@drawable/icon_bell"/>

создает это размытое изображение при попытке отобразить значок на 400dp (на довольно большом мобильном устройстве с низким разрешением около 2015 года, использующем леденец):

blurryIcon

Изменение ширины и высоты в определении вектора, пригодного для 200dp, значительно улучшает ситуацию при размере 400dp. Однако установка этого параметра как элемента для текста (например, слева от текста) теперь создает огромный значок.

Мои вопросы:

1) Почему спецификация ширины/высоты в векторе доступна? Я думал, что все дело в том, что они масштабируются вверх и вниз без потерь, делая ширину и высоту бессмысленными в своем определении?

2) Можно ли использовать один векторный чертеж, который работает как 24dp, вытягиваемый в TextView, но хорошо масштабируется, чтобы использовать также большие изображения? Например. как мне избежать создания нескольких векторных чертежей разного размера и вместо этого использовать тот, который масштабируется до моих визуализированных требований?

3) Как эффективно использовать атрибуты width/height и в чем разница с viewportWidth/Height?

Дополнительная информация:

  • Устройство работает с API 22
  • Использование Android Studio v1.5.1 с Gradle версией 1.5.0
  • Манифест - это компиляция и целевой уровень 23, минимальный уровень 15. Я также пробовал перемещать минимальный уровень до 21, но это не имело значения.
  • Декомпиляция APK (с минимальным уровнем, установленным в 21) показывает один XML-ресурс в папке с возможностью переноса. Растеризованные изображения не создаются.
4b9b3361

Ответ 1

Здесь есть новая информация об этой проблеме:

https://code.google.com/p/android/issues/detail?id=202019

Похоже, android:scaleType="fitXY" сделает правильное масштабирование на Lollipop.

От инженера Google:

Привет, дайте мне знать, если scaleType = 'fitXY' может быть обходным путем для вас, в чтобы изображение выглядело острым.

Зефир Vs Lollipop обусловлен специальной скейлинговой обработкой добавлен в зефир.

Кроме того, для ваших комментариев: "Правильное поведение: векторный вектор должен масштабироваться без потери качества. Поэтому, если мы хотим использовать один и тот же актив в 3 разных размерах в нашем приложении, нам не нужно дублировать vector_drawable.xml 3 раза с разными жестко заданными размерами."

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

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

Ответ 2

1) Почему спецификация ширины/высоты в векторе доступна? Я думал, что все дело в том, что они масштабируются вверх и вниз без потерь, делая ширину и высоту бессмысленными в своем определении?

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

2) Можно ли использовать один векторный чертеж, который работает как 24dp, вытягиваемый на TextView, а также изображение с широким экраном шириной?

Я не считаю, что это возможно, если вам также нужно настроить таргетинг на SDK менее 21.

3) Как эффективно использовать атрибуты width/height и в чем разница с viewportWidth/Height?

Документация: (на самом деле не очень полезно сейчас, когда я перечитаю его...)

android:width

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

android:height

Используется для определения внутренней высоты. Это поддерживает все единицы измерения, обычно заданные с помощью dp.

android:viewportWidth

Используется для определения ширины пространства просмотра. Viewport - это в основном виртуальный холст, на который нарисованы пути.

android:viewportHeight

Используется для определения высоты пространства просмотра. Viewport - это в основном виртуальный холст, на который нарисованы пути.

Дополнительная документация:

Android 4.4 (уровень API 20) и ниже не поддерживает векторные чертежи. Если ваш минимальный уровень API установлен на одном из этих уровней API, Vector Asset Studio также направляет Gradle для генерации растровых изображений вектора, пригодного для обратной совместимости. Вы можете ссылаться на векторные активы как Drawable в Java-коде или @drawable в XML-коде; при запуске приложения соответствующее векторное или растровое изображение автоматически отображается в зависимости от уровня API.


Изменить: Что-то странное происходит. Здесь мои результаты в эмуляторе SDK версии 23 (тестовое устройство Lollipop + уже мертво...):

Хорошие колокола на 6.x

И в эмуляторе SDK версии 21:

Crappy bells on 5.x

Ответ 3

AppCompat 23.2 представляет векторные чертежи для всех устройств под управлением Android 2.1 и выше. Изображения масштабируются правильно, независимо от ширины/высоты, указанной в векторном XML файле. К сожалению, эта реализация не используется в API уровня 21 и выше (в пользу собственной реализации).

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

Прежде всего, убедитесь, что вы используете последнюю версию AppCompat и что вы включили новую реализацию вектора:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
    compile 'com.android.support:appcompat-v7:23.2.0'
}

Затем вызовите useCompatVectorIfNeeded(); в своем приложении onCreate():

private void useCompatVectorIfNeeded() {
    int sdkInt = Build.VERSION.SDK_INT;
    if (sdkInt == 21 || sdkInt == 22) { //vector drawables scale correctly in API level 23
        try {
            AppCompatDrawableManager drawableManager = AppCompatDrawableManager.get();
            Class<?> inflateDelegateClass = Class.forName("android.support.v7.widget.AppCompatDrawableManager$InflateDelegate");
            Class<?> vdcInflateDelegateClass = Class.forName("android.support.v7.widget.AppCompatDrawableManager$VdcInflateDelegate");

            Constructor<?> constructor = vdcInflateDelegateClass.getDeclaredConstructor();
            constructor.setAccessible(true);
            Object vdcInflateDelegate = constructor.newInstance();

            Class<?> args[] = {String.class, inflateDelegateClass};
            Method addDelegate = AppCompatDrawableManager.class.getDeclaredMethod("addDelegate", args);
            addDelegate.setAccessible(true);
            addDelegate.invoke(drawableManager, "vector", vdcInflateDelegate);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

Наконец, убедитесь, что вы используете app:srcCompat вместо android:src для установки образа ImageView:

<ImageView
    android:layout_width="400dp"
    android:layout_height="400dp"
    app:srcCompat="@drawable/icon_bell"/>

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

Ответ 4

1) Почему спецификация ширины/высоты в векторе доступна? Я думал, что все дело в том, что они масштабируются вверх и вниз без потерь, делая ширину и высоту бессмысленными в своем определении?

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

2) Можно ли использовать один векторный чертеж, который работает как 24dp, вытягиваемый на TextView, а также изображение с широким экраном шириной?

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

3) Как эффективно использовать атрибуты width/height и в чем разница с viewportWidth/Height?

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

Ответ 5

Я стараюсь этого, но, к сожалению, никто из них не работал. Я пытаюсь fitXY в ImageView, я пытаюсь использовать app:srcCompat, но даже не могу его использовать. но я нашел трюк:

установите для параметра значение background вашего ImageView.

Но точка этого пути - размеры просмотров. если ваш ImageView имеет неправильные размеры, drawable получает Stretch. вы должны контролировать его в версиях до леллипопа или использовать некоторые виды PercentRelativeLayout.

Надеюсь, что это будет полезно.

Ответ 6

Первый: import svg to drawble: ((https://www.learn2crack.com/2016/02/android-studio-svg.html))

1-Щелкните правой кнопкой мыши по выделенной папке выберите "Создать" → "Векторный объект"

введите описание изображения здесь

2. Vector Asset Studio предоставляет вам возможность выбрать встроенный Значки материалов или собственный локальный файл svg. Вы можете переопределить размер по умолчанию при необходимости.

введите описание изображения здесь

Второй. Если вам нужна поддержка от android API 7+, вы должны использовать поддержку библиотеки поддержки Android ((fooobar.com/questions/110861/...) )

1- добавить

vectorDrawables.useSupportLibrary = true

в файл build.gradle.

2-Использовать пространство имен в вашем макете с изображением:

xmlns:app="http://schemas.android.com/apk/res-auto"

Третий: установите изображение с помощью android: scaleType = "fitXY" и используйте приложение: srcCompat

 <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        app:srcCompat="@drawable/ic_menu" />

Четвертый: если вы хотите установить svg в java-коде, вам нужно добавить строку ниже oncreate methoed

 @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

Ответ 7

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

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="300"
    android:viewportWidth="300">

И я изменил его на 150dp (размер ImageView в макете с этим векторным ресурсом), например:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="150dp"
    android:height="150dp"
    android:viewportHeight="300"
    android:viewportWidth="300">

Это работает для меня.

Ответ 8

Для меня причиной, по которой векторы были преобразованы в png, был атрибут android:fillType="evenodd" в моем векторном объекте. Когда я удалил все вхождения этого атрибута в моем рисоваемом (то есть в векторе, используя тип заливки по умолчанию nonzero), в следующий раз приложение было построено, все было хорошо.