recyclerview横向滑动间距_打造一个有不同 Item 布局的 RecyclerView

本文通过实例演示如何利用RecyclerView实现一个包含不同Item布局的列表,包括横向滑动的Header,内容涵盖列表对象创建、样式设计、Adapter实现及效果展示。提供了完整的源码和Demo下载链接。
摘要由CSDN通过智能技术生成

RecyclerView 作为 ListView 的升级版,其强大的性能和极高的灵活性使得可以在项目中实现更多的列表效果,比如瀑布流、自定义 Header 和 Footer 、不同内容的 Item 布局等,今天就利用 RecyclerView 来实现一个根据内容变化 Item 布局的列表布局,并添加一个横向滑动的列表作为 Header 。用到的主要是 RecyclerView.Adapter 中关于 View Type 的一些设定。

前期准备

首先我们先新建一个类 ListItem 作为存放列表内容的对象。

ListItem.class

12345678910111213
public class ListItem {    int type;       // Item 的类型    String title;   // Item 的标题    String brief;   // Item 的简介    String image;   // Item 的图片    public ListItem(int type, String title, String brief, String image) {        this.type = type;        this.title = title;        this.brief = brief;        this.image = image;    }}

列表样式设计

这里我设计了 5 个不同的样式:列表的头部、仅有文字的列表项目、带有小图片的列表项目、带有大图片的列表项目和列表的尾部。
列表的头部的是常见的左右滚动形式,其他几个部分则是简单的 Card ,最后列表的尾部为一行文字。

dacd8cc0fb8780f67e9a9e53ef9ba566.png

为了不贴出太多代码,影响阅读体验,这里就放出头部的和仅有文字的列表项目的 XML 文件,其他的文件会在项目的 GitHub Repo 中放出。

item_list_header.xml

这里使用一个 HorizontalScrollView 包裹一个 LinearLayout 实现横向滚动效果,实际使用时可以用一个横向的 RecyclerView 替代。

1234567891011121314151617181920212223242526272829303132
<?xml version="1.0" encoding="utf-8"?>    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:scrollbars="none">            android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="horizontal"        android:scrollbars="none">                    android:layout_width="wrap_content"            android:layout_height="200dp"            android:layout_marginVertical="16dp"            android:layout_marginStart="16dp">             android:id="@+id/header_image_1" android:layout_width="300dp" android:layout_height="200dp" android:contentDescription="@string/image_description"/>         ... ...    

item_text_only.xml

简单的一个 CardView 。

1234567891011121314151617181920212223242526272829303132333435
<?xml version="1.0" encoding="utf-8"?>    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="16dp">            android:layout_width="match_parent"        android:layout_height="wrap_content">                    android:id="@+id/item_title"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_margin="16dp"            android:textSize="20sp"            app:layout_constraintStart_toStartOf="parent"            app:layout_constraintTop_toTopOf="parent" />         android:id="@+id/item_brief" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginBottom="16dp" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/item_title" /> 

创建 Adapter

ListAdapter.java

这里大体跟一般使用 RecyclerView.Adapter 一样,但是重写了 getItemViewType() 方法,根据 position 返回不同的 Type ,getItemCount() 的返回值也从一般的列表 Size 变成了 Size + 2 ,因为多了头部和尾部两个项目。其他的一些改动请看代码,部分重复或无关代码已省略。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
public class ListAdapter extends RecyclerView.Adapter {    ... ...    public ListAdapter(Context context, List mData) {        this.mContext = context;        this.mData = mData;    }    @Override    public int getItemViewType(int position) {        // 根据位置和内容判断布局类型        if (position == 0) {            return TYPE_HEADER;        } else if (position == getItemCount() - 1) {            return TYPE_FOOTER;        } else {            return mData.get(position - 1).type;        }    }    @NonNull    @Override    public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        // 应用不同布局        switch (viewType) {            case TYPE_HEADER:                return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(                        R.layout.item_list_header, parent, false), viewType);            case TYPE_NO_IMAGE:                return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(                        R.layout.item_text_only, parent, false), viewType);            case TYPE_SMALL_IMAGE:                return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(                        R.layout.item_text_with_small_image, parent, false), viewType);            case TYPE_BIG_IMAGE:                return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(                        R.layout.item_text_with_big_image, parent, false), viewType);            default:                return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(                        R.layout.item_list_footer, parent, false), viewType);        }    }    @Override    public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {        //  根据类型对内容进行设置        if (holder.type == TYPE_HEADER) {            String imgURL1 = "file:///android_asset/1.jpg";            Glide.with(mContext)                    .load(imgURL1)                    .centerCrop()                    .into(holder.headerImage1);            ... ...        } else if (holder.type != TYPE_FOOTER) {            holder.textTitle.setText(mData.get(position - 1).title);            holder.textBrief.setText(mData.get(position - 1).brief);            if (holder.type == 2 || holder.type == 3) {                // 简单的图片加载                String imgURL = "file:///android_asset/" + mData.get(position - 1).image + ".jpg";                Glide.with(mContext)                        .load(imgURL)                        .centerCrop()                        .into(holder.imageView);            }        }    }    @Override    public int getItemCount() {        // 计算头部和尾部项目        return mData.size() + 2;    }    static class ItemViewHolder extends RecyclerView.ViewHolder {        int type;        ImageView headerImage1, headerImage2, headerImage3;        TextView textTitle, textBrief;        ImageView imageView;        public ItemViewHolder(@NonNull View itemView, int viewType) {            super(itemView);            this.type = viewType;            textTitle = itemView.findViewById(R.id.item_title);            textBrief = itemView.findViewById(R.id.item_brief);            // 根据不同布局设置界面元素            if (viewType == 0) {                headerImage1 = itemView.findViewById(R.id.header_image_1);                headerImage2 = itemView.findViewById(R.id.header_image_2);                headerImage3 = itemView.findViewById(R.id.header_image_3);            }            if (viewType == 2 || viewType == 3) {                imageView = itemView.findViewById(R.id.item_image);            }        }    }}

实装 RecyclerView

这部分就是给 RecyclerView 设置刚刚完成的 Adapter ,然后填上对应的内容,至此,整个列表就完成了。

123456789101112131415161718192021
public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Toolbar toolbar = findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        // 设置列表内容        List listItems = new ArrayList<>();        listItems.add(new ListItem(1, "标题1", "简介1", "1"));        listItems.add(new ListItem(2, "标题2", "简介2", "2"));        listItems.add(new ListItem(3, "标题3", "简介3", "3"));        // 设置 RecyclerView        RecyclerView recyclerView = findViewById(R.id.recycler_view);        recyclerView.setLayoutManager(new LinearLayoutManager(this));        recyclerView.setAdapter(new ListAdapter(this, listItems));    }}

效果展示

就是上面那个图片啦,我是做出来才截图的。

源码以及 Demo

微信现在无法设置其他网站的超链接,只能设置跟公众号文章相关的,所以就复制一下去浏览器打开啦。

整个过程的源码已经上传到 GitHub ,项目地址:

https://github.com/xMuu/RecyclerViewDemo 

如果想试试整个 App 的效果可以到这里下载体验。(https://github.com/xMuu/RecyclerViewDemo/releases) 

如有错误或瑕疵,欢迎提出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值