Linkage-RecyclerView 是一款基于 MVP 架构开发的二级联动列表控件。它是因 “RxJava 魔法师” 这个项目的需求而存在。
在最初寻遍了 GitHub 也没有找到合适的开源库(高度解耦、可远程依赖)之后,我决心研究参考现有开源项目关于二级联动的逻辑,并自己动手编写一个 高度解耦、轻松配置、可通过 maven 仓库远程依赖 的真正的第三方库。
Linkage-RecyclerView 的个性化配置十分简单,依托于 MVP 的 “配置解耦” 特性,使用者无需知道内部的实现细节,仅通过实现 Config 类即可完成功能的定制和扩展。
此外,在不设置自定义配置的情况下,Linkage-RecyclerView 最少只需 一行代码即可运行起来。
RxMagic | Eleme Linear | Eleme Grid |
---|---|---|
Linkage-RecyclerView 的目标是:一行代码即可接入二级联动列表。
除了一键接入而省去 99% 不必要的、复杂的、重复的工作外,你还可以从这个开源项目获得的内容包括:
如果你正在思考 如何为项目挑选合适的架构 的话,这个项目值得你参考!
1.在 build.gradle 中添加对该库的依赖。
implementation 'com.kunminx.linkage:linkage-recyclerview:1.3.5'
2.依据默认的分组实体类 DefaultGroupedItem
的结构准备一串数据(以下以 JSON 为例)。
// DefaultGroupedItem.ItemInfo 包含三个字段: String title //(必填)二级选项的标题 String group //(必填)二级选项所在分组的名称,要和对应的一级选项的标题相同 String content //(选填)二级选项的内容
[ { "header": "优惠", "isHeader": true }, { "isHeader": false, "info": { "content": "好吃的食物,增肥神器,有求必应", "group": "优惠", "title": "全家桶" } }, { "header": "热卖", "isHeader": true }, { "isHeader": false, "info": { "content": "爆款热卖,月销超过 999 件", "group": "热卖", "title": "烤全翅" } } ]
3.在布局中引入 LinkageRecyclerView 。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.kunminx.linkage.LinkageRecyclerView android:id="@+id/linkage" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
4.在得到数据后,最少只需一行代码即可完成初始化。
List<DefaultGroupedItem> items = gson.fromJson(...); //一行代码完成初始化 linkage.init(items);
注意:如使用 JSON,请在 ProGuard Rules 中为该实体类配置混淆白名单:
-keep class com.kunminx.linkage.bean.** {*;}
该库为一级和二级 Adapter 分别准备了 Config 接口(ILevelPrimaryAdapterConfig
和 ILevelSecondaryAdapterConfig
),自定义配置时,即是去实现这两个接口,来取代默认的配置。
之所以设置成接口的形式,而非 Builder 的形式,是因为二级联动列表内部的联动逻辑需要指明关键的控件。接口相比 Builder 具有强制性,能够让使用者一目了然必须配置的内容,故而采用接口,通过 MVP 架构的方式来编写该库。
关于个性化配置,具体可以参考我在 ElemeGroupedItem
和 SwitchSampleFragment
中编写的案例:
你需要根据需求,在 BaseGroupedItem
的基础上扩展分组实体类,具体的办法是,编写一个实体类,该实体类须继承于 BaseGroupedItem
;该实体类的内部类 ItemInfo
也须继承于 BaseGroupedItem.ItemInfo
。
以 Eleme 分组实体类为例,扩充 content
、imgUrl
、cost
三个字段:
public class ElemeGroupedItem extends BaseGroupedItem<ElemeGroupedItem.ItemInfo> { public ElemeGroupedItem(boolean isHeader, String header) { super(isHeader, header); } public ElemeGroupedItem(ItemInfo item) { super(item); } public static class ItemInfo extends BaseGroupedItem.ItemInfo { private String content; private String imgUrl; private String cost; public ItemInfo(String title, String group, String content) { super(title, group); this.content = content; } public ItemInfo(String title, String group, String content, String imgUrl) { this(title, group, content); this.imgUrl = imgUrl; } public ItemInfo(String title, String group, String content, String imgUrl, String cost) { this(title, group, content, imgUrl); this.cost = cost; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getImgUrl() { return imgUrl; } public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; } public String getCost() { return cost; } public void setCost(String cost) { this.cost = cost; } } }
注意:如使用 JSON,请在 ProGuard Rules 中为该实体类配置混淆白名单。
在装载数据和实现自定义配置时,泛型框中须指明你编写的实体类,注意 List<ElemeLinkageItem>
,以及 new ILevelSecondaryAdapterConfig<ElemeLinkageItem.ItemInfo>()
这两处。
private void initLinkageDatas(LinkageRecyclerView linkage) { Gson gson = new Gson(); List<ElemeGroupedItem> items = gson.fromJson(...); linkage.init(items, new ILevelPrimaryAdapterConfig() { private Context mContext; public void setContext(Context context) { mContext = context; } @Override public int getLayoutId() { return R.layout.default_adapter_linkage_level_primary; } @Override public int getTextViewId() { return R.id.tv_group; } @Override public int getRootViewId() { return R.id.layout_group; } @Override public void onBindViewHolder( LinkageLevelPrimaryAdapter.LevelPrimaryViewHolder holder, String title, int position) { holder.getView(R.id.layout_group).setOnClickListener(v -> { //TODO }); } @Override public void onItemSelected(boolean selected, TextView itemView) { itemView.setBackgroundColor(mContext.getResources().getColor(selected ? com.kunminx.linkage.R.color.colorLightBlue : com.kunminx.linkage.R.color.colorWhite)); itemView.setTextColor(ContextCompat.getColor(mContext, selected ? com.kunminx.linkage.R.color.colorWhite : com.kunminx.linkage.R.color.colorGray)); } }, new ILevelSecondaryAdapterConfig<ElemeGroupedItem.ItemInfo>() { private Context mContext; private boolean mIsGridMode; public void setContext(Context context) { mContext = context; } @Override public int getGridLayoutId() { return R.layout.adapter_eleme_secondary_grid; } @Override public int getLinearLayoutId() { return R.layout.adapter_eleme_secondary_linear; } @Override public int getHeaderLayoutId() { return R.layout.default_adapter_linkage_level_secondary_header; } @Override public int getTextViewId() { return R.id.iv_goods_name; } @Override public int getRootViewId() { return R.id.iv_goods_item; } @Override public int getHeaderViewId() { return R.id.level_2_header; } @Override public boolean isGridMode() { return mIsGridMode; } @Override public void setGridMode(boolean isGridMode) { mIsGridMode = isGridMode; } @Override public int getSpanCount() { return 2; } @Override public void onBindViewHolder( LinkageLevelSecondaryAdapter.LevelSecondaryViewHolder holder, BaseGroupedItem<ElemeGroupedItem.ItemInfo> item, int position) { ((TextView) holder.getView(R.id.iv_goods_name)) .setText(item.info.getTitle()); Glide.with(mContext).load(item.info.getImgUrl()) .into((ImageView) holder.getView(R.id.iv_goods_img)); holder.getView(R.id.iv_goods_item).setOnClickListener(v -> { //TODO }); holder.getView(R.id.iv_goods_add).setOnClickListener(v -> { //TODO }); } }); }
当前版本 1.9.2 项目地址 概述 自定义LinkageRecyclerView控件,该控件布局中含有两个RecyclerView控件,左边为主Rv,右边为次Rv. 次Rv顶部有一个悬挂头View,该View专门用来展示次Rv中每个分组的组名称. 监听次Rv的滑动事件,根据屏幕中展示的次Rv中的第一条目索引的改变来判断当前组名称时候有更改,如果有更改组名称就拿到该组名称在原始数据中的索引位置,进
目录介绍 1.复杂页面库介绍 2.本库优势亮点 2.1 支持多种状态切换管理 2.2 支持添加多个header和footer 2.3 支持侧滑功能和拖拽移动 2.4 其他亮点介绍 3.如何使用介绍 3.1 最基础的使用 3.2 添加下拉刷新和加载更多监听 3.3 添加header和footer操作 3.4 设置数据和刷新 3.5 设置adapter 3.6 设置条目点击事件 3.7 设置侧滑删除功
本文向大家介绍JavaScript实现常用二级省市级联下拉列表的方法,包括了JavaScript实现常用二级省市级联下拉列表的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript实现常用二级省市级联下拉列表的方法。分享给大家供大家参考。具体分析如下: 这里省和市的名称都是动态填充,选择省后自动填充城市 希望本文所述对大家的javascript程序设计有所帮助。
Linkage是一款采用C++和GTK+撰写的BT客户端软件,利用libtorrent库实现P2P,并且支持DHT、PEX、UPnP设备、桌面提醒和制作种子等实用功能。
本文向大家介绍android-wheel控件实现三级联动效果,包括了android-wheel控件实现三级联动效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了android wheel省市县三级联动效果,供大家参考,具体内容如下 在github上面有一个叫做 Android-wheel 的开源控件, 代码地址:https://github.com/maarek/android-w
本文向大家介绍javascript实现简单的二级联动,包括了javascript实现简单的二级联动的使用技巧和注意事项,需要的朋友参考一下 二级联动在一般的网页中随处可见,一般是地址,比如点击浙江省,随后出现的是杭州市,嘉兴市;点击北京省出现的是朝阳,海淀,而不是出现杭州,嘉兴。 要想实现这个步骤,就要用到javascript来实现。其中原理用到onchange时间。 首先,onchange 事件
本文向大家介绍jQuery实现多级联动下拉列表查询框,包括了jQuery实现多级联动下拉列表查询框的使用技巧和注意事项,需要的朋友参考一下 本文实例介绍了jQuery实现多级联动下拉列表查询框的详细代码,分享给大家供大家参考,具体内容如下 效果图: 具体代码: 希望本文所述对大家学习jquery程序设计有所帮助。
本文向大家介绍JavaScript实现的级联算法示例【省市二级联动功能】,包括了JavaScript实现的级联算法示例【省市二级联动功能】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript实现的级联算法。分享给大家供大家参考,具体如下: 使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试