新しいAndroidバージョンでは、次のコード:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<shape Android:shape="oval">
<solid Android:color="#bdbdbd" />
<size
Android:width="60dp"
Android:height="60dp" />
</shape>
</item>
<item
Android:drawable="@drawable/ic_library_books_black_24dp"
Android:gravity="center"
Android:width="40dp"
Android:height="40dp"
>
</item>
</layer-list>
これを完璧に生成します:
しかし、以前のAndroidバージョン(私がテストしたものからのAPI 16および19)は、これがまったく好きではなく、
E/AndroidRuntime: FATAL EXCEPTION: main
Process: package.app, PID: 11490
Android.view.InflateException: Binary XML file line #26: Error inflating class ImageView
インフレ時に。すべてのImageViewにapp:srcCompat
を使用しているので、問題はありません。
標準のベクターDrawableも正常に機能しますが、layer-list
に配置すると混乱が生じます。回避策はありますか?
レイヤーリスト内のベクトルドロアブルの幅/高さ属性は、API 23(Marshmallow)以降でのみサポートされています。 Android Studioエディターでレイヤーリストのドロアブルを見ると、これらの属性の周りに黄色のブロックがあり、古いデバイスでは確実に機能しないという警告が表示されます。
しかし、警告を取り除き、次のような同じセンタリング効果を達成できると思います。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<shape Android:shape="oval">
<solid Android:color="#bdbdbd" />
<size
Android:width="60dp"
Android:height="60dp" />
</shape>
</item>
<item
Android:drawable="@drawable/ic_library_books_black_24dp"
Android:top="10dp"
Android:bottom="10dp"
Android:left="10dp"
Android:right="10dp">
</item>
</layer-list>
これを古いAPI 15の電話でテストしましたが、うまくいきました。これがあなたにも役立つことを願っています。
この回答の以前のバージョンでは、vectorDrawables.useSupportLibrary = true
をレイヤーリストで使用しないことをお勧めしました。クラッシュを引き起こすためです。ただし、クラッシュを修正するように思われる回避策について最近学びました(@ Android developerが正しく言及されている、自動生成された太ったpngファイルを回避します)。正しく機能するために何をする必要があるのかを以下に要約します。
xmlで必ずsrcCompatを使用してください。
<Android.support.v7.widget.AppCompatImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:srcCompat="@drawable/layer_list_with_svg" />
'vectorDrawables.useSupportLibrary'をapp/build.gradleに追加
Android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
'setCompatVectorFromResourcesEnabled(true)'をonCreateに追加
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
setContentView(R.layout.activity_main);
}
より知識のある人が私に説明したように、これはAndroidが互換性のあるベクトルDrawableをロードする方法と関係しています。vectorDrawables.useSupportLibrary = true
を使用している場合、画像ビューはVectorDrawableCompat
をロードしますapp:srcCompat
を使用する場合のドロウアブル。レイヤーリストドロウアブルが膨張している場合、それらの参照ベクトルドロウアブルの作成方法を把握する方法はありません。しかし、setCompatVectorFromResourcesEnabled
をオンにすると、画像ビューとそのapp:srcCompat
属性よりもはるかに低いレベルであるため、レイヤーリストで参照されるベクタードロウアブルをロードする方法を把握できます。
この回答は、Chris Banes(サポートライブラリで作業している)の記事 AppCompat-Vector of Vectors に基づいています。この質問については、「The magic 'way」というタイトルのセクションに注目しています。
あなたが経験しているクラッシュは、サポートライブラリがデフォルトでVectorDrawablesを使用するsome方法のみを許可し、layer-listがそれらの1つではないためです。
アクティビティの一番上に追加して、<layer-list>
などの他のVectorDrawable
の使用を有効にすることができる特定のコードブロックがあります。
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
注:リンクされた記事には、このメソッド名に「FromSources」を使用した誤字が含まれています。上記のように「FromResources」である必要があります。
このようなドロアブルを使用する各アクティビティにこれを追加するか、他のアクティビティの拡張元であるBaseActivityクラスに含める必要があります。
記事によれば、これは以下が機能することを意味するはずです。
ベクターリソースのみを含む他のドロウアブルリソースを参照するDrawableContainers。
... StateListDrawable ... InsetDrawable、LayerDrawable、LevelListDrawable、およびRotateDrawable。
ただし、このメソッドは「may」という単語と重く、これは動作する可能性があり、デフォルトでは有効になっていないため、実際に動作していることに注意して確認してくださいあなたのために!
実際、この質問には別の側面があり、他のユーザーへのクレジットSelim AjimiおよびRapunzel Van Winkle回答でこれに対処します。 <layer-list>
は、APIの間でいくつかの異なる動作を持ちます。特に、<item>
のwidth
およびheight
属性は、API 23+でのみサポートされます。これはクラッシュの原因ではなく、アプリがクラッシュすることもありませんが、以前のAPIで機能するとイメージが意図したとおりに表示されないことを意味します。
Rapunzel Van Winkleからの提案は、実際にAPI全体でドロウアブルを正しく配置する良い方法のようです(API 16および24でテスト済み):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<shape Android:shape="oval">
<solid Android:color="#bdbdbd" />
<size
Android:width="60dp"
Android:height="60dp" />
</shape>
</item>
<item
Android:drawable="@drawable/ic_library_books_black_24dp"
Android:top="10dp"
Android:bottom="10dp"
Android:left="10dp"
Android:right="10dp"
>
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<item
Android:drawable="@[package:]drawable/drawable_resource"
Android:id="@[+][package:]id/resource_name"
Android:top="dimension"
Android:right="dimension"
Android:bottom="dimension"
Android:left="dimension" />
</layer-list>
ご覧のとおり here には幅/高さの属性がありません...
あなたはアイテムにビットマップを追加することができますこれは最良の解決策だと思います
古いAndroidバージョンでのVectorDrawbleのサポートは かなり制限されています です。vectorDrawables.useSupportLibrary = true
を使用すると仮定します:
Android 5.0(APIレベル11)以降を実行しているすべてのデバイスでVectorDrawableCompatをAPIレベル7およびAnimatedVectorDrawableCompatに戻すことができます。方法Android XMLファイルなど、Drawable IDを受け入れるすべての場所でベクターDrawableのロードがサポートされていますAndroid.support.v7.appcompatパッケージには、ベクターDrawableを使いやすくするための多くの機能が追加されています。 ImageViewまたはImageButtonやFloatingActionButtonなどのサブクラスを含む.support.v7.appcompatパッケージでは、新しいapp:srcCompat属性を使用して、ベクターのドロアブルとAndroid:srcで利用可能な他のドロアブルを参照できます。
コードでも、制限があります:
実行時にドロアブルを変更するには、以前と同様にsetImageResource()メソッドを使用できます。 AppCompatとapp:srcCompatを使用することは、ベクタードロウアブルをアプリに統合する最も確実な方法です。
何ができる?
可能な解決策はほとんどありません:
layerDrawableで使用するVectorDrawableの代替ドローアブルがあります。たとえば、res/drawable-xxhdpiに配置し、VectorDrawableをres/drawable-anydpiに配置します。
アプリにVectorDrawableを使用できるminSdkがあるまで、vectorDrawables.useSupportLibrary = true
を使用しないでください。 IDEはPNGファイルを生成するため、これは機能します。
layerListをプログラムで作成し(例 here )、VectorDrawableを配置するには、AppCompatResources.getDrawable
を使用します。 VectorDrawableを配置する部分を除き、XMLを使用してそれを行うこともできます。
ところで、それが制限されている理由は、Googleが効率的で問題なくそれを実現できなかったことです。 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)を使用することで、完全にサポートするという当初の試みに到達できますが、ドキュメントにあるように、 [risk here :
この機能を有効にすると、メモリ使用量の問題や構成インスタンスの更新の問題が発生する可能性があるため、この機能はデフォルトで無効になっています。構成を手動で更新する場合、おそらくこれを有効にしたくないでしょう。 あなたは警告を受けました。