このカスタムImageView
クラスを開発して、私のニーズに合わせてデフォルトの動作の一部をオーバーライドしました。この習慣が何をするのか説明しましょうImageView
...
フォルダーとフォルダーGridView
の両方に表示するアイコンがたくさんあるとします。それぞれのサイズは 48x48px と 72x72px です。フォルダに使用できるアイコンはありません。属性は、すべてのアイコンのサイズが 48x48dp になるように設定されています (これは、mpdi、hdpi、および xhdpi 密度に対してそれぞれ 48px、72px、および 96px に変換されます)。drawable-mdpi
drawable-hdpi
drawable-xhdpi
GridView
フォルダーにはアイコンがないためdrawable-xhdpi
、このアプリがそのような密度のデバイスで実行されると、アイコンはフォルダーからプルされdrawable-hdpi
ます。また、それらは 72 ピクセルしかなく、xhdpi デバイスは 96 ピクセルの画像を想定しているため、アイコンは引き伸ばされて残りのピクセルを埋めます。
これは、私のカスタムImageView
がオーバーライドしようとしている動作です。カスタム コンポーネントを使用すると、画像が単純に引き伸ばされなくなります。たとえば、私のクラスを使用した上記の例では、ImageView
内部のそれぞれGridView
は 96x96px のままですが (48x48dp のサイズが定義されているため)、使用される画像drawable-hdpi
は 72x72px のフォルダーからのものです。何が起こるかというと、drawable-hdpi
フォルダーのこれらの画像はImageView
、ビュー全体のサイズに合わせて画像を引き伸ばすことなく、サイズが 96x96 ピクセルの の中央に配置されます。
上記がわかりにくい場合は、いくつかの写真で試してみましょう。以下の例では を使用していませんGridView
。カスタム クラスの背後にあるアイデアを単純化しようとしています。これらは、この例で使用しているソース画像です。
これは、HDPIデバイスでの結果です。
そして、これはXHDPIデバイスでの結果です:
上記のスクリーンショットのレイアウトのコードは次のとおりです。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Standard ImageView:"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="10dp"
android:scaleType="center"
android:background="#FFEEEE"
android:src="@drawable/ic_female"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="10dp"
android:scaleType="center"
android:background="#FFEEEE"
android:src="@drawable/ic_male"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Custom UnscaledImageView:"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<com.sampleapp.widget.UnscaledImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="10dp"
android:scaleType="center"
android:background="#FFEEEE"
android:src="@drawable/ic_female"/>
<com.sampleapp.widget.UnscaledImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="10dp"
android:scaleType="center"
android:background="#FFEEEE"
android:src="@drawable/ic_male"/>
</LinearLayout>
より明確になりましたか?これは私がやりたいことであり、これはうまく機能していますが、小さなパフォーマンスの問題を除けば...このようなカスタムコンポーネントに使用しているコードを投稿しましょう:
attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="UnscaledImageView">
<attr name="android:src" />
</declare-styleable>
</resources>
UnscaledImageView.java:
public class UnscaledImageView extends ImageView {
private int mDeviceDensityDpi;
public UnscaledImageView(Context context) {
super(context);
mDeviceDensityDpi = getResources().getDisplayMetrics().densityDpi;
}
public UnscaledImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mDeviceDensityDpi = getResources().getDisplayMetrics().densityDpi;
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.UnscaledImageView);
int resourceId = styledAttrs.getResourceId(R.styleable.UnscaledImageView_android_src, 0);
if(resourceId != 0) {
setUnscaledImageResource(resourceId);
}
styledAttrs.recycle();
}
public void setUnscaledImageResource(int resId) {
setImageBitmap(decodeBitmapResource(resId));
}
@SuppressWarnings("deprecation")
public void setUnscaledBackgroundResource(int resId) {
BitmapDrawable drawable = new BitmapDrawable(null, decodeBitmapResource(resId));
drawable.setTargetDensity(mDeviceDensityDpi);
drawable.setGravity(Gravity.CENTER);
setBackgroundDrawable(drawable);
}
private Bitmap decodeBitmapResource(int resId) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = mDeviceDensityDpi;
return BitmapFactory.decodeResource(getResources(), resId, options);
}
}
したがって、このクラスは、UnscaledImageView
ビューが XML レイアウトで使用されているか、コードで直接初期化されている場合に機能します。また、2 つのメソッドを用意して、画像が引き伸ばされないようにしながら、コードで画像を変更できるようにしました。ご覧のとおり、これらのメソッドはリソース ID のみを受け取ります。これまでのところ、ドローアブルやビットマップを直接使用する必要性を感じたことはありません。
今、私がこれで抱えている本当の問題は...
このクラスが何らかのレイアウトで単一の画像ビューとして使用される場合、問題はありません。1 つの画像をデコードするだけです。ただし、GridView
40 個のアイコン (xhdpi デバイスで実行されているアプリで実際に発生することからこの値を取得しています) が同時に表示される可能性がある場所で使用される場合、スクロールは非常GridView
に遅くなります。ありとあらゆるイメージ。decodeBitmapResource()
BitmapFactory.decodeResource()
これは私の問題であり、それが私の質問です。これを最適化するにはどうすればよいですか?できれば全然...