{"id":32312776,"url":"https://github.com/swasidhant/directselect","last_synced_at":"2025-10-23T09:59:39.742Z","repository":{"id":56908581,"uuid":"242492454","full_name":"Swasidhant/DirectSelect","owner":"Swasidhant","description":"An iOS implementation of Direct Select by Virgil Pana","archived":false,"fork":false,"pushed_at":"2020-03-23T17:36:42.000Z","size":6068,"stargazers_count":23,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-23T09:59:35.996Z","etag":null,"topics":["animation","dropdown","ios","library","selector","swift"],"latest_commit_sha":null,"homepage":null,"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/Swasidhant.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":"2020-02-23T09:51:42.000Z","updated_at":"2024-03-28T06:56:20.000Z","dependencies_parsed_at":"2022-08-21T01:50:57.638Z","dependency_job_id":null,"html_url":"https://github.com/Swasidhant/DirectSelect","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Swasidhant/DirectSelect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swasidhant%2FDirectSelect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swasidhant%2FDirectSelect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swasidhant%2FDirectSelect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swasidhant%2FDirectSelect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Swasidhant","download_url":"https://codeload.github.com/Swasidhant/DirectSelect/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Swasidhant%2FDirectSelect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280598945,"owners_count":26357977,"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","status":"online","status_checked_at":"2025-10-23T02:00:06.710Z","response_time":142,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["animation","dropdown","ios","library","selector","swift"],"created_at":"2025-10-23T09:59:34.054Z","updated_at":"2025-10-23T09:59:39.732Z","avatar_url":"https://github.com/Swasidhant.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Direct Select\n\n\u003c!--[![CI Status](https://img.shields.io/travis/Swasidhant/DirectSelect.svg?style=flat)](https://travis-ci.org/Swasidhant/DirectSelect)--\u003e\n[![Version](https://img.shields.io/cocoapods/v/DirectSelect.svg?style=flat)](https://cocoapods.org/pods/DirectSelect)\n[![License](https://img.shields.io/cocoapods/l/DirectSelect.svg?style=flat)](https://cocoapods.org/pods/DirectSelect)\n[![Platform](https://img.shields.io/cocoapods/p/DirectSelect.svg?style=flat)](https://cocoapods.org/pods/DirectSelect)\n\u003c!--[![Twitter](https://img.shields.io/cocoapods/badge/DirectSelect.svg?style=flat)](https://twitter.com/Swasidhant7)--\u003e\n\nBased on Virgil Pana's \u003ca href=\"https://dribbble.com/shots/3876250-DirectSelect-Dropdown-ux\n\"\u003eDirect select's\u003c/a\u003e design:\n\n![](./gif/DSGif.gif)\n\n\n## Requirements\n- iOS 8.0+\n- Xcode 10.0+\n- Swift 5.0+\n\n## Installation\nJust add the DirectSelect directory to your project\n\nOr use Cocoapods:\n\n```ruby\npod 'DirectSelect'\n```\n\n## Usage\n**1** Create an instance of DSInitialView from the `createInstance` method. Comply the intended delegate to `DSInitialViewDelegate`, which updates which option the user selected.\nA data model of type `DSDataModel` has to be passed. This is here you pass the list of all options, initial option selected, various UI configurations, etc.\n\n```swift\nlet initialView = DSInitialView.createInstance(model: giveDataModel1(), delegate: self)\n```\n\n**1.1** More details on the DSDataModel and what configurations are available:-\n\n```swift\npublic class DSDataModel {\npublic class DSUIConfigs {\n//should show an options expanding button on the initial view (See the second expanding view in the Example project)\npublic var showOptionsButton: Bool = false\n\n//tintColor of the options button if its shown\npublic var optionsBtnColor: UIColor = UIColor.init(red: 34.0/255.0, green: 34.0/255.0, blue: 34.0/255.0, alpha: 1.0)\n\n//font of the text on the initial view\npublic var initialFont: UIFont = UIFont.systemFont(ofSize: 14.0)\n\n//font of the text on the rows of the final tableview\npublic var finalFont: UIFont = UIFont.systemFont(ofSize: 18.0)\n\n//font of the title of final tableview view\npublic var finalTitleFont: UIFont = UIFont.systemFont(ofSize: 18.0)\n\n//font color of the text on the initial view\npublic var initialFontColor: UIColor = UIColor.init(red: 34.0/255.0, green: 34.0/255.0, blue: 34.0/255.0, alpha: 1.0)\n\n//font color of the text on the rows of the final tableview\npublic var finalFontColor: UIColor = UIColor.init(red: 34.0/255.0, green: 34.0/255.0, blue: 34.0/255.0, alpha: 1.0)\n\n//background color of both the initial View and the final view cells and tableview\npublic var finalBGColor: UIColor = UIColor.white\n\n//separator color of tableview\npublic var finalBGSeparatorColor: UIColor = UIColor.init(red: 243.0/255.0, green: 243.0/255.0, blue: 243.0/255.0, alpha: 1.0)\n\n//font color of the title of final tableview view\npublic var finalTitleColor: UIColor = UIColor.init(red: 34.0/255.0, green: 34.0/255.0, blue: 34.0/255.0, alpha: 1.0)\n\n//font color of the cell texts in non selection state\npublic var defaultSubviewNonSelectionColor: UIColor = UIColor.lightGray\n\n//font of the cell title text in non selection state\npublic var finalTitleNonSelectionStateFont: UIFont = UIFont.systemFont(ofSize: 18.0)\n\n//tableview row which is selected should first align itself exactly in the selectable area before the final tableview UI is dismissed\npublic var selectedRowShouldCenterBeforeDismiss: Bool = false\n\n//UI configs of intro view if it is used\npublic var introViewUIModel: DSIntroUIModel?\n\npublic init() {\n\n}\n}\n\npublic init() {\n\n}\n\n//title to display on top of the final tableview\npublic var titleString: String?\n\n//options to display on top of the final tableview. Type is [Any] as the even custom Subviews are allowed through DSSubview\npublic var values: [Any] = []\n\n//time interval for which final tableview shows before auto dismissing\npublic var longPressDuration: TimeInterval = 1.0\n\n//initial index which is selected by default in the tableview\npublic var initialIndex: Int = 0\n\n//initial data which is shown by default in the tableview\npublic var initialData: Any?\n\n//case defaultCell - we are using the default view for initial view and final view cells\n//case customCell - we are custom view for initial view and final view cells\npublic var cellSubviewType: CSCellSubviewType = .defaultCell\n\n//UI configs instance explained above\npublic var uiConfigs = DSUIConfigs()\n\n//superview on which to add the final Tableview UI as subview\n//if this is nil, we add the final Tableview UI to the superview of DSinitialView instance\n//make this nil if the initial view is a direct subview of the view on which you need to present the final tableview UI\n//other assign this property to the intended superview of the final tableview UI\npublic var finalViewSuperview: UIView?\n\n//in case you are using custom subview, this block should return an instance of your custom subview\n//we call this block when we want to initialize an instance of your subview.\n//For assigning properties to your subview, we call assignData method of the DSSubview\npublic var customSubviewCreator: (() -\u003e DSSubview)?\n}\n```\n\n**2**  You can use an intro view to coach users on how to use DirectSelect. (See the first example of the FoodJournal Example). Just call `addAndShowIntroView()` on the `DSInitialView`. When you want to remove the intro call `removeIntroView()` on the same DSInitialView. As per current implementation, when user long presses on an initial view, we will remove the intro view (if present) and then show the final tableview ui.\n\n**2.1** Configurations available on the intro view:\n\n```swift\npublic class DSIntroUIModel {\n//text to coach the user on how to use DirectSelect\npublic var introLabelText: String = \"Long press to open options, then tap and drag to select.\"\n//color of the text which coaches the user on how to use DirectSelect\npublic var introLabelColor: UIColor = UIColor.init(red: 150.0/255.0, green: 150.0/255.0, blue: 150.0/255.0, alpha: 1.0)\n//backgroundColor of the circle view used in the intro screen\npublic var circleViewColor: UIColor = UIColor.blue.withAlphaComponent(0.4)\n//backgroundColor of the halo effect used in the intro screen\npublic var haloColor: UIColor = UIColor.init(red: 140.0/255.0, green: 217.0/255.0, blue: 190.0/255.0, alpha: 1.0).withAlphaComponent(0.6)\n}\n```\n\n**3** You can also use custom UI in the DSInitialView and in cells of the final tablview subview. Your custom subview should implement the protocol `DSSubview`. As an example check `giveDataModel4()` function in  `ViewController` class of the Example project. We use the custom UIView `CustomSubview` instead of the default view. Notice the line:\n\n```swift\ndataModel.customSubviewCreator = {DSSubview.createInstance()}\n```\n\nHere we assign the code creating an instance of the custom UIView to `customSubviewCreator` property of the dataModel\n\n**3.1** DSSubview protocol methods are as follows:-\n\n```swift\npublic protocol DSSubview: class {\nvar delegate: DSDefaultCellSubviewDelegate? {get set}\n\n//callback when the subview enters the area of selection, (i.e. it enters between the two separator lines in the final tableview UI) you might want to make ui changes here\n//For example, you might want to make the text font/color changes or background color changes\nfunc wentInsideSelectionArea()\n\n//callback when the subview goes outside the area of selection, (i.e. it enters outside the two separator lines in the final tableview UI) you might want to make ui changes here\nfunc wentOutsideSelectionArea()\n\n//give the list of views who size or position who want to change between the initial and final views\nfunc giveViewsToAnimate() -\u003e [UIView]\n\n//this one's a bit tricky. So basically when we animate between different sizes between initial and final views, the spaces between the views will be different in the initial and final views\n//so either you can give different constraints and return an array of CGFloat(0.0)s here (with length equal to the no of elements in giveViewsToAnimate())\n//or you can return the values of how much to move the views in the x-coordinate space\nfunc giveHorizontalTransformValues() -\u003e [CGFloat]\n\n//make the initial data and Ui setup of your subview\n//DSInitialSetupViewType gives whether this subview instance is used in DSInitialView or DSFinalView\nfunc initialSetup(_ data: Any?, viewType: DSInitialSetupViewType)\n\n//make the data assignment\nfunc assignData(_ data: Any?)\n\n//give initial sizes of the views you want to be animated (you had passed them in giveViewsToAnimate())\n//the order should be the same as the order of the views in giveViewsToAnimate()\nfunc getInitialViewSizes(_ data: Any?) -\u003e [CGSize]\n\n//give final sizes of the views you want to be animated (you had passed them in giveViewsToAnimate())\n//the order should be the same as the order of the views in giveViewsToAnimate()\nfunc getFinalViewSizes(_ data: Any?) -\u003e [CGSize]\n}\n```\n**3.2** If we want to present the final view through some button click in our custom subview call the `showFinalViewAction()` of the `DSDefaultCellSubviewDelegate` protocol.\n\n## Author\n\nSwasidhant, ssprofessional33@gmail.com \u003cbr/\u003e\n\u003ca href=\"https://twitter.com/Swasidhant7\"\u003eTwitter\u003c/a\u003e\n\u003ca href=\"https://www.linkedin.com/in/swasidhant-chowdhury-6095b960/\"\u003e Linkedin\u003c/a\u003e\n\n## Note of Thanks\n\nSpecial thanks to \u003ca href=\"https://dribbble.com/Vraj247\"\u003eVikas Raj\u003c/a\u003e for all his help with the design part. Could not have done it without the motivation, design help and criticism.\n\n\u003ca href=\"https://twitter.com/Vraj247\"\u003eTwitter\u003c/a\u003e\n\n## License\n\nCustomSelector is available under the MIT license. See the [LICENSE](./LICENSE) file for more info.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswasidhant%2Fdirectselect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswasidhant%2Fdirectselect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswasidhant%2Fdirectselect/lists"}