我正在使用RecyclerView
作为水平列表来显示我的图片。
如果我滚动到第五张图片,前两个或三个将被回收,ViewHolder会丢失其宽度。如果我回滚到第一张图像,图像会再次加载,并在滚动时导致跳转。
以下是R.layout.fragment_details_view_img_item
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/details_view_img_item"
android:background="@color/red"
android:adjustViewBounds="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ImageView>
我的ViewHolder和适配器:
private class ViewHolder extends RecyclerView.ViewHolder {
ImageView img;
public ViewHolder(ImageView imgV){
super(imgV);
img = imgV;
}
}
private class ImageListAdapter extends RecyclerView.Adapter<ViewHolder> {
[...]
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
View v = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_details_view_img_item, parent, false);
v.setOnClickListener(listener);
logDebug("onCreateViewHolder");
return new ViewHolder((ImageView) v);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
logDebug("onBindViewHolder");
ImageItem item = data.get(i);
if (item != null) {
ImageView imgView = viewHolder.img;
imgView.setTag(item);
String imgurl = ImageUtil.imgUrlForAvailableHeightInPX(item, parentHeight);
ImageLoader.instance().loadASYNC(imgurl, imgView);
}
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
logDebug("onViewRecycled: " + holder.img.getTag());
}
}
那么如何保持ViewHolder的宽度?
答案 0 :(得分:0)
在我开始解决这个问题之前,有一点需要明确。 ViewHolder
没有任何宽度,ImageView
它&#34;拥有&#34;确实有宽度,这就是你想要控制的东西。
现在,考虑到这一点,你的问题是(在查看你的代码做出某些假设之后)你需要知道某个图像处于特定高度时的宽度,同时保持纵横比 - 在它到达之前来自服务器。
这是一个棘手的问题。
一种选择是预加载所有图像。然而,这对于内存非常昂贵,并且可能导致内存崩溃。
更好的选择是加载所有图像&#39;细节,没有实际下载图像&#39;像素。然后,您需要记住某些缓存中所有图像的纵横比,并在实际下载图像内容之前设置您要加载的图像的尺寸。
要下载图片的尺寸而不下载图片本身,您应该使用以下内容:
public float getImageAspectRatio(InputStream inputStreamFromServer)
{
BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStreamFromServer, null, decodeOptions);
final float imageDesiredWidth = decodeOptions.outWidth;
final float imageDesiredHeight = decodeOptions.outHeight;
return imageDesiredWidth / imageDesiredHeight;
}
使用此方法后,您需要使用此功能预加载所有图像:
private float[] mAspectRatios;
public void decodeAllAspectRatios(List<String> imageUrls)
{
mAspectRatios = new float[imageUrls.size()];
InputStream inputStream;
int index = 0;
for (String url : imageUrls)
{
// Get the input stream from the image url using whatever method you use.
mAspectRatios[index] = getImageAspectRatio(inputStream);
index++;
}
}
重要提示:在此方法完成工作之前,您的RecyclerView
不应该开始工作。
预加载所有宽高比后,我们将返回ViewHolder:
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
logDebug("onBindViewHolder");
ImageItem item = data.get(i);
if (item != null) {
ImageView imgView = viewHolder.img;
// set the layout params of the image, making it fit the correct size prior to loading the bitmap.
imgView.setLayoutParams(new LayoutParams(parentHeight * mAspectRatios[i], parentHeight));
imgView.setTag(item);
String imgurl = ImageUtil.imgUrlForAvailableHeightInPX(item, parentHeight);
ImageLoader.instance().loadASYNC(imgurl, imgView);
}
}
只要您希望RecyclerView
根据宽高比显示不同宽度的图像,我相信这是您的最佳选择。