StaggeredGridLayoutManager 和移动项目

新手上路,请多包涵

我创建了一个非常简单的项目,通过 recyclerview 使用 StaggeredGridLayoutManager 显示 28 张图像。但是当我滚动 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://i.imgur.com/FUApm2K.gif?1

如果你玩(上下滚动)你会发现更多有趣的动画:-)

如何防止这种情况并像普通列表视图一样具有稳定的布局?

编辑

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

原文由 mmlooloo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 930
2 个回答

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

加载具有不同大小(比占位符)的实际图像会触发新的布局请求,并且在该布局请求期间,SGLM 检测到 UI 中将存在间隙(或者某些具有较高位置的项目出现在具有较低位置的项目下方) position) 因此重新排序带有动画的项目。

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

原文由 yigit 发布,翻译遵循 CC BY-SA 3.0 许可协议

对我有用的是在使用 StaggeredGridLayoutManager 时禁用回收视图上的所有动画。

mRecyclerView.setItemAnimator(null);

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

原文由 Sanchit 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题