So zentrieren Sie einen in der Ebenenliste zeichnbaren Vektor ohne Skalierung

102

Ich versuche, a VectorDrawablein a zu verwenden, LayerListohne den Vektor zu skalieren. Beispielsweise:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
    <item android:gravity="center" android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

Die zeichnbare ic_check_white_48dpID definiert als:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

Der gewünschte Effekt besteht darin, dass das Häkchensymbol ohne Skalierung in der zu zeichnenden Ebene zentriert wird. Das Problem ist, dass die Ebenenliste oben bewirkt, dass das Häkchensymbol an die Ebenengröße angepasst wird.

Ich kann den gewünschten Effekt erzielen, wenn ich den Vektor, der für jede Dichte gezeichnet werden kann, durch PNGs ersetze und die Ebenenliste als solche ändere:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
    <item>
        <bitmap android:gravity="center" android:src="@drawable/ic_check_white_48dp"/>
    </item>
</layer-list>

Gibt es eine Möglichkeit, dies mit einem zu tun VectorDrawable?

Ashughes
quelle
11
Es scheint, dass dies einfach ein Fehler in API 21/22 sein kann. Ich habe gerade auf einem API 23-Gerät getestet und der zu zeichnende Vektor war korrekt zentriert.
Ashughes
1
Sie sollten Ihre eigene Frage beantworten und akzeptieren. Auf diese Weise ist es sichtbarer und die Frage wird nicht als unbeantwortet angezeigt.
Marcin Koziński
1
Ich habe meine Frage nicht beantwortet, da ich noch keine Antwort darauf habe, was mit API 21/22 zu tun ist. Meine vorübergehende Lösung bestand darin, PNGs anstelle von Vektoren zu verwenden. In der Hoffnung, immer noch einen Weg zu finden, wie Vektoren funktionieren.
Ashughes
1
Ich habe hier ein Problem geöffnet: code.google.com/p/android/issues/detail?id=219600
toobsco42
Dies ist bereits in API 23 behoben, daher wird Ihr Fehlerbericht vermutlich nur als behoben markiert.
Ashughes

Antworten:

29

Ich hatte das gleiche Problem beim Versuch, Vektor-Drawables auf einer überlagerten Liste zu zentrieren.

Ich habe eine Problemumgehung, die nicht genau gleich ist, aber funktioniert. Sie müssen eine Größe für das gesamte Zeichenelement festlegen und dem Vektorelement eine Auffüllung hinzufügen:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <size android:height="120dp" android:width="120dp"/>
            <solid android:color="@color/grid_item_activated"/>
        </shape>
    </item>
    <item android:top="24dp"
          android:bottom="24dp"
          android:left="24dp"
          android:right="24dp"
          android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

Die Größe der obigen Form legt die Größe des gesamten Zeichens fest, in diesem Beispiel 120 dp. Die Auffüllung des zweiten Elements, in diesem Beispiel 24 dp, zentriert das Vektorbild.

Es ist nicht dasselbe wie die Verwendung von, gravity="center"aber seine Arbeitsweise bei der Verwendung von Vektoren in API 21 und 22.

Nicolas Tyler
quelle
2
Dies klingt so, als müssten Sie die genaue Größe des Zeichens kennen (um die Formgröße festzulegen), anstatt den gesamten Bereich, auf den es eingestellt ist, mit dem darin zentrierten Häkchen ausfüllen zu lassen.
Ashughes
1
Es ist möglich, die Größe nicht zu kennen, aber Sie können die Polsterung mit dieser Methode nicht ändern. Sie können die Zeichen in Bildansichten übereinander legen. Wie ich oben sagte, gibt es keine perfekte Lösung für eine gravity="center"in API 21 und 22.
Nicolas Tyler
Es funktioniert nicht mit windowBackground. Explizite Größen bewirken in diesem Fall nichts. Und es funktioniert auch nicht, wenn ich eine Ebenenliste in eine andere Ebenenliste einfüge.
Vsevolod Ganin
19

Ich hatte mit dem gleichen Problem zu kämpfen. Die einzige Möglichkeit, dies zu beheben und zu vermeiden, dass das Drawable vergrößert werden kann, bestand darin, die Drawable-Größe festzulegen und sie mithilfe der Schwerkraft auszurichten:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
     <item
        android:gravity="center"
        android:width="48dp"
        android:height="48dp"
        android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

Ich hoffe es hilft!

Felipe Duarte
quelle
34
Dies hilft in API 21-22 nicht, da das widthAttribut auf diesen API-Ebenen nicht verfügbar ist. Unter API 23 werden diese nicht benötigt, da der Fehler behoben und das Drawable nicht mehr gedehnt wird.
WonderCsabo
3
Dies funktioniert nicht richtig für API 27, Bild wird auf Vollbild gestreckt
Konstantin Konopko
8

Überarbeitete Lösung, mit der Ihr SplashScreen auf allen APIs, einschließlich API21 bis API23, gut aussieht

Lesen Sie dies zuerst Artikel und folgen Sie der GUTEN Art, einen Begrüßungsbildschirm zu erstellen.

Wenn Ihr Logo verzerrt ist oder nicht passt und Sie nur auf APIs24 + abzielen, können Sie Ihren Vektor, der direkt in seiner XML-Datei gezeichnet werden kann, einfach wie folgt verkleinern:

<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="640"
android:viewportHeight="640"
android:width="240dp"
android:height="240dp">
<path
    android:pathData="M320.96 55.9L477.14 345L161.67 345L320.96 55.9Z"
    android:strokeColor="#292929"
    android:strokeWidth="24" />
</vector>

Im obigen Code skaliere ich eine Zeichenfläche, die ich auf eine Leinwand mit einer Größe von 640 x 640 gezeichnet habe, auf 240 x 240 neu. dann habe ich es einfach so in meinen Begrüßungsbildschirm gezeichnet und es funktioniert großartig:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"
android:paddingBottom="20dp" android:paddingRight="20dp" android:paddingLeft="20dp" android:paddingTop="20dp">

<!-- The background color, preferably the same as your normal theme -->
<item>
    <shape>
        <size android:height="120dp" android:width="120dp"/>
        <solid android:color="@android:color/white"/>
    </shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item
    android:drawable="@drawable/logo_vect"
    android:gravity="center">

</item>
</layer-list>

Mein Code zeichnet eigentlich nur das Dreieck im Bild unten, aber hier sehen Sie, was Sie damit erreichen können. Die Auflösung ist schließlich großartig im Gegensatz zu den pixeligen Kanten, die ich bei der Verwendung von Bitmap erhalten habe. Verwenden Sie also auf jeden Fall einen Vektor, der gezeichnet werden kann (es gibt eine Site namens vectr, mit der ich meine erstellt habe, ohne spezielle Software herunterladen zu müssen).

BEARBEITEN, damit es auch auf API21-22-23 funktioniert

Während die obige Lösung für Geräte funktioniert, auf denen API24 + ausgeführt wird, war ich nach der Installation meiner App auf einem Gerät mit API22 sehr enttäuscht. Ich bemerkte, dass der Begrüßungsbildschirm erneut versuchte, die gesamte Ansicht auszufüllen und wie Scheiße aussah. Nachdem ich mir einen halben Tag lang die Augenbrauen herausgerissen hatte, erzwang ich schließlich eine Lösung durch bloße Willenskraft.

Sie müssen eine zweite Datei mit dem Namen splashscreen xml (z. B. splash_screen.xml) erstellen und in zwei Ordnern mit den Namen drawable-v22 und drawable-v21 ablegen, die Sie im Ordner res / erstellen (um sie selbst zu sehen) müssen Ihre Projektansicht von Android auf Projekt ändern). Dies dient dazu, Ihr Telefon anzuweisen, zu Dateien umzuleiten, die sich in diesen Ordnern befinden, wenn auf dem entsprechenden Gerät eine API ausgeführt wird, die dem Suffix -vXX im Zeichenordner entspricht ( siehe diesen Link) . Fügen Sie den folgenden Code in die Ebenenliste der Datei splash_screen.xml ein, die Sie in diesen Ordnern erstellen:

<item>
<shape>
    <size android:height="120dp" android:width="120dp"/>
    <solid android:color="@android:color/white"/>
</shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item android:gravity="center">
    <bitmap android:gravity="center"
        android:src="logo_vect"/>

</item>

So sehen die Ordner aus

Aus irgendeinem Grund müssen Sie für diese APIs Ihr Drawable in eine Bitmap einbinden, damit es funktioniert und das Endergebnis gleich aussieht. Das Problem ist, dass Sie den Ansatz mit den zusätzlichen zeichnbaren Ordnern verwenden müssen, da die zweite Version der Datei splash_screen.xml dazu führt, dass Ihr Begrüßungsbildschirm auf Geräten mit APIs über 23 überhaupt nicht angezeigt wird. Möglicherweise müssen Sie auch platzieren Die erste Version der Datei splash_screen.xml in drawable-v24, da Android standardmäßig den nächstgelegenen Ordner drawable-vXX verwendet, den es für Ressourcen finden kann.

mein Begrüßungsbildschirm

quealegriamasalegre
quelle
4

Ich arbeite derzeit an einem Begrüßungsbildschirm mit einem Vektor, der horizontal und vertikal zentriert werden kann. Folgendes habe ich auf API-Ebene 25 erhalten:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">

<!-- background color, same as theme -->
<item android:drawable="@android:color/white"/>

<!-- app logo -->

<item
    android:drawable="@drawable/my_app_logo"
    android:gravity="center_horizontal|center_vertical"
    android:width="200dp"
    android:height="200dp"
    />
</layer-list>

Wenn Sie die Dimension des Vektorzeichens anpassen möchten, ändern Sie android:widthundandroid:height die obigen Attribute Attribute, nicht unbedingt das ursprüngliche Zeichen.

Außerdem habe ich die Erfahrung gemacht, dass der Vektor, der gezeichnet werden kann, NICHT in ein Bitmap-Tag eingefügt wird, was für mich nie funktioniert. Bitmap ist für Dateien im Format .png, .jpg und .gif, nicht für Vektorzeichnungen.

Referenz

https://developer.android.com/guide/topics/resources/drawable-resource#LayerList

https://developer.android.com/guide/topics/resources/more-resources.html#Dimension

Wenhe Qi
quelle
1
Guter Fang für Vektor-Drawables, die sich in einem <item> -Tag anstelle eines <bitmap> -Tags befinden müssen.
FrostRocket