{"id":18974660,"url":"https://github.com/pujiaxin33/jxbottomsheetview","last_synced_at":"2025-04-09T18:19:11.158Z","repository":{"id":56916672,"uuid":"143218701","full_name":"pujiaxin33/JXBottomSheetView","owner":"pujiaxin33","description":"A useful and gesture interaction BottomSheetView!","archived":false,"fork":false,"pushed_at":"2020-06-23T08:33:56.000Z","size":608,"stargazers_count":268,"open_issues_count":0,"forks_count":44,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-09T18:19:05.542Z","etag":null,"topics":["bottomsheet","ios","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pujiaxin33.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}},"created_at":"2018-08-01T23:35:29.000Z","updated_at":"2025-03-22T20:50:32.000Z","dependencies_parsed_at":"2022-08-21T03:50:50.008Z","dependency_job_id":null,"html_url":"https://github.com/pujiaxin33/JXBottomSheetView","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXBottomSheetView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXBottomSheetView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXBottomSheetView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pujiaxin33%2FJXBottomSheetView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pujiaxin33","download_url":"https://codeload.github.com/pujiaxin33/JXBottomSheetView/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085325,"owners_count":21045139,"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":["bottomsheet","ios","swift"],"created_at":"2024-11-08T15:15:43.587Z","updated_at":"2025-04-09T18:19:11.134Z","avatar_url":"https://github.com/pujiaxin33.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JXBottomSheetView\n\n项目中有类似于外卖软件的已点菜品列表，类似于下图：\n\n![meituan.gif](https://upload-images.jianshu.io/upload_images/1085173-77587ed9d77747a8.gif?imageMogr2/auto-orient/strip)\n\n可以看到列表的显示与隐藏，都只能通过按钮触发。不能通过手势驱动。不能设置最小可显示范围。针对以上问题，就有了这个项目。\n\n其实以上的需求核心问题就一个，如何优雅的解决：当内容还未到最大可显示范围时，列表里的内容不能滚动；当内容显示到最大的时候，如何不断开当前滚动手势，继续滚动列表里的内容。\n\n之前写了一个类似的底部列表滚动视图，地址：https://github.com/pujiaxin33/JXBottomSheetTableView 里面的实现方案还是挺有趣的，对外完全封装了里面的滚动控制细节，且以UITableView的子类实现。无奈越骚的操作越容易翻车。里面的应用场景比较狭窄，需求一变动就GG了。\n所以重新写了这个库，使用场景更大，使用更方便，交互更友善，好了，不说了，快上车吧！\n\n# 原理\n\n为`JXBottomSheetView`添加一个`UIPanGestureRecognizer`，成为其`delegate`，并让`shouldRecognizeSimultaneouslyWithOtherGestureRecognizer`方法返回true；\n如此一来，内容承载视图与列表视图的滚动手势可以同时响应了。接着，我们需要处理好当内容承载视图未显示到最大值时，列表视图(UITableView、UICollectionView)的`contentOffset.y`会被强制设置为0，营造一种列表内容未滚动的假象；\n当内容承载视图滚动到最大的时候，就放开对列表视图的滚动限制。\n其他一些细节可以参看源码了解；\n\n# 特性\n\n- 支持长距离滚动，不断手势：当列表视图滚动到规定的最高点时，停止视图移动，转而滚动里面的内容；\n- 内容自适应：当列表的数据源发生变动时，会根据最新的`contentSize`调整布局；\n- 切换流畅：最大、最小的手势切换，借鉴了系统`UIScrollView`的`PagingEnabled`切换效果；\n\n# 预览\n\n- 普通短距离滚动\n\n![](https://github.com/pujiaxin33/JXBottomSheetView/blob/master/JXBottomSheetView/Gif/NormalScroll.gif)\n\n- 长距离滚动，手势没有停掉。滚动到顶部的时候，继续滚动里面的内容\n\n![](https://github.com/pujiaxin33/JXBottomSheetView/blob/master/JXBottomSheetView/Gif/Scroll.gif)\n\n- 内容自适应，根据`contentView`的`contentSize`自动调整布局\n\n![](https://github.com/pujiaxin33/JXBottomSheetView/blob/master/JXBottomSheetView/Gif/Changed.gif)\n\n# 属性/方法\n\n属性/方法 | 描述 |\n----|------|\n**defaultMininumDisplayHeight** | 默认最小内容高度，当contentSize.height更小时，会更新mininumDisplayHeight值。  | \n**defaultMaxinumDisplayHeight** | 默认最大内容高度，当contentSize.height更小时，会更新maxinumDisplayHeight值。  | \n**displayState** | 当前展示状态，最大或最小  | \n**triggerDistance** | 滚动多少距离，可以触发展开和收缩状态切换。  | \n**triggerVelocity** | 触发状态切换的滚动速度，points/second  | \n**contentView: UIScrollView** | 用于承载内容的视图，UITableView、UICollectionView皆可。  | \n**displayMax()** | 显示最大内容  | \n**displayMin()** | 显示最小内容  | \n\n\n# 使用\n\n```\n        tableView = UITableView.init(frame: CGRect.zero, style: .plain)\n        \n        let bottomSheet = JXBottomSheetView(contentView: tableView)\n        bottomSheet.defaultMininumDisplayHeight = 100\n        bottomSheet.defaultMaxinumDisplayHeight = 300\n        bottomSheet.displayState = .minDisplay\n        bottomSheet.frame = self.view.bounds\n        view.addSubview(bottomSheet)\n```\n\n# 安装\n\nswift版本：5.0+\n\n```ruby\nuse_frameworks!\ntarget '\u003cYour Target Name\u003e' do\n    pod 'JXBottomSheetView'\nend\n```\n\n# 注意\n\n- 内部会影响到外部的代码\n  ```contentView.bounces = false\n  if let tableView = contentView as? UITableView {\n            tableView.estimatedRowHeight = 0\n        }\n  ```\n\n- 数据源的增删，请使用`reloadData`，而不是`insertRows`、`deleteRows`刷新页面。因为...你试一下就知道了。\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpujiaxin33%2Fjxbottomsheetview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpujiaxin33%2Fjxbottomsheetview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpujiaxin33%2Fjxbottomsheetview/lists"}