StaggeredGridLayoutManager and moving items

匿名 (未验证) 提交于 2019-12-03 02:54:01

问题:

I have created a very simple project, displaying 28 images with StaggeredGridLayoutManager by recyclerview. but as I scroll the recyclerview it moves items for example from left to right or swap the column of left and right.

codes:

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 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();         for (int i = 1; i 

And the adapter:

public class MyRecyclerAdapter extends RecyclerView.Adapter {       private List mItems;     Context mContext;      public MyRecyclerAdapter(Context context,List 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);      }  } 

and a sample moving item:

http://i.imgur.com/FUapm2K.gif?1

if you play (scroll up and down) you can discover more interesting animation :-)

How to prevent that and having stable layout like an ordinary listview?

Edit

@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()); } 

回答1:

This is happening because SGLM does not keep any w/h information about the views. So each time a View is rebound, it gets the place holder size first and then the final size when the image is loaded.

Loading the actual image w/ different size (than place holder) triggers a new layout request, and during that layout request, SGLM detects that there will be gaps in the UI (or some item w/ higher position appears below an item w/ lower position) thus re-orders items w/ an animation.

You can avoid it by setting your place holder image to the dimensions of the actual image. If you don't have it ahead of time, you can save them after the image is loaded for the first-time and use it in the next onBind call.



回答2:

What worked for me was to disable all animation on the recycle view when using StaggeredGridLayoutManager.

mRecyclerView.setItemAnimator(null);

You can create your own animator if you only want to restrict moving animations and keep the add and remove item animations.



回答3:

Change this line

mLayoutManager.setGapStrategy(         StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);  

to this line

mLayoutManager.setGapStrategy(         StaggeredGridLayoutManager.GAP_HANDLING_NONE);            


回答4:

You can try this

    StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL);     manager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);     mRecyclerView.setLayoutManager(manager); 

after you set this, you'll find there is a blank at the top when you scroll to the top. continue to set this

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {         @Override         public void onScrollStateChanged(RecyclerView recyclerView, int newState) {             super.onScrollStateChanged(recyclerView, newState);             ((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).invalidateSpanAssignments();         }     }); 

It's work for me, I get this way somewhere. I hope it can help you!



回答5:

Add the following line at the end of the method: holder.mImageView.requestLayout();

@Override public void onBindViewHolder(ViewHolder holder, int position) {     ...     holder.mImageView.requestLayout(); } 

This fixed the issue for me.



回答6:

Maybe this is a more efficient way:

mBrandRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {         @Override         public void onScrollStateChanged(RecyclerView recyclerView, int newState) {             if(newState == RecyclerView.SCROLL_STATE_IDLE){                 mBrandRecyclerView.invalidateItemDecorations();             }         }     }); 

For more information: https://github.com/ibosong/CommonItemDecoration



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!