25

Ben metin içeren basit öğeler ve bazı durumlarda da görüntüleri göstermek için android.support.v7.widget.RecyclerView kullanıyorum. Temel olarak burada https://developer.android.com/training/material/lists-cards.html dan öğreticiyi takip ettim ve String [] 'den JSONArray ve ViewHolder'ın xml'sine mDataset türünü değiştirdim. Benim RecyclerView basit Fragment bulunur: Bu parçadaGörüntülerin garip davranışı RecyclerView

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin"> 

<!-- A RecyclerView with some commonly used attributes --> 
<android.support.v7.widget.RecyclerView 
    android:id="@+id/my_hopps_recycler_view" 
    android:scrollbars="vertical" 
    android:layout_centerInParent="true" 
    android:layout_width="200dp" 
    android:layout_height="wrap_content"/> 

</RelativeLayout> 

Bir web sunucusu tüm bilgileri yükleme ediyorum. Bilgileri aldıktan sonra öğeleri RecyclerView'da başlatıyorum. Fragmanımın onCreate yönteminde ayarlanmış bir LinearLayoutManager kullanıyorum. Bağdaştırıcıyı ekledikten sonra, RecyclerView'ımda setHasFixedSize (true) yöntemini çağırıyorum. Benim Adaptör sınıfı şöyle görünür:

import android.graphics.BitmapFactory; 
import android.support.v7.widget.RecyclerView; 
import android.util.Base64; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageButton; 
import android.widget.ImageView; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

import org.apache.commons.lang3.StringEscapeUtils; 
import org.json.JSONArray; 
import org.json.JSONObject; 

import saruul.julian.MyFragment; 
import saruul.julian.R; 

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { 

/** 
* Fragment holding the RecyclerView. 
*/ 
private MyFragment myFragment; 
/** 
* The data to display. 
*/ 
private JSONArray mDataset; 

public static class ViewHolder extends RecyclerView.ViewHolder { 

    public TextView text; 
    ImageView image; 

    public ViewHolder(View v) { 
     super(v); 
     text = (TextView) v.findViewById(R.id.my_view_text); 
     image = (ImageView) v.findViewById(R.id.my_view_image); 
    } 
} 

public MyAdapter(MyFragment callingFragment, JSONArray myDataset) { 
    myFragment = callingFragment; 
    mDataset = myDataset; 
} 

@Override 
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 
               int viewType) { 
    View v = LayoutInflater.from(parent.getContext()) 
      .inflate(R.layout.my_view, parent, false); 
    ViewHolder vh = new ViewHolder(v); 
    return vh; 
} 

// Replace the contents of a view (invoked by the layout manager) 
@Override 
public void onBindViewHolder(ViewHolder holder, int position) { 
    try { 
     JSONObject object = mDataset.getJSONObject(position); 
     if (object.has("image")){ 
      if (!hopp.getString("image").equals("")){ 
       try { 
        byte[] decodedString = Base64.decode(StringEscapeUtils.unescapeJson(object.getString("image")), Base64.DEFAULT); 
        holder.image.setImageBitmap(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length)); 
        holder.image.setVisibility(View.VISIBLE); 
       } catch (Exception e){ 
        e.printStackTrace(); 
       } 
      } 
     } 
     if (object.has("text")){ 
      holder.text.setText(object.getString("text")); 
     } 
    } catch (Exception e){ 
     e.printStackTrace(); 
    } 
} 

// Return the size of your dataset (invoked by the layout manager) 
@Override 
public int getItemCount() { 
    return mDataset.length(); 
} 
} 

Ve RecyclerView içinde bir görünüm için benim xml:

<android.support.v7.widget.CardView 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:card_view="http://schemas.android.com/apk/res-auto" 
android:id="@+id/card_view" 
android:layout_gravity="center" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
card_view:cardCornerRadius="4dp"> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:gravity="center" 
    android:orientation="vertical" 
    android:padding="@dimen/activity_horizontal_margin"> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center" 
     android:id="@+id/my_hopp_people_reached"/> 

    <ImageView 
     android:id="@+id/my_hopp_image" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:visibility="gone" 
     android:adjustViewBounds="true"/> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center" 
     android:id="@+id/my_hopp_text"/> 

    <ImageButton 
     android:id="@+id/my_hopp_delete" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@null" 
     android:src="@drawable/ic_action_discard" 
     /> 

</LinearLayout> 

</android.support.v7.widget.CardView> 

Yani şimdi burada benim problem: Her şey iyi çalışır. RecyclerView'umda metin ve resim doğru şekilde gösteriliyor. Ancak listenin sonuna kadar aşağıya inip tekrar yukarı kaydırırsam, resimler resimler içermemesi gereken öğelerde gösterilir. Şu anda dokuz ürünüm var. Son ikisi bir resim içeriyor. Bu yüzden aşağı kaydırıyorum ve ilk yedi öğede sadece metni görüyorum. Listenin sonuna ulaşmak bana beklenen iki fotoğrafı gösteriyor. Ancak tekrar yukarı kaydırırsam bu resimler diğer öğelerde görünür.

yukarı kaydırma ve aşağı aynı sırayla her zaman resim değiştirir:

  • ilk yukarı kaydırma (bir kez aşağı kaldıktan sonra) ikinci maddesinde bir resim yaratır.
  • Aşağı kaydırma, 7. öğede bir fotoğraf oluşturur.
  • Yukarı kaydırma, ilk öğede bir fotoğraf oluşturur.
  • Aşağı doğru kaydırma hiçbir şey oluşturmaz.
  • Kaydırma, üçüncü öğede bir fotoğraf oluşturur ve ikinci öğedeki resmin üzerine başka bir resim yazılır.
  • Aşağı kaydırma, 6. öğede bir resim oluşturur ve 7. öğenin içindeki resmin kaybolmasına izin verir.
  • Ve daha neler ...

Zaten onBindViewHolder (ViewHolder sahibi, int pozisyon) yöntemi her bir öğe ekranda tekrar görünür denir keşfetti. MDataset'imde konum ve verilen bilgileri kontrol ettim. Burada her şey iyi çalışıyor: Doğru ve verilen bilgiler de doğru. Tüm öğelerdeki metin değişmez ve her zaman doğru şekilde gösterilir. Bu sorunun herhangi bir türü var mı ve bir çözüm biliyor mu? Bunun neden gerekli olduğunu the documentation for onBindViewHolder en iyi tarif düşünüyorum

holder.image.setImageDrawable(null); 

:

cevap

39

Sana boş görüntüyü ayarlayarak, onBindViewHolder(ViewHolder holder, int position) stilini if (object.has("image")) açıklamaya bir else madde eklemek gerek

Verileri belirtilen konumda görüntülemek için RecyclerView tarafından çağrılır. Bu yöntem, öğeyi belirtilen konumda yansıtmak için itemView'un içeriğini güncellemelidir.

Hep insanlar hala bu ile ilgili sorunlar varsa tamamen güncellenmesi :)

+0

Bu hile yapmak gibi görünüyor! JSONObjects'imde her zaman bir resim alanı olacağından, if (! Hopp.getString ("image"). Equals ("")) deyimine başka bir ifade koydum. Ben de aynı şeyi denedim ama açıkça işe yaramadı ya da yanlış bir ifadede de koydum holder.image.setImageBitmap (null) kullanılır. Farketmez çünkü günümü kurtardın. :) –

+1

Teşekkürler. "Holder.image.setImageResource (R.drawable.image)" için değiştirdim; – zackygaurav

+0

Not: Volley – delive

11

emin değil ihtiyaç halinde ViewHolder geçti üstlenmesi gerektiğini, ancak deyimi benim için işe yaramadı eğer. Benim için çalışma yaptı şudur: adaptöre bu yöntem üzerinde geçersiz kılma kullanma

açıklamada onBindViewHolder içerisindeki görüntü kendisi için bu dayalı eğer öyleyse gibi arayarak takip

@Override 
    public int getItemViewType(int position) { 
     return position; 
    } 

:

int pos = getItemViewType(position); 
      if(theList.get(pos).getPicture() == null) { 

       holder.picture.setVisibility(View.GONE); 
      } else { 

       Picasso.with(context).load(R.drawable.robot).into(holder.picture); 
      } 

Picasso kullanıyorum ama başka bir durumla çalışması gerekiyor. Umarım bu birisine yardım eder!

+0

teşekkürler ahbap çalışıyor ... –

+1

getItemViewType ekleniyor sorunumu çözdü! – ziniestro

+0

Gerçekten işe yaradığı için – sukhbir

2

@ Lion789'un yanıtını temel alır. Resim ve json yüklemesi için Google'ın Volley kullanıyorum.

Bu, daha sonra geri dönüştürülecek görünümdeki konumu almamıza izin verir. istekte bulunurken

@Override 
public int getItemViewType(int position) { 
    return position; 
} 

, TAG

@Override 
public void onBindViewHolder(final ItemHolder holder, int position) { 
     ImageRequest thumbnailRequest = new ImageRequest(url, 
       new Response.Listener<Bitmap>() { 
        @Override 
        public void onResponse(Bitmap response) {       
         holder.itemThumbnail.setImageBitmap(response); 
        } 
       },[...]); 

     thumbnailRequest.setTag(String.valueOf(position)); //setting the TAG 
     mQueue.addToRequestQueue(thumbnailRequest); 
} 

Ve pozisyonunu ayarlamak görünümü biz mevcut görüntü

@Override 
public void onViewRecycled(ItemHolder holder) { 
    super.onViewRecycled(holder); 
    mQueue.cancelAll(String.valueOf(holder.getItemViewType())); 
    holder.itemThumbnail.setImageDrawable(null); 
} 
isteği iptal ve kaldırırız geri dönüşümlü edilirken

Volley garantileri iptal edilen istekleri teslim edilmeyecektir.

+0

teşekkürler, daha sonra görüntü her defasında görüntüye geri dönüyor mu? – x10sion

+0

Evet, ancak Volley her şeyi önbelleğe aldığından, görüntü zaten bellekte olurdu – Marcola