之前要做一个瀑布流效果 需要动态设置图片的高度 按照普通的recyclerview设置瀑布流的操作来写 结果出现一个现象:向下滑动超出一屏的距离再滑动回顶部的时候 出现Item错位,间距消失等问题 (注:截图没体现出瀑布流效果是因为这几张图片的高度一样 )
先贴效果图和有问题的代码
效果图:
有问题的代码:
private void initRecyclerview() {
mRecyclerviewFind.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerviewFind.setLayoutManager(staggeredGridLayoutManager);
mRecyclerviewFind.setItemAnimator(null);
if (mRecyclerviewFind.getItemDecorationCount() == 0) {
mRecyclerviewFind.addItemDecoration(new StaggeredDividerItemDecorationFind(getActivity(), DisplayUtils.dp2px(getActivity(), 4)));
}
mStaggerAdapter = new MyRecyclerAdapter(getActivity(),mDataList);
mStaggerAdapter.setHasStableIds(true);
mRecyclerviewFind.setAdapter(mStaggerAdapter);
{
}
class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder>{
private List<FindBean.DataBean> mDatas;
private Context mContext;
private LayoutInflater inflater;
private HashMap<Integer,Integer> map=new HashMap<>();
private int item_width=App.SCREEN_WIDTH/2-DisplayUtils.dp2px(getActivity(),2); //item宽度
public MyRecyclerAdapter(Context context,List<FindBean.DataBean> datas){
this. mContext=context;
this. mDatas=datas;
inflater=LayoutInflater. from(mContext);
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.adapter_find,parent, false);
MyViewHolder holder= new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
try {
int width = mDatas.get(position).getCover().getWidth();
int height = mDatas.get(position).getCover().getHeight();
ViewGroup.LayoutParams layoutParams = holder.mIvPic.getLayoutParams();
layoutParams.width=item_width;
layoutParams.height=height*layoutParams.width/width;
holder.mIvPic.setLayoutParams(layoutParams);
Log.e("xxxxxxxx",position+"----宽:"+layoutParams.width+"------高"+layoutParams.height);
FindBean.DataBean bean = mDatas.get(position);
FindBean.DataBean.AuthorInfoBean authorInfo = bean.getAuthorInfo();
if (null!=authorInfo){
holder.mTvName.setText(authorInfo.getName());
}
holder.mTvTitle.setText(bean.getTitle());
// RoundedCorners roundedCorners = new RoundedCorners(DisplayUtils.dp2px(getActivity(), 5));
// //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
// RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300);
//加载图片
GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_pic_placeholder).load( bean.getCover().getUrl()).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.mIvPic);
if (null!=authorInfo)
GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_userdefault).apply(RequestOptions.circleCropTransform()).load(authorInfo.getOwnerUrl()).into(holder.mIvUserIcon);
holder.mIvLaudView.setBackgroundResource(true == mDatas.get(position).isLaudedStatus() ? R.mipmap.ic_like_red : R.mipmap.ic_like_black);
} catch (Exception e) {
e.printStackTrace();
}
holder.mIvPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
holder.mIvLaudView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTvTitle;
TextView mTvName;
ImageView mIvPic;
ImageView mIvUserIcon;
ImageView mIvLaudView;
RelativeLayout mParentView;
public MyViewHolder(View itemView) {
super(itemView);
mTvName= itemView.findViewById(R.id.tv_name);
mTvTitle= itemView.findViewById(R.id.tv_title);
mIvPic= itemView.findViewById(R.id.iv_pic);
mIvUserIcon= itemView.findViewById(R.id.iv_usericon);
mIvLaudView= itemView.findViewById(R.id.iv_laudedstatus);
mParentView= itemView.findViewById(R.id.parent);
}
}
}
然后我百度recyclerview瀑布流滑动item错乱问题 发现很多的解决办法
最多的就是设置以下代码
staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//不设置的话,图片闪烁错位,有可能有整列错位的情况。
mRecyclerviewFind.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
staggeredGridLayoutManager.invalidateSpanAssignments();
}
});
我设置setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE)后发现item都不可见了 然后继续找解决办法
网上说在adapter的layout布局外面套一层Framelayout,我在布局外面套了一层RelaytiveLayout,发现有效果,Item可见了,但是滑动数据错乱问题依旧没有解决
最后查到有的解决方案是重写getitemId 返回position 有的是重写 getItemViewType方法 return position,没办法 只好一个个试一下 结果发现重写getItemViewType方法有效果,Item不再错位
在adapter中重写
@Override
public int getItemViewType(int position) {
return position;
}
但是现在还有个问题 就是每次滑动 Item虽然不错位 但是会闪烁和间距消失(就是图片上同一行的两个item左边的item右间距没了 右边Item的左间距没有变成右间距) 如图:
我猜测是滑动的时候重绘引起的 于是将下面这段代码注销
mRecyclerviewFind.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
staggeredGridLayoutManager.invalidateSpanAssignments();
}
});
Ok,功夫不负有心人 ,终于 问题解决 特此记录下。希望能帮到遇到同样问题的你
最后贴上我完整的正确代码:
public class StaggeredDividerItemDecorationFind extends RecyclerView.ItemDecoration {
private Context context;
private int interval;
public StaggeredDividerItemDecorationFind(Context context, int interval) {
this.context = context;
this.interval = interval;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
// 获取item在span中的下标
int spanIndex = params.getSpanIndex();
int interval = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
this.interval, context.getResources().getDisplayMetrics());
// 中间间隔
if (spanIndex % 2 == 0) { //左
outRect.left = 0;
outRect.right=interval/2;
} else { //右
// item为奇数位,设置其左间隔为5dp
outRect.left=interval/2;
outRect.right = 0;
}
// 下方间隔
outRect.bottom = interval;
}
}
private void initRecyclerview() {
mRecyclerviewFind.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
//staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//不设置的话,图片闪烁错位,有可能有整列错位的情况。
mRecyclerviewFind.setLayoutManager(staggeredGridLayoutManager);
mRecyclerviewFind.setItemAnimator(null);
if (mRecyclerviewFind.getItemDecorationCount() == 0) {
mRecyclerviewFind.addItemDecoration(new StaggeredDividerItemDecorationFind(getActivity(), DisplayUtils.dp2px(getActivity(), 4)));
}
mStaggerAdapter = new MyRecyclerAdapter(getActivity(),mDataList);
mStaggerAdapter.setHasStableIds(true);
mRecyclerviewFind.setAdapter(mStaggerAdapter);
}
class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder>{
private List<FindBean.DataBean> mDatas;
private Context mContext;
private LayoutInflater inflater;
private HashMap<Integer,Integer> map=new HashMap<>();
private int item_width=App.SCREEN_WIDTH/2-DisplayUtils.dp2px(getActivity(),2); //item宽度
public MyRecyclerAdapter(Context context,List<FindBean.DataBean> datas){
this. mContext=context;
this. mDatas=datas;
inflater=LayoutInflater. from(mContext);
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.adapter_find,parent, false);
MyViewHolder holder= new MyViewHolder(view);
return holder;
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
try {
//动态设置图片的高度
int width = mDatas.get(position).getCover().getWidth();
int height = mDatas.get(position).getCover().getHeight();
ViewGroup.LayoutParams layoutParams = holder.mIvPic.getLayoutParams();
layoutParams.width=item_width;
layoutParams.height=height*layoutParams.width/width;
holder.mIvPic.setLayoutParams(layoutParams);
Log.e("xxxxxxxx",position+"----宽:"+layoutParams.width+"------高"+layoutParams.height);
FindBean.DataBean bean = mDatas.get(position);
FindBean.DataBean.AuthorInfoBean authorInfo = bean.getAuthorInfo();
if (null!=authorInfo){
holder.mTvName.setText(authorInfo.getName());
}
holder.mTvTitle.setText(bean.getTitle());
// RoundedCorners roundedCorners = new RoundedCorners(DisplayUtils.dp2px(getActivity(), 5));
// //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
// RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300);
//加载图片
GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_pic_placeholder).load( bean.getCover().getUrl()).diskCacheStrategy(DiskCacheStrategy.ALL).into(holder.mIvPic);
if (null!=authorInfo)
GlideApp.with(getActivity()).asBitmap().placeholder(R.mipmap.ic_userdefault).apply(RequestOptions.circleCropTransform()).load(authorInfo.getOwnerUrl()).into(holder.mIvUserIcon);
holder.mIvLaudView.setBackgroundResource(true == mDatas.get(position).isLaudedStatus() ? R.mipmap.ic_like_red : R.mipmap.ic_like_black);
} catch (Exception e) {
e.printStackTrace();
}
holder.mIvPic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
holder.mIvLaudView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView mTvTitle;
TextView mTvName;
ImageView mIvPic;
ImageView mIvUserIcon;
ImageView mIvLaudView;
public MyViewHolder(View itemView) {
super(itemView);
mTvName= itemView.findViewById(R.id.tv_name);
mTvTitle= itemView.findViewById(R.id.tv_title);
mIvPic= itemView.findViewById(R.id.iv_pic);
mIvUserIcon= itemView.findViewById(R.id.iv_usericon);
mIvLaudView= itemView.findViewById(R.id.iv_laudedstatus);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/rl_pic"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_pic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/ic_pic_placeholder"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/iv_laudedstatus"
android:layout_width="18dp"
android:layout_height="17dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:background="@mipmap/ic_like_black" />
</RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/rl_pic"
android:layout_marginLeft="18dp"
android:background="@mipmap/ic_arrow_up_white" />
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/rl_pic"
android:layout_marginBottom="14dp">
<ImageView
android:id="@+id/iv_usericon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="11dp"
android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:singleLine="true"
android:text=""
android:textColor="#262628"
android:textSize="12dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/iv_usericon"
app:layout_constraintLeft_toRightOf="@id/iv_usericon"
app:layout_constraintTop_toTopOf="@+id/iv_usericon" />
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="11dp"
android:layout_marginRight="11dp"
android:layout_marginTop="9dp"
android:ellipsize="end"
android:fontFamily="@font/roboto_light"
android:lineSpacingExtra="3dp"
android:maxLines="2"
android:text=""
android:textColor="#676768"
android:textSize="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_usericon" />
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
</RelativeLayout>
总结:在我遇到的问题里 实际有效的解决方案是在adapter里重写getItemViewType方法
@Override
public int getItemViewType(int position) {
return position;
}