RecyclerView–不同布局的item实现

RecyclerView–不同布局的item实现

RecyclerView相信大部分人都用过,这篇就是讲一下RecyclerView的一些简单的使用技巧,本篇简单易懂,读者可以在此基础上封装扩展,话不多说,我们来看最终的效果图。

布局一:图片+歌曲名字+歌手

RecyclerView_1
布局1
<android.support.v7.widget.CardView
    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:layout_margin="5dp"
    android:orientation="vertical"
    app:cardCornerRadius="5dp">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <View
            android:id="@+id/v_playing"
            android:layout_width="3dp"
            android:layout_height="50dp"
            android:layout_marginRight="3dp"
            android:background="@color/com"
            android:contentDescription="@null"
            android:visibility="invisible"/>

        <ImageView
            android:id="@+id/item_iv_cover"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginLeft="10dp"
            android:scaleType="fitXY"
            android:src="@drawable/default_cover"/>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:layout_marginLeft="10dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <LinearLayout
                    android:id="@+id/item_play"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/item_tv_title"
                        style="@style/AppTheme.Text"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:ellipsize="end"
                        android:singleLine="true"
                        android:text="歌曲"
                        android:textSize="16sp"/>

                    <TextView
                        android:id="@+id/item_tv_artist"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="5dp"
                        android:ellipsize="end"
                        android:singleLine="true"
                        android:text="歌手 - 专辑"
                        android:textColor="@color/grey"
                        android:textSize="12sp"/>
                </LinearLayout>

                <ImageView
                    android:id="@+id/item_iv_more"
                    android:layout_width="50dp"
                    android:layout_height="match_parent"
                    android:background="@drawable/music_list_more_bg_selector"
                    android:contentDescription="@null"
                    android:padding="18dp"
                    android:scaleType="centerInside"
                    android:src="@drawable/ic_music_list_icon_more"/>
            </LinearLayout>

            <View
                android:id="@+id/v_divider"
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:layout_gravity="bottom"
                android:background="?android:attr/listDivider"/>
        </FrameLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>

布局二 图片+文字:

布局2
<android.support.v7.widget.CardView
    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:layout_margin="5dp"
    android:orientation="vertical"
    app:cardCornerRadius="5dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/more_music_img"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:scaleType="centerCrop"
            />

        <TextView
            android:id="@+id/more_music_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="@color/trangery"
            android:gravity="center_vertical"
            android:padding="5dp"
            android:textColor="@color/white"
            android:textSize="15sp"
            />

    </RelativeLayout>
</android.support.v7.widget.CardView>

下面我们来思考怎么实现Adapter。在Adapter中:

@Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

通过此方法可以获取对应position的item的布局类型,因此,我们根据自己的需求分析,我们的需求是

  1. position 0\1\2:布局二
  2. position 3\4\5 :布局一

之后布局进行循环,因此我们可以根据position取模6:

@Override
    public int getItemViewType(int position) {

        return (position % 6);
    }

之后在onCreateViewHolder中根据返回的viewType创建我们需要的ViewHolder。

@NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         switch (viewType) {
            case 0:
            case 1:
            case 2:
                return new ViewHolderType1(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_more_item1, parent, false));
            case 3:
            case 4:
            case 5:
                return new MusicListAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_list_item, parent, false));

        }
        return new MusicListAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_list_item, parent, false));
    }

ViewHolder1

static class ViewHolderType1 extends RecyclerView.ViewHolder {
        ImageView mImageView;
        TextView mTextView;

        public ViewHolderType1(View itemView) {
            super(itemView);
            mImageView = itemView.findViewById(R.id.more_music_img);
            mTextView = itemView.findViewById(R.id.more_music_title);
        }
    }

其中MusicListAdapter.ViewHolder就不再贴出,和ViewHolder1实现同理。
最后在对holder进行类型的判断,对不同的holder类型进行相应的绑定。

@Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean songlistBean = mSonglistBeans.get(position);
        if (holder instanceof ViewHolderType1) {
            GlideApp.with(mContext)
                    .load(songlistBean.getAlbumpic_big())
                    .placeholder(R.drawable.default_cover)
                    .error(R.drawable.default_cover)
                    .into(((ViewHolderType1) holder).mImageView);
            ((ViewHolderType1) holder).mImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
            ((ViewHolderType1) holder).mTextView.setText(songlistBean.getSongname() + " - " + songlistBean.getSingername());
        } else if (holder instanceof MusicListAdapter.ViewHolder) {
            GlideApp.with(mContext)
                    .load(songlistBean.getAlbumpic_small())
                    .placeholder(R.drawable.default_cover)
                    .error(R.drawable.default_cover)
                    .into(((MusicListAdapter.ViewHolder) holder).mImageView);
            ((MusicListAdapter.ViewHolder) holder).title.setText(songlistBean.getSongname());
            ((MusicListAdapter.ViewHolder) holder).author.setText(songlistBean.getSongname() + " - " + songlistBean.getSingername());
            ((MusicListAdapter.ViewHolder) holder).mLinearLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
            ((MusicListAdapter.ViewHolder) holder).more.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
        }
    }

现在我们已经可以根据position来实现不同的item布局了,小节一下就是:
1.在getItemViewType中返回布局类型;
2.在onCreateViewHolder中根据返回的布局类型创建相应的ViewHolder;
3.在onBindViewHolder中根据ViewHolder的类型进项布局的绑定
此时,我们已经实现了一半的功能了。我们看到position 1和2在一行上,与其他行列数不同,我们怎么实现呐?相信你也想到了,使用GridLayoutManager。

mRecyclerView.setLayoutManager(new GridLayoutManager(mRecyclerView.getContext(), 6, GridLayoutManager.VERTICAL, false));

我们在onAttachedToRecyclerView根据item类型分配不同的列数,进而实现最终效果。

 @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            GridLayoutManager layoutManager = (GridLayoutManager) manager;
            layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int type = getItemViewType(position);
                    switch (type) {
                        case 0:
                        case 3:
                        case 4:
                        case 5:
                            return 6;
                        case 2:
                        case 1:
                            return 3;
                        default:
                            return 6;
                    }

                }
            });
        }
    }

方法中返回6,就是独占一行,返回3就是占一半。
完整的Adapter代码如下:

public class MoreListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    List<OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean> mSonglistBeans = new ArrayList<OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean>();
    Context mContext;

    public MoreListAdapter(List<OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean> list, Context context) {
        mSonglistBeans = list;
        mContext = context;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        switch (viewType) {
            case 0:
            case 1:
            case 2:
                return new ViewHolderType1(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_more_item1, parent, false));
            case 3:
            case 4:
            case 5:
                return new MusicListAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_list_item, parent, false));

        }
        return new MusicListAdapter.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.music_list_item, parent, false));
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean songlistBean = mSonglistBeans.get(position);
        if (holder instanceof ViewHolderType1) {
            GlideApp.with(mContext)
                    .load(songlistBean.getAlbumpic_big())
                    .placeholder(R.drawable.default_cover)
                    .error(R.drawable.default_cover)
                    .into(((ViewHolderType1) holder).mImageView);
            ((ViewHolderType1) holder).mImageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
            ((ViewHolderType1) holder).mTextView.setText(songlistBean.getSongname() + " - " + songlistBean.getSingername());
        } else if (holder instanceof MusicListAdapter.ViewHolder) {
            GlideApp.with(mContext)
                    .load(songlistBean.getAlbumpic_small())
                    .placeholder(R.drawable.default_cover)
                    .error(R.drawable.default_cover)
                    .into(((MusicListAdapter.ViewHolder) holder).mImageView);
            ((MusicListAdapter.ViewHolder) holder).title.setText(songlistBean.getSongname());
            ((MusicListAdapter.ViewHolder) holder).author.setText(songlistBean.getSongname() + " - " + songlistBean.getSingername());
            ((MusicListAdapter.ViewHolder) holder).mLinearLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
            ((MusicListAdapter.ViewHolder) holder).more.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
        }
    }

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

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            GridLayoutManager layoutManager = (GridLayoutManager) manager;
            layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int type = getItemViewType(position);
                    switch (type) {
                        case 0:
                        case 3:
                        case 4:
                        case 5:
                            return 6;
                        case 2:
                        case 1:
                            return 3;
                        default:
                            return 6;
                    }

                }
            });
        }
    }

    @Override
    public int getItemViewType(int position) {

        return (position % 6);
    }

    static class ViewHolderType1 extends RecyclerView.ViewHolder {
        ImageView mImageView;
        TextView mTextView;

        public ViewHolderType1(View itemView) {
            super(itemView);
            mImageView = itemView.findViewById(R.id.more_music_img);
            mTextView = itemView.findViewById(R.id.more_music_title);
        }
    }
    /*MusicListAdapter.ViewHolder 在其他类中已经定义*/

}

在Activity/Fragment中使用:

public class MoreMusicFragment extends Fragment {

    private RecyclerView mRecyclerView;
    private MoreListAdapter mMoreListAdapter;
    private Context mContext;
    private List<OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean> mOnlineMusicList=new ArrayList<OnlineMusic.ShowapiResBodyBean.PagebeanBean.SonglistBean>();
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_more_music, container, false);
        mContext= MainActivity.sMainActivity;
        mRecyclerView=view.findViewById(R.id.fg_more_list);
        mMoreListAdapter=new MoreListAdapter(mOnlineMusicList,mContext);
        initView();
        intitData();
        return view;
    }

    private void initView(){
        mRecyclerView.setLayoutManager(new GridLayoutManager(mRecyclerView.getContext(), 6, GridLayoutManager.VERTICAL, false));
        mRecyclerView.setAdapter(mMoreListAdapter);
    }
    private void intitData(){
        //设置数据

    }

}