RecyclerView 布局管理器操作

RecyclerView Layout Manager Manipulation

我有一个回收站视图,它应该显示如下数据(如果位置是偶数,则显示 1 个项目;如果位置是奇数,则 2 个项目并排显示),老实说,我试了又试,但我没有这样做。

它应该是这样的

现在是这样的(忽略宽高,看视频3膨胀了两次)

我正在使用 LinearLayoutManager,这是我的适配器:

public class MediaItemsAdapter extends RecyclerView.Adapter<MediaItemsAdapter.RecyclerViewHolder> {

private List<MediaItem> allMediaItems;
private Activity context;
private RecyclerViewOnItemClickListener itemClickListener;

public MediaItemsAdapter(Activity context, List<MediaItem> allMediaItems, RecyclerViewOnItemClickListener itemClickListener ) {

    this.allMediaItems = allMediaItems;
    this.context = context;
    this.itemClickListener = itemClickListener;
}

@Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position) {

    MediaItem mediaItem = allMediaItems.get(position);

    if(position %2 == 0){ // even

        holder.tvTitle.setText(mediaItem.getTitle());
        holder.tvSummary.setText(mediaItem.getDate());

        try {
            Picasso.with(context)
                    .load(mediaItem.getImageUrl())
                    .into(holder.ivImage, new com.squareup.picasso.Callback() {
                        @Override
                        public void onSuccess() {
                            holder.ivImage.setAlpha((float) 1);
                        }

                        @Override
                        public void onError() {
                            Log.wtf("error", "in loading");
                        }
                    });

        } catch (Exception e) {
            e.printStackTrace();
        }

        holder.ivPlay.setVisibility(mediaItem.isVideo() ? View.VISIBLE : View.GONE);
    }else{ //odd

        holder.tvTitle.setText(mediaItem.getTitle());
        holder.tvSummary.setText(mediaItem.getDate());

        try {
            Picasso.with(context)
                    .load(mediaItem.getImageUrl())
                    .into(holder.ivImage, new com.squareup.picasso.Callback() {
                        @Override
                        public void onSuccess() {
                            holder.ivImage.setAlpha((float) 1);
                        }

                        @Override
                        public void onError() {
                            Log.wtf("error", "in loading");
                        }
                    });

        } catch (Exception e) {
            e.printStackTrace();
        }

        holder.ivPlay.setVisibility(mediaItem.isVideo() ? View.VISIBLE : View.GONE);

        try{

            MediaItem secondMediaItem = allMediaItems.get(position + 1);
            holder.tvSecondTitle.setText(secondMediaItem.getTitle());
            holder.tvSecondSummary.setText(secondMediaItem.getDate());

            try {
                Picasso.with(context)
                        .load(secondMediaItem.getImageUrl())
                        .into(holder.ivSecondImage, new com.squareup.picasso.Callback() {
                            @Override
                            public void onSuccess() {
                                holder.ivSecondImage.setAlpha((float) 1);
                            }

                            @Override
                            public void onError() {
                                Log.wtf("error", "in loading");
                            }
                        });

            } catch (Exception e) {
                e.printStackTrace();
            }

            holder.ivSecondPlay.setVisibility(secondMediaItem.isVideo() ? View.VISIBLE : View.GONE);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

@Override
public int getItemViewType(int position) {
    return position %2 == 0 ? 0 : 1;
}

@Override
public int getItemCount() {
    return this.allMediaItems.size();
}


public interface RecyclerViewOnItemClickListener {
    void onItemClicked(View v, int position);
}

public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View layoutView;

    if (viewType == 0 ){

        layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.even_media_layout, parent, false);
        RecyclerViewHolder rcv = new RecyclerViewHolder(layoutView);
        return (rcv);
    }else{

        layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.odd_media_layout, parent, false);
        RecyclerViewHolder rcv = new RecyclerViewHolder(layoutView);
        return (rcv);
    }
}

public class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private TextView tvTitle, tvSecondTitle, tvSummary, tvSecondSummary;
    private ImageView ivImage, ivSecondImage;
    private ImageButton ivPlay, ivSecondPlay;

    protected View itemView;

    public RecyclerViewHolder(View itemView) {
        super(itemView);
        this.itemView = itemView;
        this.itemView.setOnClickListener(this);

        tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
        tvSecondTitle = (TextView) itemView.findViewById(R.id.tvSecondTitle);
        tvSummary = (TextView) itemView.findViewById(R.id.tvSummary);
        tvSecondSummary = (TextView) itemView.findViewById(R.id.tvSecondSummary);

        ivImage = (ImageView) itemView.findViewById(R.id.ivImage);
        ivSecondImage = (ImageView) itemView.findViewById(R.id.ivSecondImage);

        ivPlay = (ImageButton) itemView.findViewById(R.id.ivPlay);
        ivSecondPlay = (ImageButton) itemView.findViewById(R.id.ivSecondPlay);
    }

    @Override
    public void onClick(View view) {
        itemClickListener.onItemClicked(view, getLayoutPosition());
    }
}
}

如何防止数据复制,如何告诉数组列表对象3已经膨胀了?有没有比 LinearLayoutManager

更好的方法

此致。

你的计算有误

return position %2 == 0 ? 0 : 1;

看到这个

|0|
1|2
|3|
4|5
|6|
7|8

如果你仔细观察项目的出现,3的倍数的项目是全宽的。

所以基本上你的计算应该是这样的

return position % 3 == 0 ? 0 : 1;

稍微解释一下,偶数行有两个项目,但您计算的是偶数个项目。

也更正这部分代码

@Override
public void onBindViewHolder(final RecyclerViewHolder holder, int position) {

    final int adapterPosition = holder.getAdapterPosition();
    MediaItem mediaItem = allMediaItems.get(adapterPosition);

    if(adapterPoaition % 3 == 0){ // every third item
       //your codes
    }
    //remaining codes
}

首先你应该使用适配器位置而不是作为参数传递的视图位置。接下来你也必须在这里使用第三个位置而不是第二个

P.S. your adapter code is bit messed up, not sure whether correcting this calculation will give you correct results or not until you do little code cleanup.

我建议你使用Adapter delegates,显然你可以不用它,但它会帮助你进一步开发。

Here你可以看看

您应该创建 2 个代表,然后根据提供的条件 isForViewType() return 布尔值 return position % 2 == 1onCreateViewHolder() return 相关的 ViewHolder(您将有 2)

使用 GridLayoutManage 到您的 RecyclerView 并像这样设置跨度大小查找。

    GridLayoutManager glm = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
    glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup(){

        @Override
        public int getSpanSize(int position) {
            return position % 3 == 0 ? 2 : 1;
        }
    });