web-dev-qa-db-ja.com

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

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

  • 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の外部でベクトルDrawableを直接参照すると、Lollipopの前に失敗します。ただし、AppCompatは、StateListDrawable、InsetDrawable、LayerDrawable、LevelListDrawable、RotateDrawableなどの別のドロアブルコンテナで参照されている場合、ベクトルドロアブルのロードをサポートします。このindirectionを使用することにより、TextViewのAndroid:drawableLeft属性などの場合にベクタードロアブルを使用できます。これは通常、ベクタードロアブルをサポートできません。

app:srcCompatを使用している場合はすべて正常に機能しますが、使用する場合:

Android:background
Android:drawableLeft
Android:drawableRight
Android:drawableTop
Android:drawableBottom

lollipopの前のImageViewImageButtonTextView、またはEditTextでは、次のように予期がスローされます。

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

最新アップデート-2019年6月

サポートライブラリは、元の回答から少し変更されています。現在、gradleでもビルド時にPNGを自動的に生成できます。そのため、最近はうまくいくはずの2つの新しいアプローチを以下に示します。より多くの情報を見つけることができます こちら:

サポートライブラリ

おそらく、これはあなたのために働くソリューションです。ここに来た場合、Android St​​udioがPNGを自動的に生成していないことを意味します。そのため、アプリがクラッシュしています。 PNG生成は、XML要素のサブセットのみをサポートします。ただし、このソリューションはすべてのxmlタグをサポートします。したがって、ベクトルドロウアブルを完全にサポートしています。

まず、ビルドグラドルを更新してサポートする必要があります。

Android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  compile 'com.Android.support:appcompat-v7:23.2.0' // OR HIGHER
}

そして、ベクトルドロウアブルにはapp:srcCompatの代わりにAndroid:srcを使用します。これを忘れないでください。

TextViewの場合、AndroidXを使用している場合、app:drawableLeftCompatの代わりにapp:drawableLeft(またはright、top、bottom)を使用できます

AndroidXを使用していない場合やボタンを使用していない場合は、

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

PNG生成

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

私は自分のアプリでこのソリューションを使用していますが、正常に動作します。追加のbuild.gradleフラグは必要ありません。ハックは必要ありません。 「/ build/generated/res/pngs/...」に移動すると、生成されたすべてのPNGが表示されます。

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


更新-2016年7月

彼らはそのVectorDrawableを再び有効にしました
Androidサポートライブラリ23.4.

AppCompatユーザーの場合、opt-inAPIを追加しましたAppCompatDelegate.setCompatVectorFromResourcesEnabled(true)を介して、リソースからのベクターDrawablesのサポートを再度有効にします(23.2にある動作)-これにより、メモリ使用量とConfigurationインスタンスの更新の問題が発生する可能性があるため、デフォルトで無効になっている理由に注意してください。

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

今、それを有効にするには、あなたがする必要があります:

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

    ...
}

元の回答-2016年4月

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

これによると POST

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

Issue ISSUE 205236 にアクセスすると、今後有効になるようですが、メモリの問題は間もなく修正されません。

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

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

これが最良の選択肢かどうかはわかりませんが、私の意見ではすべてのクラッシュを修正します。

67
W0rmH0le

同じ問題がありました。しかし、多くの研究開発を行うと、答えが得られました。

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

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

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

58

他の 非常に良い答え について詳しく説明するために、ここに があります。 23.4.0から少なくとも25.1.0のサポートライブラリがある場合に有効です。

VectorDrawable cheatsheet

51
David Ferrand

Guillherme Pからの答えはとても素晴らしいです。ちょっとした改善をするために、すべてのアクティビティにその行を追加する必要はありません。Applicationクラスに一度追加すると、同様に機能します。

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. drawableLeftおよび同様のビューで使用されるdrawableStartdrawableRightdrawableEndTextView属性については、今のところプログラムで設定する必要があります。 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);
    }
    
38
Benny

同じ問題がありました。削除して修正します

vectorDrawables.useSupportLibrary = true

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

 compile 'com.Android.support:appcompat-v7:25.3.1'
12
Rajesh Nasit

事前ロリポップのVectorDrawablesは、使用せずに正常に動作するはずです

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

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

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

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

9
cesards

多くの研究開発、最終的にロリポップ以前のデバイスでのクラッシュに対するこのソリューションを取得しました。

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

6
Jatin Mandanka

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

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

4
Geng Jiawen

Pre-LollipopデバイスでVectorDrawablesを使用していますが、これがその方法です:-

ステップ1:これをアプリレベルのgradleに入れます。

Android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

ステップ2:

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

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

ステップ3:

次を使用してVectorDrawablesを取得します。

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

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

Android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




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

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

DrawableEnd、DrawableStart、DrawableTop、DrawableBottom、背景

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

例:

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"
       />
0
Rajesh Gr

状態リストに描画可能なベクトルを単にオーバーラップすると、問題が解決します

たとえば、後方矢印ベクトル画像があります:

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
mr.boyfox

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にGradientタグがあることがわかりました。以下のAPI <= 23でグラデーションタグを個々のパスに変換し、同じSVG API> = 24を使用すると機能しました。

この答えから助けを得た https://stackoverflow.com/a/47783962/217151

0
Aalap

最も簡単な使用法:

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

そして... app:** CompatabilityのCompatを使用するだけです

Buil.gradleのサポートも追加します(モジュール)

Android {
 defaultConfig {
vectorDrawables.useSupportLibrary = true
               }
        }
0
Hamed Jaliliani