Używam rysunków wektorowych w systemie Android przed Lollipopem i są to niektóre z moich bibliotek i wersji narzędzi:
- Android Studio: 2.0.0
- Wtyczka Android Gradle: 2.0.0
- Narzędzia do budowania: 23.0.2
- Biblioteka obsługi Androida: 23.3.0
Dodałem tę właściwość na poziomie mojej aplikacji Build.Gradle
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Warto również wspomnieć, że używam dodatkowego elementu do rysowania, takiego jak LayerDrawable (lista_warstw), jak podano na oficjalnym blogu Androida ( link tutaj ), aby ustawić rysunki dla rysunków wektorowych pozaapp:srcCompat
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/search"/>
</level-list>
Znajdziesz bezpośrednie odniesienia do rysunków wektorowych poza aplikacją: srcCompat zawiedzie przed Lollipopem. Jednak AppCompat obsługuje ładowanie wektorów rysunkowych, gdy są przywoływane w innym kontenerze do rysowania, takim jak StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable i RotateDrawable. Korzystając z tego pośrednictwa , można używać wektorów drawables w przypadkach takich jak atrybut android: drawableLeft w TextView, który normalnie nie byłby w stanie obsługiwać wektorów drawables.
Kiedy używam, app:srcCompat
wszystko działa dobrze, ale kiedy używam:
android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom
na ImageView
, ImageButton
, TextView
lub EditText
przed Lollipop zgłasza expection:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
źródło
Odpowiedzi:
NAJNOWSZA AKTUALIZACJA - czerwiec / 2019
Biblioteka wsparcia zmieniła się nieco od czasu oryginalnej odpowiedzi. Teraz nawet wtyczka Android dla Gradle jest w stanie automatycznie generować PNG w czasie kompilacji. Tak więc poniżej są dwa nowe podejścia, które powinny działać w dzisiejszych czasach. Więcej informacji znajdziesz tutaj:
Generacja PNG
Gradle może automatycznie tworzyć obrazy PNG z Twoich zasobów podczas kompilacji. Jednak w tym podejściu nie wszystkie elementy XML są obsługiwane . To rozwiązanie jest wygodne, ponieważ nie musisz niczego zmieniać w kodzie ani w pliku build.gradle. Upewnij się tylko, że używasz wtyczki Android w wersji 1.5.0 lub nowszej i Android Studio 2.2 lub nowszej .
Używam tego rozwiązania w mojej aplikacji i działa dobrze. Nie jest wymagana dodatkowa flaga build.gradle . Żadne hacki nie są potrzebne. Jeśli przejdziesz do / build / generated / res / pngs / ... możesz zobaczyć wszystkie wygenerowane pliki PNG.
Tak więc, jeśli masz jakąś prostą ikonę (ponieważ nie wszystkie elementy xml są obsługiwane), to rozwiązanie może działać dla Ciebie. Po prostu zaktualizuj swoje Android Studio i wtyczkę Android dla Gradle.
Biblioteka wsparcia
Zapewne jest to rozwiązanie, które Ci się spodoba. Jeśli tu jesteś, oznacza to, że Twoje Android Studio nie generuje plików PNG automatycznie. Twoja aplikacja ulega awarii.
A może nie chcesz, aby Android Studio w ogóle generował pliki PNG.
W odróżnieniu od „automatycznego generowania PNG”, które obsługuje podzbiór elementów XML, to rozwiązanie obsługuje wszystkie znaczniki XML. Więc masz pełne wsparcie dla swojego wektora do rysowania.
Najpierw musisz zaktualizować plik build.gradle, aby go obsługiwał:
android { defaultConfig { // This flag will also prevents Android Studio from generating PNGs automatically vectorDrawables.useSupportLibrary = true } } dependencies { // Use this for Support Library implementation 'com.android.support:appcompat-v7:23.2.0' // OR HIGHER // Use this for AndroidX implementation 'androidx.appcompat:appcompat:1.1.0' // OR HIGHER }
A następnie użyj
app:srcCompat
zamiastandroid:src
podczas ładowaniaVectorDrawables
. Nie zapomnij o tym.Dla
TextView
jeśli używaszandroidx
wersji biblioteki wsparcia, można użyćapp:drawableLeftCompat
(lub w prawo, góra, dół) zamiastapp:drawableLeft
W przypadku
CheckBox
/RadioButton
, użyjapp:buttonCompat
zamiastandroid:button
.Jeśli nie używasz
androidx
wersji Support Library, a Twoja wersjaminSdkVersion
jest17
lub nowsza lub używasz przycisku, możesz spróbować ustawić programowo za pomocąDrawable icon = AppCompatResources.getDrawable(context, <drawable_id>); textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);
AKTUALIZACJA - lipiec / 2016
Ponownie włączyli VectorDrawable w
bibliotece obsługi systemu Android 23.4.0
Być może ,
build.gradle
ustawienie jest teraz przestarzała i po prostu trzeba ją włączyć w odpowiednich działań (jednak trzeba przetestować).Teraz, aby to włączyć, musisz:
public class MainActivity extends AppCompatActivity { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } ... }
Oryginalna odpowiedź - kwiecień 2016 r
Myślę, że dzieje się tak, ponieważ Support Vector został wyłączony w najnowszej wersji biblioteki: 23.3.0
Według tego POST :
Jeśli odwiedzisz numer ISSUE 205236 , wydaje się, że w przyszłości się włączą , ale problem z pamięcią nie zostanie wkrótce rozwiązany:
Miałem podobny problem. Tak więc w moim przypadku ponownie przywróciłem wszystkie ikony, które używają wektorów, które można narysować z zasobów, do obrazów PNG (ponieważ problem z pamięcią będzie się powtarzał nawet po udostępnieniu opcji ponownego włączenia).
Nie jestem pewien, czy to najlepsza opcja, ale moim zdaniem naprawia wszystkie awarie.
źródło
vectorDrawables.useSupportLibrary = true
opcji umożliwiającej ponowne włączenie generowania plików PNG w czasie kompilacji ?Miałem ten sam problem. Ale robiąc dużo badań i rozwoju, otrzymałem odpowiedź.
W przypadku użycia w Imageview i ImageButton
app:srcCompat="@drawable/...."
oraz w przypadku innych widoków, takich jak Button, Textview, zamiast używać"drawableLeft/right..."
w XML, określ programowalne elementy rysunkowe jako:button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);
I użyj „AppCompatResources”, aby pobrać plik do rysowania.
źródło
Aby rozwinąć inne bardzo dobre odpowiedzi , oto diagram, który może ci pomóc. Jest ważny, jeśli masz bibliotekę wsparcia od 23.4.0 do co najmniej 25.1.0.
źródło
Odpowiedź udzielona przez Guillherme P jest niesamowita. Żeby zrobić małą poprawę, nie musisz dodawać tej linii w każdym działaniu, jeśli dodałeś ją raz w klasie Application, to również zadziała.
public class App extends Application { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }
PAMIĘTAJ: nadal musisz mieć włączoną obsługę biblioteki w gradle:
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
Upewnij się też, że używasz biblioteki obsługi w wersji nowszej niż 23.4, gdy Google ponownie dodał obsługę kontenerów do rysowania dla VectorDrawables (informacja o wersji )
Aktualizacja
A dla zmian w kodzie:
app:srcCompat
każdego miejsca, które akceptujeandroid:src
atrybut (IDE ostrzeże Cię, jeśli jest nieprawidłowy, jak w przypadku<bitmap>
tagu).Na
drawableLeft
,drawableStart
,drawableRight
,drawableEnd
atrybuty używane wTextView
i podobne widoki, trzeba będzie ustawić je programowo teraz. Przykładowe ustawieniedrawableStart
:Drawable drawable = AppCompatResources.getDrawable( getContext(), R.drawable.your_vector_drawable); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); }
źródło
Miałem ten sam problem. I napraw to, usuwając
vectorDrawables.useSupportLibrary = true
Moja wersja docelowa to 25, a biblioteka wsparcia to
compile 'com.android.support:appcompat-v7:25.3.1'
źródło
vectorDrawables.useSupportLibrary = true
VectorDrawables na pre-Lollipop powinny działać dobrze bez użycia
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
Jeśli chcesz używać VectorDrawables wewnątrz ImageViews, możesz użyć atrybutu
srcCompat
i zadziała, ale w Buttons lub TextViews nie będzie , więc musisz zawinąć Drawable w InsetDrawable lub LayerDrawable. Jest jeszcze jedna sztuczka, którą odkryłem, jeśli używasz wiązania danych, możesz to zrobić:android:drawableLeft="@{@drawable/vector_ic_access_time_24px}" android:drawableStart="@{@drawable/vector_ic_access_time_24px}"
To magicznie zadziała, nie badałem, co dzieje się za kulisami, ale wydaje mi się, że TextView używa metody getDrawable z AppCompatResources lub podobnej.
źródło
Wiele prac badawczo-rozwojowych, w końcu otrzymuję to rozwiązanie na wypadek awarii na urządzeniach sprzed wersji Lollipop.
W przypadku Imageview
Dla TextView / EditText
Dla Build.gradle
źródło
Najłatwiejszy sposób użycia:
app:drawableRightCompat ="@drawable/ic_mobilelogin" app:drawableEndCompat="@drawable/ic_mobilelogin" app:srcCompat="@drawable/ic_mobile"
i ... po prostu użyj
app:**Compat
dla kompatybilności. Dodaj również obsługębuild.gradle
(moduł)android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
źródło
Dla każdego, kto zaktualizuje do Androida Gradle 3.0 i nowszy, nie ma potrzeby używania
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
ani ustawianiavectorDrawables.useSupportLibrary = true
(dodanie tego spowoduje problem) i używaniaapp:srcCompat
, po prostu działa.Zajmij mi dwa dni, aby to rozgryźć, i nie znalazłem żadnych powiązanych dokumentów w dokumentach Google ...
źródło
Używam VectorDrawables na urządzeniach Pre-Lollipop i tak to robię: -
Krok 1: Umieść to w ocenie na poziomie aplikacji.
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
Krok 2:
Umieść to w swojej klasie Application i nie zapomnij zarejestrować swojej klasy Application w pliku manifestu.
public class App extends Application { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } }
Krok 3:
Pobierz VectorDrawables za pomocą,
imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
źródło
Po użyciu poniższego kodu.
android { defaultConfig { vectorDrawables.useSupportLibrary = true } } public class App extends Application { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }}
nadal istnieje problem z obrazami wektorowymi dla poniższych atrybutów
DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Background
W takim przypadku postępuj zgodnie z poniższymi wskazówkami. Zamiast bezpośredniego odniesienia do obrazu wektorowego użyj znacznika selektora jako pośredniego pliku do rysowania.
Przykład:
ic_warranty_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="17dp" android:height="24dp" android:autoMirrored="true" android:viewportWidth="17" android:viewportHeight="24"> <path android:fillColor="#fff" android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />
safe_ic_warranty_icon.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_warranty_icon" /> </selector>
Twój TextView / Layout.
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableStart="@drawable/ic_warranty_icon" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/ic_warranty_icon" />
źródło
selector
Wypróbowaliśmy 3 rzeczy
vectorDrawables.useSupportLibrary = true
Ustawienie setCompatVectorFromResourcesEnabled w klasie Application
static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }
I użyć
app:srcCompat
Ale nawet potem zawodziło
Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008
potem zorientowaliśmy się, że nasz SVG ma tag Gradient. Konwersja tagu gradientu na indywidualne ścieżki dla poniższego API <= 23 i użycie tego samego API SVG> = 24 zadziałało.
Pomoc z tej odpowiedzi: https://stackoverflow.com/a/47783962/2171513
źródło
Walczyłem z tym godzinami.
Wypróbowałem wszystko, co podpowiadały mi te odpowiedzi, ale moja aplikacja nie przestawała się zawieszać. Usunąłem ten wiersz:
app:srcCompat="@drawable/keyboard"
i moja aplikacja przestała się zawieszać. a kiedy dodałem z powrotem to samo, znowu zaczęło się zawieszać. Postanowiłem więc otworzyć ten plik i zobaczyłem błąd w pierwszym wierszu:Kliknąłem plik prawym przyciskiem myszy i kliknąłem „Pokaż w eksploratorze” i nie znajdował się on w folderze do rysowania, ale w katalogu drawable-v24. Więc skopiowałem go i wkleiłem do katalogu do rysowania i ostatecznie pozbyłem się awarii.
źródło
Po prostu nałóż wektor, który można narysować na listę stanów, a problem zostanie rozwiązany
Na przykład masz obraz wektorowy strzałki wstecz:
ic_back_arrow.xml
tak, powinieneś nałożyć go na listę warstw xml (ic_back_arrow_vector_vector.xml):
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_back_arrow"/> </layer-list>
Ponieważ logika:
vectorDrawables.useSupportLibrary = true
i
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
nie pomoże Ci na niektórych chińskich urządzeniach i starszych urządzeniach Samsung. Jeśli ich nie pokryjesz, to się nie powiedzie.
źródło
Sugestia Guilherme P nie zadziałała dla mnie. Poszedłem naprzód i podjąłem decyzję o użyciu png, gdzie muszę robić rzeczy poza aplikacją: srcCompat, czyli drawableLeft, drawableRight itp. To była dość łatwa zmiana i nie ma potencjalnych problemów z pamięcią AppCompatDelegate.setCompatVectorFromResourcesEnabled ( prawdziwe); wprowadza.
źródło
Alternatywą dla odpowiedzi Benny'ego jest stworzenie
Activity
nadklasy:public abstract class VectorDrawableActivity extends AppCompatActivity { static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } //... }
Teraz rozszerz
VectorDrawableActivity
zamiastAppCompatActivity
.źródło