gpt4 book ai didi

android - 如何优化要在 GridView 中使用的自定义 ImageView?

转载 作者:行者123 更新时间:2023-11-29 02:00:34 24 4
gpt4 key购买 nike

我开发了这个自定义 ImageView 类来覆盖一些默认行为以满足我的需要。让我描述一下这个自定义 ImageView 的作用...

假设您有一堆图标要显示在 drawable-mdpidrawable-hdpi 文件夹中的 GridView 中,它们是大小分别为 48x48px 和 72x72px。 drawable-xhdpi 文件夹中没有可用图标。 GridView 属性使所有图标的大小都为 48x48dp(对于 mpdi、hdpi 和 xhdpi 密度,这将分别转换为 48px、72px 和 96px)。

由于 drawable-xhdpi 文件夹中没有图标,当此应用程序在具有这种密度的设备上运行时,图标将从 drawable-hdpi 中提取> 文件夹。 并且由于它们只有 72 像素,而 xhdpi 设备需要 96 像素的图像,因此图标将被拉伸(stretch)以填充剩余的像素。

这是我的自定义 ImageView 试图覆盖的行为。使用我的自定义组件,将会发生的是图像不会被拉伸(stretch)。例如,在上面使用我的类的示例中,GridView 中的每个 ImageView 仍将是 96x96px(因为定义了 48x48dp 大小)但使用的图像来自 drawable-hdpi 文件夹,大小为 72x72px。 将会发生的是,drawable-hdpi 文件夹中的这些图像将放置在大小为 96x96px 的 ImageView 的中心,而无需拉伸(stretch)图像以适应整个 View 大小。

如果上面的内容令人困惑,让我们尝试几张图片。下面的示例没有使用 GridView,我试图简化自定义类背后的想法。这些是我在此示例中使用的源图片:

source-files

这是在 HDPI 设备上的结果:

hdpi-demo

这是在 XHDPI 设备上的结果:

xhdpi-demo

上面截图的布局代码是这样的:

<?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>

现在更清楚了吗?这就是我想要做的,除了一个小的性能问题外,它工作得很好......现在让我发布我用于此类自定义组件的代码:

属性.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 View 用于 XML 布局或直接在代码中初始化,则此类将执行此操作。我还提供了 2 种方法,因此可以在代码中更改图像,同时防止图像被拉伸(stretch)。如您所见,这些方法仅采用资源 ID,到目前为止,我还没有觉得需要直接使用可绘制对象或位图。

现在我遇到的真正问题是......

如果此类在某些布局中用作单个 ImageView ,没问题,它只会解码一个图像。但是,如果它用在 GridView 中,其中可能有 40 个图标(我从我的 xhdpi 设备上运行的应用程序中实际发生的情况中获取这个值)同时可见,滚动 GridView 会非常慢,因为 decodeBitmapResource() 正在为每个图像调用 BitmapFactory.decodeResource()

这是我的问题,那是我的问题。 我该如何优化它?如果可能的话……

最佳答案

将这些图像放入 res/drawable-nodpi/ 可以做你想做的事(我是说将不同分辨率的图像并排放置)。

这会有点棘手,因为您可能必须遵循命名约定才能为您尝试绘制的给定图像找到最佳资源。可能这将要求您尝试按名称查找图像,这不是检索资源的非常有效的方法。

我想象的方式是:在布局(或其他任何地方)上,您指定要使用的图像资源的名称(字符串,而不是 id!)。

在该 nodpi 文件夹中,您将拥有带有预期屏幕密度后缀的图像。

然后,在 setter 方法中,您必须尝试不同的组合以找到最佳可用资源。

您要思考的问题:如果您要缩小图像怎么办?该资源将比您绘制它的 View 更大!

关于android - 如何优化要在 GridView 中使用的自定义 ImageView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12897775/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com