我开发了这个自定义ImageView
类来覆盖一些默认行为以满足我的需要。让我描述一下这个习俗ImageView
的作用......
假设您有一堆图标要显示在GridView
和drawable-mdpi
文件drawable-hdpi
夹中,它们的大小分别为 48x48px 和 72x72px。文件夹中没有可用的图标drawable-xhdpi
。这些GridView
属性使所有图标大小都为 48x48dp(这将分别转换为 mpdi、hdpi 和 xhdpi 密度的 48px、72px 和 96px)。
由于文件夹中没有图标,所以drawable-xhdpi
当这个应用程序在如此密度的设备上运行时,图标将从drawable-hdpi
文件夹中拉出。由于它们只有 72 像素,而 xhdpi 设备需要 96 像素的图像,因此图标将被拉伸以填充剩余的像素。
这是我的自定义ImageView
尝试覆盖的行为。使用我的自定义组件,将发生的情况是图像根本不会被拉伸。例如,在上面使用我的类的示例中,ImageView
里面的每个GridView
仍然是 96x96px(因为定义了 48x48dp 大小),但使用的图像来自drawable-hdpi
72x72px 的文件夹。将会发生的是,文件夹中的这些图像drawable-hdpi
将被放置在ImageView
96x96px 大小的中心,而不会拉伸图像以适应整个视图大小。
如果上面的内容令人困惑,让我们尝试几张图片。下面的示例不使用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,到目前为止,我还没有觉得需要直接使用可绘制对象或位图。
现在我遇到的真正问题是......
如果这个类在某些布局中用作单个图像视图,没问题,它只解码一个图像。但是,如果它用于GridView
可能同时有 40 个图标(我从在我的 xhdpi 设备上运行的应用程序上实际发生的情况中获取这个值)可见的情况下,滚动GridView
将非常慢,因为它正在decodeBitmapResource()
调用BitmapFactory.decodeResource()
每一个图像。
这是我的问题,也是我的问题。我该如何优化呢?如果可能的话,完全...