Cara memusatkan drawable vektor di daftar lapisan tanpa penskalaan

102

Saya mencoba menggunakan a VectorDrawabledalam LayerListtanpa skala vektor. Sebagai contoh:

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

ic_check_white_48dpId drawable didefinisikan sebagai:

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

Efek yang diinginkan adalah ikon centang dipusatkan di layer drawable, tanpa penskalaan. Masalahnya adalah, daftar lapisan di atas menyebabkan ikon centang diskalakan agar sesuai dengan ukuran lapisan.

Saya dapat menghasilkan efek yang diinginkan jika saya mengganti vector drawable dengan PNG untuk setiap kepadatan dan memodifikasi daftar-lapisan seperti:

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

Apakah ada cara agar saya dapat melakukan ini dengan menggunakan VectorDrawable?

ashughes
sumber
11
Tampaknya ini hanyalah bug di API 21/22. Saya baru saja menguji perangkat API 23 dan vector drawable sudah berada di tengah dengan benar.
ashugh
1
Anda harus menjawab pertanyaan Anda sendiri dan menerimanya. Dengan begitu, pertanyaan ini lebih terlihat dan pertanyaannya tidak muncul sebagai belum terjawab.
Marcin Koziński
1
Saya belum menjawab pertanyaan saya karena saya belum memiliki jawaban untuk apa yang harus dilakukan pada API 21/22. Solusi sementara saya adalah menggunakan PNG alih-alih vektor. Berharap untuk tetap menemukan cara untuk membuat vektor bekerja.
ashugh
1
Saya membuka masalah di sini: code.google.com/p/android/issues/detail?id=219600
toobsco42
Ini sudah diperbaiki di API 23, jadi saya rasa laporan bug Anda hanya akan ditandai sebagai diperbaiki.
ashugh

Jawaban:

29

Saya mengalami masalah yang sama saat mencoba memusatkan vector drawable pada daftar berlapis.

Saya punya solusi, tidak persis sama tetapi berhasil, Anda perlu menetapkan ukuran untuk seluruh drawable dan menambahkan padding ke item vektor:

<?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>

Ukuran bentuk di atas menyetel ukuran seluruh drawable, dalam contoh ini 120dp, padding pada item kedua, 24dp dalam contoh ini, memusatkan gambar vektor.

Ini tidak sama dengan menggunakan gravity="center"tetapi cara kerjanya menggunakan vektor di API 21 dan 22.

Nicolas Tyler
sumber
2
Sepertinya Anda perlu mengetahui ukuran pasti drawable (untuk menyetel ukuran bentuk), daripada membiarkannya mengisi seluruh ruang yang disetel dengan kotak centang drawable yang berada di tengahnya.
ashugh
1
Anda mungkin tidak mengetahui ukurannya tetapi Anda tidak dapat mengubah padding dengan metode ini, Anda bisa melapisi drawable di atas satu sama lain dalam tampilan gambar. Seperti yang saya nyatakan di atas, tidak ada solusi sempurna untuk gravity="center"di API 21 dan 22.
Nicolas Tyler
Tidak bekerja saat digunakan dengan windowBackground. Ukuran eksplisit tidak melakukan apa pun dalam kasus ini. Dan itu juga tidak berhasil jika saya meletakkan daftar lapisan di dalam daftar lapisan lain.
Vsevolod Ganin
19

Telah berjuang dengan masalah yang sama. Satu-satunya cara yang saya temukan untuk memperbaiki ini dan menghindari drawable untuk ditingkatkan adalah dengan menyetel ukuran drawable dan menggunakan gravitasi untuk menyelaraskannya:

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

Semoga membantu!

Felipe Duarte
sumber
34
Ini tidak membantu pada API 21-22, karena widthatribut tidak tersedia pada level API tersebut. Pada API 23, ini tidak diperlukan, karena bug telah diperbaiki dan drawable tidak diregangkan lagi.
WonderCsabo
3
Ini tidak berfungsi dengan benar untuk API 27, gambar diregangkan ke layar penuh
Konstantin Konopko
8

Solusi yang diedit yang akan membuat SplashScreen Anda tampak hebat di semua API termasuk API21 hingga API23

Pertama-tama baca artikel ini dan ikuti cara BAGUS membuat layar splash.

Jika logo Anda terdistorsi atau tidak sesuai dan Anda hanya menargetkan APIs24 + Anda cukup menurunkan drawable vektor Anda langsung di file xml seperti:

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

pada kode di atas saya mengubah ukuran drawable yang saya gambar di kanvas 640x640 menjadi 240x240. lalu saya taruh saja di layar splash drawable saya seperti itu dan itu berfungsi dengan baik:

<?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>

kode saya sebenarnya hanya menggambar segitiga pada gambar di bagian bawah tetapi di sini Anda melihat apa yang dapat Anda capai dengan ini. Resolusi akhirnya bagus dibandingkan dengan tepi pixelated yang saya dapatkan saat menggunakan bitmap. jadi gunakan drawable vektor dengan segala cara (ada situs bernama vectr yang saya gunakan untuk membuat milik saya tanpa perlu mengunduh perangkat lunak khusus).

EDIT untuk membuatnya berfungsi juga di API21-22-23

Sementara solusi di atas berfungsi untuk perangkat yang menjalankan API24 +, saya benar-benar kecewa setelah menginstal aplikasi saya, perangkat yang menjalankan API22. Saya perhatikan bahwa splashscreen lagi-lagi mencoba memenuhi seluruh tampilan dan terlihat seperti kotoran. Setelah merobek alis saya selama setengah hari, saya akhirnya memaksakan solusi dengan kemauan keras.

Anda perlu membuat file kedua dengan nama persis seperti splashscreen xml (katakanlah splash_screen.xml) dan letakkan ke dalam 2 folder bernama drawable-v22 dan drawable-v21 yang akan Anda buat di folder res / (untuk melihatnya, Anda harus mengubah tampilan proyek Anda dari Android ke Proyek). Ini berfungsi untuk memberi tahu ponsel Anda untuk mengalihkan ke file yang ditempatkan di folder tersebut setiap kali perangkat yang relevan menjalankan API yang sesuai dengan sufiks -vXX di folder drawable, lihat tautan ini . tempatkan kode berikut di Daftar lapisan file splash_screen.xml yang Anda buat di folder ini:

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

seperti inilah tampilan folder

Untuk beberapa alasan untuk API ini, Anda harus membungkus drawable Anda dalam bitmap untuk membuatnya berfungsi dan hasil akhirnya terlihat sama. Masalahnya adalah Anda harus menggunakan pendekatan dengan folder drawable tambahan karena versi kedua dari file splash_screen.xml akan menyebabkan layar splash Anda tidak ditampilkan sama sekali pada perangkat yang menjalankan API yang lebih tinggi dari 23. Anda mungkin juga harus menempatkannya versi pertama splash_screen.xml ke dalam drawable-v24 sebagai default android ke folder drawable-vXX terdekat yang dapat ditemukannya untuk sumber daya.

splashscreen saya

quealegriamasalegre
sumber
4

Saat ini saya sedang mengerjakan splash screen dengan vector drawable yang berada di tengah baik secara horizontal maupun vertikal. Inilah yang saya dapatkan di API level 25:

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

Jika Anda ingin menyesuaikan dimensi drawable vektor, memodifikasi android:widthdan android:heightatribut di atas, tidak perlu memodifikasi drawable asli.

Selain itu, pengalaman saya JANGAN meletakkan vector drawable dalam tag bitmap, yang tidak pernah berhasil untuk saya. Bitmap adalah untuk file format .png, .jpg dan .gif, bukan untuk drawable vektor.

Referensi

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

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

Wenhe Qi
sumber
1
Tangkapan bagus tentang vector drawable yang harus berada di dalam tag <item> alih-alih tag <bitmap>.
FrostRocket