J'ai créé un projet très simple, affichant 28 images avec StaggeredGridLayoutManager
par recyclerview. mais au fur et à mesure que je fais défiler la vue recyclée, il déplace des éléments, par exemple, de gauche à droite ou échange la colonne gauche/droite.
import Java.util.ArrayList;
import Java.util.List;
import Android.app.Activity;
import Android.os.Bundle;
import Android.support.v7.widget.RecyclerView;
import Android.support.v7.widget.StaggeredGridLayoutManager;
public class MainActivity extends Activity {
String mImageDir;
private RecyclerView mRecyclerView;
private StaggeredGridLayoutManager mLayoutManager;
MyRecyclerAdapter myRecyclerAdapter;
List<ImageModel> mImageList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview_rootview);
mLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(false);
mImageList = new ArrayList<ImageModel>();
for (int i = 1; i < 29 ; i++) {
ImageModel img = new ImageModel();
img.setTitle("Image No " + i);
int drawableResourceId = this.getResources().getIdentifier("image"+String.valueOf(i), "drawable", this.getPackageName());
img.setResId(drawableResourceId);
mImageList.add(img);
}
myRecyclerAdapter = new MyRecyclerAdapter(MainActivity.this,mImageList);
mRecyclerView.setAdapter(myRecyclerAdapter);
}
}
Et l'adaptateur:
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
private List<ImageModel> mItems;
Context mContext;
public MyRecyclerAdapter(Context context,List<ImageModel> objects) {
mContext = context;
mItems = objects;
}
static class ViewHolder extends RecyclerView.ViewHolder{
public ImageView mImageView;
public TextView mTextView;
public View rootView;
public ViewHolder(View itemView) {
super(itemView);
rootView = itemView;
mImageView =(ImageView)itemView.findViewById(R.id.image);
mTextView =(TextView)itemView.findViewById(R.id.title);
}
}
@Override
public int getItemCount() {
return mItems.size();
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageModel item = mItems.get(position);
Picasso.with(mContext).load(item.getResId()).into(holder.mImageView);
holder.mTextView.setText(item.getTitle());
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
LayoutInflater inflater =
(LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View convertView = inflater.inflate(R.layout.item, parent, false);
return new ViewHolder(convertView);
}
}
http://i.imgur.com/FUapm2K.gif?1
si vous jouez (faites défiler de haut en bas) vous pouvez découvrir une animation plus intéressante :-)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ImageModel item = mItems.get(position);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams)holder.mImageView.getLayoutParams();
float ratio = item.getHeight()/item.getWidth();
rlp.height = (int)(rlp.width * ratio);
holder.mImageView.setLayoutParams(rlp);
Picasso.with(mContext).load(item.getResId()).into(holder.mImageView);
holder.mTextView.setText(item.getTitle());
}
Cela se produit car SGLM ne conserve aucune information sur les vues. Ainsi, chaque fois qu’une vue est rebondie, elle obtient d’abord la taille de l’emplacement, puis la taille finale du chargement de l’image.
Le chargement de l'image réelle avec une taille différente (que celle de l'espace réservé) déclenche une nouvelle demande de mise en page. Au cours de cette demande, SGLM détecte qu'il y aura des vides dans l'interface utilisateur (ou qu'un élément avec une position plus élevée apparaît sous un élément avec positionne donc les articles avec une animation.
Vous pouvez l'éviter en définissant votre image de lieu réservé aux dimensions de l'image réelle. Si vous ne l'avez pas à l'avance, vous pouvez les enregistrer une fois que l'image est chargée pour la première fois et les utiliser lors du prochain appel onBind.
Changer cette ligne
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
à cette ligne
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_NONE);
Tu peux essayer ça
StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL);
manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
mRecyclerView.setLayoutManager(manager);
une fois que vous avez défini ceci, vous constaterez qu’il ya un blanc en haut lorsque vous faites défiler vers le haut. continuer à définir cette
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).invalidateSpanAssignments();
}
});
C'est un travail pour moi, j'arrive là quelque part. J'espère que cela peut vous aider!
Ajoutez la ligne suivante à la fin de la méthode: holder.mImageView.requestLayout ();
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
holder.mImageView.requestLayout();
}
Cela a résolu le problème pour moi.
Tout d'abord définir la stratégie de l'écart comme suit
mLayoutManager = new StaggeredGridLayoutManager (SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL); mLayoutManager.setGapStrategy (StaggeredGridLayoutManager.GAP_HANDLING_NONE);
puis ajoutez votre article à mItems puis utilisez:
mAdapter.notifyItemInserted (mItems.size () - 1); cette méthode est préférable à l'utilisation de:
mAdapter.notifyDataSetChanged ();
C'est peut-être un moyen plus efficace:
mBrandRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if(newState == RecyclerView.SCROLL_STATE_IDLE){
mBrandRecyclerView.invalidateItemDecorations();
}
}
});
Pour plus d'informations: https://github.com/ibosong/CommonItemDecoration
Définissez la hauteur de votre vue recyclable ainsi que la hauteur et la largeur de l'élément, ainsi que le contenu enveloppant pour le gestionnaire de disposition décalé