0

我使用RecyclerView作爲水平列表來顯示我的圖像。如何保持viewHolder的視圖被回收後的寬度

如果我滾動到第五張圖片,前兩個或三個被回收並且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

在我開始處理這個問題之前,有一件事需要清楚。 ViewHolder沒有任何寬度,它「擁有」的ImageView確實有寬度,這就是你想要控制的。

現在,考慮到這一點,您的問題是(在從您的代碼中進行某些假設之後),您需要知道某幅圖像在某個給定高度時的寬度,並保持寬高比 - 從服務器到達。

這是一個棘手的問題。

一種選擇是預先加載所有圖像。然而,這對於內存而言是非常昂貴的,並且可能導致內存崩潰。

更好的選擇是加載所有圖像的細節,而不實際下載圖像的像素。然後,您需要記住某個緩存中所有圖像的縱橫比,並在實際下載圖像內容之前設置要加載的圖像的尺寸。

要下載圖像的尺寸,而無需下載圖像本身,你應該使用這樣的事情:

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顯示不同取決於他們的寬高比寬度圖像,我相信這是你的最好的選擇。

+0

'onViewRecycled'後圖像的寬度仍然相同,它永遠不會改變。所以不需要'setLayoutParams' :( – dit

相關問題