Androidアプリでベクタードロウアブルを使用しようとしています。 http://developer.Android.com/training/material/drawables.html (エンファシス鉱山)から:
Android 5.0(APIレベル21)以上では、定義を失うことなくスケーリングするベクトルドロアブルを定義できます。
このドロウアブルの使用:
<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:height="24dp"
Android:width="24dp"
Android:viewportWidth="24"
Android:viewportHeight="24">
<path Android:fillColor="@color/colorPrimary" Android:pathData="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />
このImageView:
<ImageView
Android:layout_width="400dp"
Android:layout_height="400dp"
Android:src="@drawable/icon_bell"/>
400dpでアイコンを表示しようとすると、このぼやけた画像が生成されます(Lollipopを実行している2015年頃の大型の高解像度デバイスで):
ベクトルDrawableの定義で幅と高さを200dpに変更すると、400dpのレンダリングサイズでの状況が大幅に改善されます。ただし、これをTextView要素の描画可能オブジェクト(テキストの左側のアイコン)に設定すると、巨大なアイコンが作成されます。
私の質問:
1)なぜベクターのドロアブルに幅/高さの指定があるのですかこれらの全体的なポイントは、定義で幅と高さを無意味にする無損失に拡大縮小することだと思いましたか?
2)TextViewで24dpのドロアブルとして機能する単一のベクトルドロアブルを使用することはできますか?例えば。異なるサイズの複数のベクトルDrawableの作成を回避し、代わりにレンダリング要件に合わせてスケーリングするものを使用するにはどうすればよいですか?
3)幅/高さ属性を効果的に使用するにはどうすればよいですか?また、viewportWidth/Heightとの違いは何ですか?
追加の詳細:
この問題に関する新しい情報がここにあります:
https://code.google.com/p/Android/issues/detail?id=202019
Android:scaleType="fitXY"
を使用すると、Lollipopで正しくスケーリングされるようです。
Googleエンジニアから:
こんにちは、画像をシャープに見せるために、scaleType = 'fitXY'が回避策になるかどうか教えてください。
マシュマロ対ロリポップは、マシュマロに追加された特別なスケーリング処理によるものです。
また、コメントについて:「正しい動作:ベクトルドロウアブルは品質を損なうことなくスケーリングする必要があります。したがって、アプリケーションで3つの異なるサイズで同じアセットを使用する場合、vector_drawable.xmlを異なるサイズで3回複製する必要はありませんハードコードされたサイズ。」
私はこれが事実であるべきだと完全に同意しますが、実際には、Androidプラットフォームはパフォーマンスの問題を抱えており、理想的な世界にはまだ到達していません。したがって、画面上に同時に3つの異なるサイズを描画することが確実な場合は、パフォーマンスを向上させるために、実際には3つの異なるvector_drawable.xmlを使用することをお勧めします。
技術的な詳細は、基本的に、フックの下でビットマップを使用して複雑なパスレンダリングをキャッシュし、ビットマップドロアブルの再描画と同等の最高の再描画パフォーマンスを得ることができるようにすることです。
1)なぜベクターのドロアブルに幅/高さの指定があるのですかこれらの全体的なポイントは、定義で幅と高さを無意味にする無損失に拡大縮小することだと思いましたか?
ビルドシステムがラスターイメージを生成する必要がある21未満のSDKバージョンの場合、および幅/高さを指定しない場合のデフォルトサイズとして。
2)TextViewで24dpのドロアブルとして機能する単一のベクトルドロアブルと、画面に近い幅の大きな画像を使用できますか?
21未満のSDKもターゲットにする必要がある場合、これが可能だとは思わない。
3)幅/高さ属性を効果的に使用するにはどうすればよいですか?また、viewportWidth/Heightとの違いは何ですか?
ドキュメント: (実際に読み直した今ではあまり役に立たない...)
Android:width
ドロアブルの固有の幅を定義するために使用されます。これは、通常dpで指定されるすべてのディメンション単位をサポートします。
Android:height
ドロアブルの本質的な高さを定義するために使用されます。これは、通常dpで指定されるすべてのディメンション単位をサポートします。
Android:viewportWidth
ビューポートスペースの幅を定義するために使用されます。ビューポートは、基本的にパスが描画される仮想キャンバスです。
Android:viewportHeight
ビューポート空間の高さを定義するために使用されます。ビューポートは、基本的にパスが描画される仮想キャンバスです。
Android 4.4(APIレベル20)以前では、ベクトルドロアブルはサポートされていません。最小APIレベルがこれらのAPIレベルのいずれかに設定されている場合、Vector Asset Studioは、Gradleに下位互換性のためにベクトルDrawableのラスターイメージを生成するよう指示します。ベクトル資産は、Javaコードでは
Drawable
、XMLコードでは@drawable
として参照できます。アプリを実行すると、対応するベクターまたはラスター画像がAPIレベルに応じて自動的に表示されます。
編集:何か変なことが起こっています。エミュレータSDKバージョン23での私の結果は次のとおりです(Lollipop +テストデバイスは現在動作していません...):
そして、エミュレータSDKバージョン21では:
AppCompat 23.2では、Android 2.1以降を実行しているすべてのデバイスにベクタードロウアブルが導入されています。ベクタードロウアブルのXMLファイルで指定された幅/高さに関係なく、画像は正しくスケーリングされます。残念ながら、この実装はAPIレベル21以降では使用されません(ネイティブ実装が優先されます)。
良いニュースは、AppCompatにAPIレベル21および22での実装の使用を強制できることです。悪いニュースは、これを行うためにリフレクションを使用する必要があることです。
まず、AppCompatの最新バージョンを使用していること、および新しいベクター実装を有効にしていることを確認してください。
Android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
compile 'com.Android.support:appcompat-v7:23.2.0'
}
次に、アプリケーションのonCreate()でuseCompatVectorIfNeeded();
を呼び出します。
private void useCompatVectorIfNeeded() {
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt == 21 || sdkInt == 22) { //vector drawables scale correctly in API level 23
try {
AppCompatDrawableManager drawableManager = AppCompatDrawableManager.get();
Class<?> inflateDelegateClass = Class.forName("Android.support.v7.widget.AppCompatDrawableManager$InflateDelegate");
Class<?> vdcInflateDelegateClass = Class.forName("Android.support.v7.widget.AppCompatDrawableManager$VdcInflateDelegate");
Constructor<?> constructor = vdcInflateDelegateClass.getDeclaredConstructor();
constructor.setAccessible(true);
Object vdcInflateDelegate = constructor.newInstance();
Class<?> args[] = {String.class, inflateDelegateClass};
Method addDelegate = AppCompatDrawableManager.class.getDeclaredMethod("addDelegate", args);
addDelegate.setAccessible(true);
addDelegate.invoke(drawableManager, "vector", vdcInflateDelegate);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
最後に、app:srcCompat
ではなくAndroid:src
を使用してImageViewの画像を設定していることを確認してください。
<ImageView
Android:layout_width="400dp"
Android:layout_height="400dp"
app:srcCompat="@drawable/icon_bell"/>
ベクターのドローアブルは正しくスケーリングされるはずです!
1)なぜベクターのドロアブルに幅/高さの指定があるのですかこれらの全体的なポイントは、定義で幅と高さを無意味にする無損失に拡大縮小することだと思いましたか?
これは、レイアウトビューで定義しない場合のベクトルのデフォルトサイズです。 (つまり、imageviewの高さと幅にラップコンテンツを使用します)
2)TextViewで24dpのドロアブルとして機能する単一のベクトルドロアブルと、画面に近い幅の大きな画像を使用できますか?
はい、可能です。実行中のデバイスがLollipop以上を使用している限り、サイズ変更に問題はありません。以前のAPIでは、アプリをビルドすると、さまざまな画面サイズのベクターがpngに変換されます。
3)幅/高さ属性を効果的に使用するにはどうすればよいですか?また、viewportWidth/Heightとの違いは何ですか?
これは、ベクターの周囲のスペースの使用方法に影響します。つまり、ビューポート内のベクトルの「重力」を変更したり、ベクトルにデフォルトのマージンを持たせたり、ベクトルの特定の部分をビューポートから外したりするなどに使用できます。通常は、同じ値に設定しますサイズ。
私はこれらの方法を試してみましたが、残念ながら、どれも機能しませんでした。 fitXY
でImageView
を試して、app:srcCompat
を使用しようとしましたが、使用することさえできません。しかし、私はトリックの方法を見つけました:
drawableを
background
のImageView
に設定します。
しかし、この方法のポイントはビューの次元です。 ImageView
の寸法が正しくない場合、drawableはStretchを取得します。 Lollipop以前のバージョンで制御するか、一部のビューPercentRelativeLayout
を使用する必要があります。
役に立てば幸いです。
First:svgをdrawbleにインポート:(( https://www.learn2crack.com/2016/02/Android-studio-svg .html )))
描画可能フォルダを右クリックして、[新規]-> [ベクトルアセット]を選択します。
2- Vector Asset Studioには、組み込みのマテリアルアイコンまたは独自のローカルsvgファイルを選択するオプションがあります。必要に応じて、デフォルトのサイズをオーバーライドできます。
Second:Android API 7+からのサポートが必要な場合は、Android Support Library acordingを使用する必要があります(( https://stackoverflow.com/a/44713221/1140304 ))
1-追加
vectorDrawables.useSupportLibrary = true
build.gradleファイルに。
2- imageViewを持つレイアウトで名前空間を使用します。
xmlns:app="http://schemas.Android.com/apk/res-auto"
Third:imageViewをAndroid:scaleType = "fitXY"に設定し、app:srcCompatを使用します
<ImageView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scaleType="fitXY"
app:srcCompat="@drawable/ic_menu" />
4番目:Javaコードにsvgを設定する場合、oncreate methoedの行の下に追加する必要があります
@Override
protected void onCreate(Bundle savedInstanceState)
{
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
ベクトル画像のサイズを変更するだけで問題を解決できます。最初からそれは次のようなリソースでした:
<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:aapt="http://schemas.Android.com/aapt"
Android:width="24dp"
Android:height="24dp"
Android:viewportHeight="300"
Android:viewportWidth="300">
そして、私はそれを次のように150dp(このベクトルリソースのレイアウトのImageViewのサイズ)に変更しました:
<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:aapt="http://schemas.Android.com/aapt"
Android:width="150dp"
Android:height="150dp"
Android:viewportHeight="300"
Android:viewportWidth="300">
それは私のために働いています。
私にとって、ベクターがpngに変換される原因は、ベクターDrawableのAndroid:fillType="evenodd"
属性でした。 drawableでこの属性のすべてのオカレンスを削除した(デフォルトのnonzero
塗りつぶしタイプを使用するベクトル)の場合、次回アプリをビルドしたときにすべてがうまくいきました。