Pregunta ¿Por qué no es mi escala vectorial dibujable como se esperaba?


Estoy intentando usar vectores arrastrables en mi aplicación de Android. De http://developer.android.com/training/material/drawables.html (énfasis mío):

En Android 5.0 (nivel API 21) y superior, puede definir vectores dibujables, qué escala sin perder definición.

Usando esto dibujable:

<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" />

y esta ImageView:

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

produce esta imagen borrosa cuando intenta mostrar el ícono a 400dp (en un dispositivo móvil de alta resolución circa 2015 corriendo lollipop):

blurryBellIcon

Cambiar el ancho y alto en la definición del vector dibujable a 200dp mejora significativamente la situación en el tamaño renderizado de 400dp. Sin embargo, establecer esto como un drawable para un elemento TextView (es decir, un icono a la izquierda del texto) ahora crea un ícono enorme.

Mis preguntas:

1) ¿Por qué hay una especificación de ancho / altura en el vector dibujable? Pensé que el objetivo de todo esto es que escalaran hacia arriba y hacia abajo sin pérdidas, lo que hace que el ancho y la altura carezcan de sentido en su definición.

2) ¿Es posible utilizar un solo vector dibujable que funciona como un dibujo de 24dp en un TextView, pero se adapta bien para usar imágenes mucho más grandes también? P.ej. ¿Cómo evito crear maquetas de vectores múltiples de diferentes tamaños y, en su lugar, uso uno que se adapte a mis requisitos representados?

3) ¿Cómo uso efectivamente los atributos width / height y cuál es la diferencia con viewportWidth / Height?

Detalles adicionales:

  • El dispositivo está ejecutando la API 22
  • Usando Android Studio v1.5.1 con Gradle versión 1.5.0
  • Manifiesto es compilar y objetivo nivel 23, nivel mínimo 15. También he intentado mover el nivel mínimo a 21, pero esto no hizo diferencia.
  • Descompilar el APK (con un nivel mínimo establecido en 21) muestra un solo recurso XML en la carpeta dibujable. No se producen imágenes rasterizadas.

63
2018-01-21 23:48


origen


Respuestas:


Hay nueva información sobre este problema aquí:

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

Parece usar android:scaleType="fitXY" lo hará escalar correctamente en Lollipop.

De un ingeniero de Google:

Hola, avíseme si scaleType = 'fitXY' puede ser una solución para usted, en   Para que la imagen se vea nítida.

El malvavisco Vs Lollipop se debe a un tratamiento de escala especial   añadido a malvavisco.

Además, para sus comentarios: "Comportamiento correcto: el vector dibujable   debe escalar sin pérdida de calidad. Entonces, si queremos usar el mismo activo   en 3 tamaños diferentes en nuestra aplicación, no tenemos que duplicar   vector_drawable.xml 3 veces con diferentes tamaños codificados. "

Aunque estoy totalmente de acuerdo, este debería ser el caso, en realidad, el   La plataforma Android tiene una preocupación de rendimiento tal que no hemos alcanzado   el mundo ideal todavía. Por lo tanto, en realidad se recomienda utilizar 3 diferentes   vector_drawable.xml para un mejor rendimiento si está seguro de que quiere   dibujar 3 tamaños diferentes en la pantalla al mismo tiempo.

El detalle técnico es básicamente que estamos usando un mapa de bits bajo el gancho   para almacenar en caché la representación de ruta compleja, de modo que podamos obtener el mejor   volver a dibujar el rendimiento, a la par con el redibujado de un mapa de bits dibujable.


74
2018-03-11 01:15



1) ¿Por qué hay una especificación de ancho / altura en el vector dibujable? Pensé que el objetivo de todo esto es que escalaran hacia arriba y hacia abajo sin pérdidas, lo que hace que el ancho y la altura carezcan de sentido en su definición.

Para las versiones de SDK inferiores a 21, donde el sistema de compilación necesita generar imágenes ráster y como el tamaño predeterminado en los casos en que no se especifica el ancho / alto.

2) ¿Es posible utilizar un único vector dibujable que funciona como un dibujo de 24dp en un TextView, así como una gran imagen de ancho de pantalla?

No creo que esto sea posible si también necesita apuntar a SDK de menos de 21.

3) ¿Cómo uso efectivamente los atributos width / height y cuál es la diferencia con viewportWidth / Height?

Documentación: (en realidad no es muy útil ahora que lo releí ...)

android:width

Se usa para definir el ancho intrínseco del dibujable. Esto admite todas las unidades de dimensión, normalmente especificadas con dp.

android:height

Se usa para definir la altura intrínseca del dibujable. Esto admite todas las unidades de dimensión, normalmente especificadas con dp.

android:viewportWidth

Se usa para definir el ancho del espacio de la ventana gráfica. La ventana gráfica es básicamente el lienzo virtual donde se dibujan las rutas.

android:viewportHeight

Se usa para definir la altura del espacio de la ventana gráfica. La ventana gráfica es básicamente el lienzo virtual donde se dibujan las rutas.

Más documentación:

Android 4.4 (nivel de API 20) e inferior no es compatible con vectores arrastrables. Si su nivel mínimo de API se establece en uno de estos niveles de API, Vector Asset Studio también indica a Gradle que genere imágenes de trama del vector dibujable para compatibilidad con versiones anteriores. Puede referirse a activos vectoriales como Drawable en código Java o @drawable en código XML; cuando se ejecuta su aplicación, el vector correspondiente o la imagen ráster se muestran automáticamente dependiendo del nivel de la API.


Editar: Algo raro esta pasando. Aquí están mis resultados en el emulador SDK versión 23 (el dispositivo de prueba Lollipop + está muerto en este momento ...):

Good bells on 6.x

Y en el emulador SDK versión 21:

Crappy bells on 5.x


19
2018-01-21 23:56



AppCompat 23.2 introduce vectores dibujables para todos los dispositivos con Android 2.1 y superior. Las imágenes se escalan correctamente, independientemente del ancho / alto especificado en el archivo XML del vector drawable. Lamentablemente, esta implementación no se utiliza en API nivel 21 y superior (a favor de la implementación nativa).

La buena noticia es que podemos forzar a AppCompat a usar su implementación en los niveles API 21 y 22. La mala noticia es que tenemos que usar la reflexión para hacer esto.

En primer lugar, asegúrese de estar utilizando la última versión de AppCompat y de haber habilitado la nueva implementación del vector:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

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

Luego llame useCompatVectorIfNeeded(); en su aplicación 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();
        }
    }
}

Finalmente, asegúrate de que estás usando app:srcCompat en lugar de android:src para establecer la imagen de su ImageView:

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

¡Tus dibujos vectoriales ahora deberían escalar correctamente!


7
2018-03-05 16:44



1) ¿Por qué hay una especificación de ancho / altura en el vector dibujable? Pensé que el objetivo de todo esto es que escalaran hacia arriba y hacia abajo sin pérdidas, lo que hace que el ancho y la altura carezcan de sentido en su definición.

Este es simplemente el tamaño predeterminado del vector en caso de que no lo defina en la vista de diseño. (es decir, usa contenido de ajuste para la altura y   ancho de su imagen)

2) ¿Es posible utilizar un único vector dibujable que funciona como un dibujo de 24dp en un TextView, así como una gran imagen de ancho de pantalla?

Sí, es posible y no he tenido ningún problema con el cambio de tamaño como   siempre que el dispositivo en ejecución esté usando lollipop o superior. En anteriores   API, el vector se convierte a pngs para diferentes tamaños de pantalla cuando   construyes la aplicación.

3) ¿Cómo uso efectivamente los atributos width / height y cuál es la diferencia con viewportWidth / Height?

Esto afecta cómo se usa el espacio alrededor de su vector. es decir, puedes   utilízalo para cambiar la "gravedad" del vector dentro de la ventana gráfica, haz   el vector tiene un margen predeterminado, deja ciertas partes del vector   fuera de la ventana gráfica, etc. ... Normalmente, simplemente los configura para el mismo   tamaño.


4
2018-01-22 00:11



Intento hacerlo de estas maneras, pero desafortunadamente ninguno de ellos funcionó. lo intento fitXY en ImageView, Trato de usar app:srcCompat pero ni siquiera puedo usarlo. pero encontré una forma de truco:

configurar el Drawable para background de tu ImageView.

Pero el objetivo de esto es ver las dimensiones. si tu ImageView tiene dimensiones incorrectas, drawable obtiene Stretch. debes controlarlo en versiones previas a la piruleta o usar algunas vistas PercentRelativeLayout.

Espero que sea útil.


3
2018-03-14 22:35



primero : import svg to drawble: ((https://www.learn2crack.com/2016/02/android-studio-svg.html)

1-Haga clic con el botón derecho en la carpeta dibujable seleccione Nuevo -> Vector activo

enter image description here

2- El Vector Asset Studio le brinda la opción de seleccionar la versión incorporada   Iconos de material o su propio archivo svg local. Puede anular el   tamaño predeterminado si es necesario.

enter image description here

Segundo : si desea soporte de android API 7+, debe usar la función de biblioteca de soporte de Android ((https://stackoverflow.com/a/44713221/1140304)

1- agregar

vectorDrawables.useSupportLibrary = true

a su archivo build.gradle

2-Use espacio de nombres en su diseño que tenga imageView:

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

Tercero : establece imageView con android: scaleType = "fitXY" y usa la aplicación: srcCompat

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

Cuarto : si quieres establecer svg en código java tienes que agregar la siguiente línea en oncreate methoed

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

0
2017-10-10 11:04