我创建了一个非常简单的项目,通过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());
}
答案 0 :(得分:15)
这种情况正在发生,因为SGLM不保留任何有关视图的w / h信息。所以每当一个View被反弹时,它首先获得占位符大小,然后在加载图像时获得最终大小。
加载具有不同尺寸(比占位符)的实际图像会触发新的布局请求,并且在该布局请求期间,SGLM会检测到UI中存在间隙(或者某个项目位于项目下方会显示更高位置w / lower position)因此重新订购带有动画的项目。
您可以通过将占位符图像设置为实际图像的尺寸来避免这种情况。如果您没有提前使用它,可以在第一次加载图像后保存它们,并在下一个onBind调用中使用它。
答案 1 :(得分:9)
对我来说有用的是在使用StaggeredGridLayoutManager时禁用回收视图上的所有动画。
mRecyclerView.setItemAnimator(null);
如果您只想限制移动动画并保留添加和删除项目动画,则可以创建自己的动画制作。
答案 2 :(得分:8)
你可以试试这个
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();
}
});
这对我有用,我在某处得到这种方式。我希望它可以帮到你!
答案 3 :(得分:6)
更改此行
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
到这一行
mLayoutManager.setGapStrategy(
StaggeredGridLayoutManager.GAP_HANDLING_NONE);
答案 4 :(得分:3)
在方法的末尾添加以下行: 的 holder.mImageView.requestLayout(); 强>
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
holder.mImageView.requestLayout();
}
这解决了我的问题。
答案 5 :(得分:0)
也许这是一种更有效的方式:
btnButton.setOnAction((Integer a) -> System.out.println("something"));
btnButton.setOnAction((ActionEvent a) -> System.out.println("something"));
btnButton.setOnAction((Consumer<Integer>) a -> System.out.println("something"));
btnButton.setOnAction((EventHandler<ActionEvent>) a -> System.out.println("something"));
答案 6 :(得分:0)
首先设置缺口策略,例如以下代码:
mLayoutManager = new StaggeredGridLayoutManager(SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
,然后将您的商品添加到mItems
,然后使用:
mAdapter.notifyItemInserted(mItems.size() - 1);
此方法比使用以下方法更好:
mAdapter.notifyDataSetChanged();
答案 7 :(得分:0)
设置您的recyclerview的高度为固定高度,并为交错布局管理器设置项目的高度和宽度包装内容