Lollipopがクラッシュする前にAndroid Vector Drawableを使用する


91

私はLollipopより前の Androidでベクタードローアブルを使用しており、これらは私のライブラリとツールバージョンの一部です。

  • Android Studio:2.0
  • Android Gradleプラグイン:2.0.0
  • ビルドツール:23.0.2
  • Androidサポートライブラリ:23.3.0

このプロパティをアプリレベルで追加しました Build.Gradle

android {  
  defaultConfig {  
    vectorDrawables.useSupportLibrary = true  
   }  
}

Android公式ブログ(リンクはこちら)に記載されているLayerDrawable(layer_list)などの追加のドローアブルを使用して、外部のベクトルドローアブルのドローアブルを設定することにも言及する価値があります。app:srcCompat

<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/search"/>
</level-list>

app:srcCompatの外部でベクタードローアブルを直接参照すると、Lollipopの前に失敗します。ただし、AppCompatは、StateListDrawable、InsetDrawable、LayerDrawable、LevelListDrawable、RotateDrawableなどの別のドローアブルコンテナーで参照されている場合、ベクタードローアブルの読み込みをサポートします。この 間接参照を使用することで、TextViewのandroid:drawableLeft属性など、通常はベクタードローアブルをサポートできない場合に、ベクタードローアブルを使用できます。

私が使用しapp:srcCompatているときはすべてうまくいきますが、使用したとき:

android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom

上のImageViewImageButtonTextViewまたはEditTextロリポップ前に、それはexpectionがスローされます。

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9


VectorDrawableをdrawableLeft、drawableRight、drawableTop、drawableBottomと一緒に使用する方法を確認するには、この回答
Behzad Bahmanyar

ここで私の答えを確認できますか?stackoverflow.com/a/40523623/2557258
Yazon2006

私の場合は、vactorのDrawableは、右のパッケージではありませんでした(開いているプロジェクトビュー)ここorginal答えstackoverflow.com/a/35836318/2163045
MURT

回答:


102

最新の更新-2019年6月

サポートライブラリは、最初の回答から少し変更されています。これで、GradleのAndroidプラグインでも、ビルド時にPNGを自動的に生成できます。だから、以下は最近うまくいくはずの2つの新しいアプローチです。あなたはここでより多くの情報を見つけることができます

PNG生成

Gradleは、ビルド時にアセットからPNG画像を自動的に作成できます。ただし、このアプローチでは、すべてのxml要素がサポートされるわけではありません。このソリューションは、コードやbuild.gradleで何も変更する必要がないため便利です。Androidプラグイン1.5.0以降Android Studio 2.2以降を使用していることを確認してください。

私は自分のアプリでこのソリューションを使用しており、正常に動作します。追加のbuild.gradleフラグは必要ありません。ハックは必要ありません。あなたがに行く場合は/構築/生成/ RES / PNG画像は/ ...あなたはすべての生成されたPNG画像を見ることができます。

したがって、単純なアイコンがある場合(すべてのxml要素がサポートされているわけではないため)、この解決策が役立つことがあります。Android StudioとGradle用のAndroidプラグインを更新するだけです。

サポートライブラリ

おそらく、これはあなたのために働くソリューションです。ここに来た場合は、Android StudioがPNGを自動的に生成していないことを意味します。そのため、アプリがクラッシュしています。

あるいは、Android StudioでPNGをまったく生成したくない場合もあります。

XML要素のサブセットをサポートする「自動PNG生成」とは異なり、このソリューションはすべてのxmlタグをサポートします。したがって、ベクタードローアブルは完全にサポートされています。

最初に、それをサポートするようにbuild.gradleを更新する必要があります。

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
}

そして、読み込み中のapp:srcCompat代わりにandroid:srcを使用しますVectorDrawables。これをお忘れなく。

の場合TextViewandroidxサポートライブラリのバージョンを使用している場合はapp:drawableLeftCompat、代わりに(または右、上、下)を使用できます。app:drawableLeft

CheckBox/の場合、の代わりにRadioButton使用します。app:buttonCompatandroid:button

androidxSupport Libraryのバージョンを使用しておらず、バージョンminSdkVersion17それ以上の場合、またはボタンを使用している場合は、プログラムで設定してみてください。

Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);

更新-2016年7月

Androidサポートライブラリ23.4.0でVectorDrawableを再度有効にしました

AppCompatユーザー向けに、AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)を介して、リソースからのベクターDrawableのサポートを再度有効にするオプトイン APIを追加しました(23.2で見つかった動作)。これでもメモリ使用量と構成インスタンスの更新に問題があるため、デフォルトで無効になっている理由。

たぶんbuild.gradle設定は廃止され、適切なアクティビティで有効にする必要があります(ただし、テストする必要があります)。

これを有効にするには、次のことを行う必要があります。

public class MainActivity extends AppCompatActivity {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    ...
}

元の回答-2016年4月

これは、最新のライブラリバージョン23.3.0でサポートベクターが無効になっているために発生していると思います。

このPOSTによると:

AppCompatユーザーの場合、バージョン23.2.0 / 23.2.1 (ISSUE 205236)の実装で見つかった問題が原因で、Lollipop以前のデバイスのリソースからベクタードローアブルを使用できる機能を削除することにしました。app:srcCompatおよびsetImageResource()の使用は引き続き機能します。

問題ISSUE 205236にアクセスすると、将来的には有効になるようですが、メモリの問題はすぐには修正されません。

次のリリースでは、削除されたVectorDrawableサポートを再度有効にできるオプトインAPIを追加しました。ただし、以前と同じ警告(メモリ使用量と構成の更新に関する問題)が付属しています。

同様の問題がありました。したがって、私の場合、ベクタードローアブルを使用するすべてのアイコンをリソースからPNG画像に戻しました(メモリを再び有効にするオプションを提供した後でもメモリの問題が発生し続けるため)。

これが最良のオプションかどうかはわかりませんが、私の意見ではすべてのクラッシュが修正されます。


1
@Guilherme P.に感謝しますが、なぜ、vectorDrawables.useSupportLibrary = trueperopertyを削除して、ビルド時にpngの生成を再び有効にすることに戻らなかったのですか?
Behzad Bahmanyar 16

1
メモリの問題により、最新バージョンv23.3.0では無効になりました。このように、実行時にpngを生成できません...そのため、logcatエラーでは、不明なタグベクトル(またはそのようなもの)が出力されます。
W0rmH0le 2016

4
こちらがオプトインの手順plus.google.com/+AndroidDevelopers/posts/B7QhFkWZ6YXです。残念ながら、VectorDrawableはまだPre-Lollipopデバイスでは動作しません。私はサポートライブラリ23.4.0を使用しており、defaultConfig {}で「generatedDensities = []」と「vectorDrawables.useSupportLibrary = true」の両方が呼び出されています。
Adam Hurwitz、2016

1
@AdamHurwitz私は答えを更新しました..再び有効にされたようです..しかし、今は別の方法で有効にする必要があります。
W0rmH0le 2016

1
@juztcodeその通りです。「androidx.appcompat:appcompat:1.1.0」を使用する必要があります
W0rmH0le

63

私も同じ問題を抱えていました。しかし、多くの研究開発を行って答えを得ました。

ImageviewとImageButtonを使用する場合、app:srcCompat="@drawable/...." およびButtonやTextviewなどの他のビューを使用する場合"drawableLeft/right..."は、XML で使用する代わりに、プログラムでドローアブルを次のように指定します。

button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);

そして、「AppCompatResources」を使用してドローアブルを取得します。


59

その他については詳しく説明し、非常に良い答え、ここでお手伝いをすることができます。23.4.0から25.1.0以上のサポートライブラリがある場合に有効です。

VectorDrawableチートシート


1
drawableLeftを設定しようとしている場合は、ここで説明するように、それをドローアブル内にラップします。medium.com/@chrisbanes/...
nizam.sp

このチャートは私たちをたくさん助けてくれてありがとう。
silentsudo 2018年

39

Guillherme Pからの答えはかなり素晴らしいです。小さな改善を行うために、すべてのアクティビティにその行を追加する必要はありません。アプリケーションクラスに一度追加すると、同様に機能します。

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

覚えておいてください。gradleでサポートライブラリの使用を有効にする必要があります。

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

また、GoogleがVectorDrawablesのDrawable Containersのサポートを再度追加したときは、v23.4以降のサポートライブラリバージョンを使用していることを確認してください(リリースノート)。

更新

そしてコード変更のために:

  1. 属性app:srcCompatを受け入れるすべての場所に必ず更新してくださいandroid:src<bitmap>タグのように無効な場合、IDEから警告が表示されます)。
  2. 以下のためにdrawableLeftdrawableStartdrawableRightdrawableEndで使用される属性TextViewと同様の見解は、あなたが今のプログラムでそれらを設定する必要があります。設定例drawableStart

    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);
    }

Gradleでベクタードローアブルのサポートライブラリを使用する必要があることを覚えておいてください:vectorDrawables.useSupportLibrary = true
Benny

2
うん。知っている。しかし、ベクタードローアブルをTexViewのドローアブルとして機能させるためのラッパーが必要であるため、この回答は不完全です。
2016年

1
すばらしい答えです。これは、すべてのアクティビティがカスタムベースアクティビティから拡張されたアプリに特に適しています。
Hong

14

私も同じ問題を抱えていました。削除して修正します

vectorDrawables.useSupportLibrary = true

私のターゲットバージョンは25で、サポートライブラリは

 compile 'com.android.support:appcompat-v7:25.3.1'

1
これは私のために働いた。ありがとう。私はちょうどそれを削除しましたvectorDrawables.useSupportLibrary = true
Androidの平凡な

これは適切な方法ではないと思います。どちらにしても、私はあなたの回答に賛成票を投じました。
ハリッシュレディ

ありがとうございました。tは私のアプリで動作します。すべてのベクター型ドローアブルは、削除されても引き続き機能します。アプリはcom.android.support:appcompat-v7:28.0.0を使用します
Hong

10

プレロリポップのVectorDrawableは使用せずに正常に動作するはずです

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

ImageViews内でVectorDrawablesを使用したい場合は、属性srcCompatを使用できますが、機能しますが、ButtonsまたはTextViews内では機能しません。そのため、DrawableをInsetDrawableまたはLayerDrawableにラップする必要があります。私が発見した別のトリックがあり、データバインディングを使用している場合、これを行うことができます。

android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"

それは魔法のように機能します。舞台裏で何が起こっているのか調査していませんが、TextViewがAppCompatResourcesなどのgetDrawableメソッドを使用していると思います。


セレクターでベクター画像を設定する方法は?
Tushar Gogna

GradleのデフォルトでvectorDrawables.useSupportLibrary = trueを設定した後、 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); 作成中のアクティビティでTextviewのandroid:drawableleftによるクラッシュを回避するには、たとえば、次のようにプログラムでdrawbleをtextviewに左に設定します。
Afjalur Ra​​hman Rana

7

多くのR&D、ついにプレロリポップデバイスでのクラッシュに対するこのソリューションを取得します。

Imageviewの場合

  • android:srcの代わりにapp:srcCompatを使用します

TextView / EditTextの場合

  • drawableleftdrawableright ....を削除し、drawable javaコードから設定します。

txtview.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(EventDetailSinglePage.this、R.drawable.ic_done_black_24_n)、null、null、null);

Build.gradleの場合

vectorDrawables.useSupportLibrary = true


1
これは、TextInputEditTextで機能するユニークなソリューションでした。
ヘロンサンチ

1
これは私の問題を解決しました。これは受け入れられるべき答えです。
DJtiwari 2018

6

最も簡単な使い方:

app:drawableRightCompat ="@drawable/ic_mobilelogin"
app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"

そして... app:**Compat互換性のためだけに使用 します。build.gradle(モジュール)のサポートも追加する

android {
   defaultConfig {
       vectorDrawables.useSupportLibrary = true
   }
}

app:drawableEndCompatとapp:drawableRightCompatは、英語の場合はほとんど同じです
Hossam Hassan

5

Android Gradle 3.0以降にアップグレードする場合は、を使用AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)したり設定したりする必要はありませんvectorDrawables.useSupportLibrary = true(これを追加すると問題が発生します)。app:srcCompat、それするだけです。

これを理解するには2日かかりますが、Googleのドキュメントで関連ドキュメントが見つかりません...


興味深いことに、私はgradle 3.3.0を使用しており、このソリューションは機能します。ただし、Android Studioは引き続きset vectorDrawables.useSupportLibrary = trueを有効にするように指示しています。
masterwok 2018

2

私はプレロリポップデバイスでVectorDrawablesを使用しています、そしてこれは私がそれをする方法です:-

ステップ1: これをアプリレベルのグラドルに配置します。

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

ステップ2:

これをアプリケーションクラスに入れ、アプリケーションクラスをマニフェストファイルに登録することを忘れないでください。

public class App extends Application {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }
}

ステップ3:

以下を使用してVectorDrawableを取得します。

imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));

2

以下のコードを使用した後。

android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




public class App extends Application {
static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}

それでも、以下の属性のベクター画像の問題が存在します

DrawableEnd、DrawableStart、DrawableTop、DrawableBottom、Background

この場合は、次のようにしてください。ベクター画像を直接参照する代わりに、セレクタータグを中間描画可能ファイルとして直接使用します。

例:

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>

あなたの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"
       />

ありがとう!!! 背景プロパティについては、ベクタードローアブルを直接使用するのではなく、間にセレクターを追加することがpre-lollipop apiで機能しました(19)。
アンクル

私の場合、これは、API(16)ではまだ機能しません。ラップしてもselector
mochadwi

1

3つのことを試しました

vectorDrawables.useSupportLibrary = true

ApplicationクラスでのsetCompatVectorFromResourcesEnabledの設定

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

そして使う app:srcCompat

しかし、その後も失敗しました

Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008

次に、SVGにグラデーションタグが付いていることがわかりました。以下のAPI <= 23のグラデーションタグを個別のパスに変換し、同じSVG API> = 24を使用するとうまくいきました。

この回答から助けを得ましたhttps://stackoverflow.com/a/47783962/2171513


なぜ誰もこれに賛成しない理由はわかりませんが、これが実際に私の問題の解決策になる可能性があります。ありがとう
DevMike01

0

単純にベクトルドローアブルを状態リストにオーバーラップして、問題を解決します

たとえば、戻る矢印のベクター画像があります:

ic_back_arrow.xml

はい、レイヤーリスト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>

論理だから:

vectorDrawables.useSupportLibrary = true

そして

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

一部の中国のデバイスと古いサムスンのデバイスではあなたを助けません。それらをオーバーラップさせないと、失敗します。


0

私はこれに何時間も苦労していました。

私はこれらの答えが教えてくれたすべてを試しましたが、私のアプリはクラッシュを止めませんでした。この行を削除したところapp:srcCompat="@drawable/keyboard"、アプリがクラッシュしなくなりました。その後、同じものを追加すると、再びクラッシュし始めました。だから私はそのファイルを開くことにしました、そして私は最初の行でエラー

「ドローアブル「キーボード」は、ベースドローアブルフォルダーに宣言がありません。これにより、クラッシュが発生する可能性があります。

ファイルを右クリックして[エクスプローラーで表示]をクリックすると、ファイルは描画可能なフォルダーではなく、描画可能なv24ディレクトリにありました。だから私はそれをコピーして描画可能なディレクトリに貼り付け、最終的にクラッシュを取り除きました。


-2

ギルヘルメPの提案は私には役立たなかった。私は先に進み、app:srcCompatの外で何かを実行する必要がある場所でpngを使用することを決定しました。 true); 紹介します。


-3

ベニーの答えの代替手段は、Activityスーパークラスを作成することです:

public abstract class VectorDrawableActivity extends AppCompatActivity {
  static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
  }

  //...
}

VectorDrawableActivityではなく、拡張してくださいAppCompatActivity


@cesardsどうして?
Code-Apprentice
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.