StaggeredGridLayoutManager和移动项目

我创build了一个非常简单的项目,通过recyclerview显示28个StaggeredGridLayoutManager的图像。 但是当我滚动recyclerview时,它会将项目从左向右移动,或者交换左右列。

代码:

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

和适配器:

 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://sofzh.miximages.com/android/FUapm2K.gif?1

如果你玩(上下滚动),你可以发现更有趣的animation:-)

如何防止和像一个普通的listview有稳定的布局?

编辑

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

Solutions Collecting From Web of "StaggeredGridLayoutManager和移动项目"

发生这种情况是因为SGLM不保留有关视图的任何w / h信息。 所以每当一个视图被反弹时,它首先得到占位符的大小,然后在图像加载的时候获得最终的大小。

加载具有不同大小(比占位符)更大的实际图像会触发新的布局请求,并且在该布局请求期间,SGLM会检测到UI中会有间隙(或者某个项目位于较低位置位置)从而重新订购项目w /animation。

您可以通过将占位符图像设置为实际图像的尺寸来避免这种情况。 如果您没有提前准备,可以在首次加载图像后保存,并在下次onBind调用中使用。

什么对我来说是使用StaggeredGridLayoutManager时禁用在回收视图上的所有animation。

mRecyclerView.setItemAnimator(null);

如果您只想限制移动animation并保留添加和删除项目animation,则可以创build自己的animation制作者。

改变这一行

 mLayoutManager.setGapStrategy( StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS); 

到这一行

 mLayoutManager.setGapStrategy( StaggeredGridLayoutManager.GAP_HANDLING_NONE); 

你可以试试这个

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

设置完毕后,当您滚动到顶部时,您会发现顶部有空白。 继续设置这个

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

这是为我工作,我在某个地方得到这种方式。 我希望它可以帮助你!

在该方法的末尾添加以下行: holder.mImageView.requestLayout();

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

这为我解决了这个问题。

也许这是一个更有效的方法:

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

欲了解更多信息: https : //github.com/ibosong/CommonItemDecoration