{"id":13642779,"url":"https://github.com/AlphaBoom/ClassifyView","last_synced_at":"2025-04-20T21:31:27.646Z","repository":{"id":156042973,"uuid":"99575743","full_name":"AlphaBoom/ClassifyView","owner":"AlphaBoom","description":"No longer maintained","archived":false,"fork":false,"pushed_at":"2019-06-21T17:28:32.000Z","size":20009,"stargazers_count":236,"open_issues_count":3,"forks_count":57,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-11-09T14:39:00.984Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlphaBoom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-08-07T12:30:58.000Z","updated_at":"2024-10-29T12:44:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"f6ef2149-9c0f-4184-93b7-a7f52c3b3a74","html_url":"https://github.com/AlphaBoom/ClassifyView","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaBoom%2FClassifyView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaBoom%2FClassifyView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaBoom%2FClassifyView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaBoom%2FClassifyView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlphaBoom","download_url":"https://codeload.github.com/AlphaBoom/ClassifyView/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249965468,"owners_count":21352904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:01:36.115Z","updated_at":"2025-04-20T21:31:27.197Z","avatar_url":"https://github.com/AlphaBoom.png","language":"Java","readme":"# ClassifyView [![](https://jitpack.io/v/AlphaBoom/ClassifyView.svg)](https://jitpack.io/#AlphaBoom/ClassifyView)[![Codewake](https://www.codewake.com/badges/ask_question.svg)](https://www.codewake.com/p/classifyview)\n实现原理 ClassifyView包裹这一个RecyclerView，当点击这个RecyclerView会弹出一个Dialog 该Dialog的布局会传入另一个RecyclerView.想详细了解，~可以查看 [博客](http://www.jianshu.com/p/a51a93366406)~\n# 效果如下\n![image](https://github.com/AlphaBoom/ClassifyView/blob/master/screenshot/classifyView.gif)\n![image](https://github.com/AlphaBoom/ClassifyView/blob/master/screenshot/ireader.gif)\n# 配置依赖\n**Step one:** Add the JitPack repository to your build file\n\n```\nallprojects {\n\t\trepositories {\n\t\t\t...\n\t\t\tmaven { url \"https://jitpack.io\" }\n\t\t}\n\t  }\n```\n**Step two:** Add the dependency\n\n```\n    dependencies {\n\t        compile 'com.github.AlphaBoom:ClassifyView:$LATEST_VERSION'\n\t}\n\n```\n最新版本查看[Latest release](https://github.com/AlphaBoom/ClassifyView/releases)\n\n# 最近更新\n- [x] 关于仿照IReader的效果需要对原库做自定义的部分都已经更新在Sample\n- [x] 在adapter中增加了拖拽开始及拖拽开始完成和次级目录弹出的回调\n- [x] 增加拖拽item的可在拖拽时放大及可合并时缩小的设置\n- [x] 在拖拽开始时添加动画，效果更自然\n- [x] 添加了一个自定义的例子，效果大致仿IReader的书架\n\n# 快速使用\n1. 继承SimpleAdapter\n\n```java\n   public class MyAdapter extends SimpleAdapter\u003cBean, MyAdapter.ViewHolder\u003e {\n\n\n    public MyAdapter(List\u003cList\u003cBean\u003e\u003e mData) {\n        super(mData);\n    }\n\n\n    @Override\n    protected ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);\n        return new MyAdapter.ViewHolder(view);\n    }\n    //convertView是缓存的View  如何使用这个convertView 参考ListView的使用步骤\n    @Override\n    public View getView(ViewGroup parent, View convertView, int mainPosition, int subPosition) {\n    //返回的View作为每一个Item的布局\n    /*布局内容自定义 例子中如下：\n    \u003cView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      android:layout_width=\"match_parent\"\n      android:layout_height=\"match_parent\"\n      android:background=\"@drawable/round_shape\"/\u003e\n    */\n       if (convertView == null) {\n            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_inner, parent, false);\n        }\n        return convertView;\n    }\n\n    @Override\n    protected void onItemClick(View view, int parentIndex, int index) {\n        Toast.makeText(view.getContext(),\"parentIndex: \"+parentIndex+\"\\nindex: \"+index,Toast.LENGTH_SHORT).show();\n    }\n\n    static class ViewHolder extends SimpleAdapter.ViewHolder {\n\n        public ViewHolder(View itemView) {\n            super(itemView);\n        }\n    }\n}\n``` \n2.找到ClassifyView 并设置Adapter\n\n```java\nmClassifyView = (ClassifyView) view.findViewById(R.id.classify_view);\nList\u003cList\u003cBean\u003e\u003e data = new ArrayList\u003c\u003e();\nfor(int i=0;i\u003c30;i++){\n    List\u003cBean\u003e inner = new ArrayList\u003c\u003e();\n        if(i\u003e10) {\n            int c = (int) (Math.random() * 15+1);\n            for(int j=0;j\u003cc;j++){\n                inner.add(new Bean());\n            }\n        }else {\n            inner.add(new Bean());\n        }\n        data.add(inner);\n    }\nmClassifyView.setAdapter(new MyAdapter(data));\n```\n# 添加拖动状态监听\n\n设置监听\n```java\n//添加监听\nClassifyView#addDragListener(DragListener)\n//移除监听    \nClassifyView#removeDragListener(DragListener)\n//移除所有监听\nClassifyView#removeAllDragListener()\n/**\n * 是否监听移动状态信息\n * @param enable false disable true enable default true\n */\nClassifyView#enableMoveListener(boolean)   \n```\n具体监听回调\n\n```java\npublic interface DragListener {\n        /**\n         * 开始拖拽\n         *\n         * @param parent parent is ClassifyView\n         * @param startX start touch x relative classify view\n         * @param startY start touch y relative classify view\n         * @param region start drag  region either  main or sub\n         */\n        void onDragStart(ViewGroup parent,View selectedView, float startX, float startY,@Region int region);\n\n        /**\n         * star drag animation end\n         * @param parent\n         * @param selectedView\n         * @param region\n         */\n        void onDragStartAnimationEnd(ViewGroup parent,View selectedView,int region);\n\n        /**\n         * 拖拽结束(recover animation end)\n         */\n        void onDragEnd(ViewGroup parent,@Region int region);\n\n        /**\n         * 释放被拖拽的View\n         */\n        void onDragRelease(ViewGroup parent, float releaseX, float releaseY,@Region int region);\n\n        /**\n         * move callback by touch location\n         *\n         * @param touchX 触摸的X坐标\n         * @param touchY 触摸的Y坐标\n         */\n        void onMove(ViewGroup parent, float touchX, float touchY,@Region int region);\n    }\n```\n\n# 支持的自定义的属性\nClassifyView attr\n\n属性  | 说明\n------------- | -------------\nMainSpanCount  | 主层级目录的列数\nSubSpanCount  | 次级层级目录的列数\nAnimationDuration | 合并动画的时间\nSubRatio | 次级目录的高度占主层级的高度比例\nEdgeWidth | 设置宽度用于当item到边缘时判断是否触发滑动\nMainPadding | 设置主层级容器的padding值\nMainPaddingLeft | \nMainPaddingTop |\nMainPaddingRight |\nMainPaddingBottom |\nSubPadding | 设置次级层级容器的padding值\nSubPaddingLeft |\nSubPaddingTop |\nSubPaddingRight |\nSubPaddingBottom |\nDragScaleX | 当item处于被拖拽状态时X轴方向缩放比例\nDragScaleY | 当item处于被拖拽状态时Y轴方向缩放比例\nDragInMergeScaleX | 当被拖拽的item处于可合并状态时X轴方向缩放比例\nDragInMergeScaleY | 当被拖拽的item处于可合并状态时Y轴方向缩放比例\n\nInsertAbleGridView(显示合并布局的View)\n\n属性 | 说明\n------- | -------\nRowCount | 行数（默认 2）\nColumnCount | 列数（默认 2）\nRowGap | 横向每列中的间隙距离\nColumnGap | 纵向每行之间的间隙距离\nOutLinePadding | 处于可以合并状态及非合并状态 外围框的距离\nOutlineWidth | 外边框的宽度\nOutlineColor | 外边框的颜色\nInnerPadding | 当内部有多个子View 时 与周围的边距\n\n# 高级自定义\n\n## 如果不喜欢`List\u003cList\u003c\u003e\u003e`的结构可以集成PrimitiveSimpleAdapter来实现其他数据源的adapter\n\n关于如何继承PrimitiveSimpleAdapter可以参考[IReaderAdapter](https://github.com/AlphaBoom/ClassifyView/blob/master/app/src/main/java/com/anarchy/classifyview/sample/ireader/IReaderAdapter.java),如果不能满足可以考虑分别继承[BaseMainAdapter](https://github.com/AlphaBoom/ClassifyView/blob/master/classify/src/main/java/com/anarchy/classify/adapter/BaseMainAdapter.java)及[BaseSubAdapter](https://github.com/AlphaBoom/ClassifyView/blob/master/classify/src/main/java/com/anarchy/classify/adapter/BaseSubAdapter.java)\n\n## 继承ClassifyView 重写以下方法：\n\n1. **RecyclerView getMain(Context context, AttributeSet parentAttrs)** \u003cbr/\u003e返回主层级使用的 RecyclerView。\n2. **RecyclerView getSub(Context context, AttributeSet parentAttrs)** 返回次级层级使用的RecyclerView\n3. **View chooseTarget(View selected, List\u003cView\u003e swapTargets, int curX, int curY)** \u003cbr/\u003e 当拖拽的View 覆盖到子View时会通过该方法在候选View中选择一个View 为目标View 之后的交互操作都会作用于当前所选择的View 及 这个目标View\u003cbr/\u003e\u003cfont color=\"green\"\u003e@param selected\u003c/font\u003e 当前选择的View\u003cbr/\u003e\u003cfont color=\"green\"\u003e@param swapTargets\u003c/font\u003e 候选的目标View(候选的目标View 为当前选择的View 能够覆盖到所有View)\u003cbr/\u003e\u003cfont color=\"green\"\u003e@param curX\u003c/font\u003e 当前选中View的X轴坐标\u003cbr/\u003e\u003cfont color=\"green\"\u003e@param curY\u003c/font\u003e 当前选中View的Y轴坐标\n4. **Drawable getDragDrawable(View view)** \u003cbr/\u003e返回用于渲染当前拖动View的显示\u003cbr/\u003e\u003cfont color=\"green\"\u003e@param view\u003c/font\u003e 当前选中的View\u003cbr/\u003e\u003cfont color=\"green\"\u003e@return drawable\u003c/font\u003e返回Drawable 用于设置拖拽View的背景\n5. 自定义次级目录的布局：\n   * 自定义次级目录的Dialog：重写 **Dialog createSubDialog()**\n   * 自定义次级目录布局：重写 **View getSubContent()**\n     \u003cbr/\u003e **注意：** 默认会在返回的View中查找有Tag 为 @String/sub_container 的View作为容器 如果没有 就已返回的View作为容器来添加次级目录的RecyclerView。 可以覆盖 **ViewGroup findHaveSubTagContainer(ViewGroup group)** 来重写查找容器的逻辑\n\n**设置数据方式有两种方式：**\n\n1. 使用 *ClassifyView.setAdapter(BaseMainAdapter mainAdapter, BaseSubAdapter subAdapter)* 用于分别设置主层级及次级层级的适配器（使用这种方式只能获取到相应状态时的回调，注意这些回调返回值的处理）\n2. 使用 *setAdapter(BaseSimpleAdapter baseSimpleAdapter)* 设置一个混合了主层级及次级层级的适配器，如何自定义可以参考 [SimpleAdapter](https://github.com/AlphaBoom/ClassifyView/blob/master/classify/src/main/java/com/anarchy/classify/simple/SimpleAdapter.java)\n\n\n## 主层级提供的回调\n在BaseAdapter中对于mergeStart等又增加了ViewHolder形式的回调 本质是一样的。\n\n回调方法 | 说明 | 是否有默认实现在BaseSubAdapter中\n------ | ----- | ----\n  setDragPosition | 设置当前被拖拽的位置 | true，默认效果为隐藏被拖拽的位置\n  boolean canDragOnLongPress|是否可以长按拖拽该View | false\n  boolean canDropOVer| 是否可以在对应点放下|true，默认返回true\n  boolean onMergeStart|第一次处于可合并状态|false\n  void onMerged|合并结束|false\n  MergeInfo onPrepareMerge|当准备进行合并动画时回调，返回的MergeInfo用于做当前拖拽的View到目标位置的动画|false\n  void onStartMergeAnimation|开始合并动画的回调|false\n  void onMergeCancel|当脱离合并状态的回调|false\n  boolean onMove|当需要触发移动时的回调|false\n  void moved|移动完成的回调|false\n  boolean canMergeItem|能否进行合并操作|false\n  int onLeaveSubRegion|当从次级目录拖动出item到主层级时回调，返回int 为添加到主层级adapter的位置|false\n  float getVelocity|只对低于这个速度的才判断能否移动(需要配合getCurrentState)|true\n  int getCurrentState|判断当前处于的状态，返回三个值 Classify.STATE_NONE 无状态，Classify.STATE_MERGE 处于合并状态，Classify.STATE_MOVE 处于移动状态| true\n  void onItemClick|当item被点击时的回调|false\n  boolean canExplodeItem|用于判断当点击一个item时是否展开次级目录|false\n  \n## 次级层级的回调\n次级层级与主层级相似 没有合并的相关回调：\n\n方法|说明\n---|---\nvoid prepareExplodeItem|用于准备初始化次级层级数据\nboolean canDropOver | 对于次层级的item 能否拖动到主层级\nboolean canDragOut | 是否可以移出次级目录到主层级\nvoid onDialogShow | 次级窗口显示时的回调\nvoid onDialogCancel | 次级窗口隐藏时的回调\n\n# 结语\n**当前项目效果展现 使用[SimpleAdapter](https://github.com/AlphaBoom/ClassifyView/blob/master/classify/src/main/java/com/anarchy/classify/simple/SimpleAdapter.java)**\n\n\n","funding_links":[],"categories":["Sort\u0026Drag"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlphaBoom%2FClassifyView","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAlphaBoom%2FClassifyView","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlphaBoom%2FClassifyView/lists"}