{"id":2740,"url":"https://github.com/huri000/CrownControl","last_synced_at":"2025-08-03T00:32:40.415Z","repository":{"id":56906839,"uuid":"158447811","full_name":"huri000/CrownControl","owner":"huri000","description":"CrownControl is a tiny accessory that makes scrolling through scrollable content possible without lifting your thumb.","archived":false,"fork":false,"pushed_at":"2018-12-01T21:30:04.000Z","size":5845,"stargazers_count":107,"open_issues_count":0,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-27T15:40:08.044Z","etag":null,"topics":["collection-view","crown-view-controller","digital-crown","ios","scroll","scrolling","scrollview","scrollview-component","swift","table-view","user-interaction"],"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/huri000.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-20T20:33:01.000Z","updated_at":"2024-11-20T15:17:33.000Z","dependencies_parsed_at":"2022-08-21T03:20:53.559Z","dependency_job_id":null,"html_url":"https://github.com/huri000/CrownControl","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huri000%2FCrownControl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huri000%2FCrownControl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huri000%2FCrownControl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/huri000%2FCrownControl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/huri000","download_url":"https://codeload.github.com/huri000/CrownControl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228510790,"owners_count":17931765,"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":["collection-view","crown-view-controller","digital-crown","ios","scroll","scrolling","scrollview","scrollview-component","swift","table-view","user-interaction"],"created_at":"2024-01-05T20:16:21.588Z","updated_at":"2024-12-06T18:30:45.889Z","avatar_url":"https://github.com/huri000.png","language":"Swift","funding_links":[],"categories":["UI"],"sub_categories":["ScrollView"],"readme":"# CrownControl\n\n[![Platform](http://img.shields.io/badge/platform-iOS-blue.svg?style=flat)](https://developer.apple.com/iphone/index.action)\n[![Language](http://img.shields.io/badge/language-Swift-brightgreen.svg?style=flat)](https://developer.apple.com/swift)\n[![Version](https://img.shields.io/cocoapods/v/CrownControl.svg?style=flat-square)](http://cocoapods.org/pods/CrownControl)\n[![codecov](https://codecov.io/gh/huri000/CrownControl/branch/master/graph/badge.svg)](https://codecov.io/gh/huri000/CrownControl)\n[![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](http://mit-license.org)\n![](https://travis-ci.com/huri000/CrownControl.svg?branch=master)\n\n* [Overview](#overview)\n  * [Features](#features)\n* [Example Project](#example-project)\n* [Requirements](#requirements)\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Quick Usage](#quick-usage)\n  * [Crown Attributes](#crown-attributes)\n    * [Scroll Axis](#scroll-axis)\n    * [Anchor Position](#anchor-position)\n    * [Spin Direction](#spin-direction)\n    * [User Interaction](#user-interaction)\n    * [Style](#style)\n    * [Sizes](#sizes)\n    * [Feedback](#feedback)\n* [Author](#author)\n* [License](#license)\n\n## Overview\n\nInspired by Apple Watch Digital Crown, CrownControl is a tiny accessory view that makes scrolling through scrollable content possible without lifting your thumb.\n\n\n### Features\n\nThe crown consists of background and foreground surfaces. \nThe foreground is an indicator which spins around the center as the attached scroll view offset changes.\n\n- [x] Can be repositioned either using force touch or long press.\n- [x] Can be spinned clockwise and counter clockwise.\n- [x] Most of the user interaction actions are configurable.\n- [x] The background and foreground sizes are configurable.\n- [x] Can be fully stylized.\n\n## Example Project\n\nThe example project contains samples where each demonstrates the CrownControl usability in a scrollable context.\n\nWeb View / PDF | Contacts | Photo Collection\n--- | --- | ---\n![pdf_example](https://github.com/huri000/assets/blob/master/crown-control/pdf.gif) | ![contacts_example](https://github.com/huri000/assets/blob/master/crown-control/contacts.gif) | ![photos_example](https://github.com/huri000/assets/blob/master/crown-control/photos.gif)\n\n## Requirements\n\n- iOS 9 or any higher version.\n- Swift 4.2 or any higher version.\n- CrownControl leans heavily on [QuickLayout](https://github.com/huri000/QuickLayout) - A lightwight library written in Swift that is used to easily layout views programmatically.\n\n## Installation\n\n### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate CrownControl into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/cocoapods/specs.git'\nplatform :ios, '9.0'\nuse_frameworks!\n\npod 'CrownControl', '1.0.0'\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n## Usage\n\n### Quick Usage\n\nUsing `CrownControl` is really simple.\n\nIn your view:\n\n1. Define and bind `CrownAttributes` to a scroll view instance, and optionally customize the attributes.\n2. Instantiate and bind the `CrownControl` instance to the `CrownAttributes` instance.\n3. Setup the `CrownControl` instance in a given superview using constraints to determine its position.\n\n```Swift\n\nprivate var crownControl: CrownControl!\nprivate var scrollView: UIScrollView!\n\nprivate func setupCrownViewController() {\n    let attributes = CrownAttributes(scrollView: scrollView, scrollAxis: .vertical)\n    \n    // Cling the bottom of the crown to the bottom of a view with -50 offset\n    let verticalConstraint = CrownAttributes.AxisConstraint(crownEdge: .bottom, anchorView: scrollView, anchorViewEdge: .bottom, offset: -50)\n    \n    // Cling the trailing edge of the crown to the trailing edge of a view with -50 offset\n    let horizontalConstraint = CrownAttributes.AxisConstraint(crownEdge: .trailing, anchorView: scrollView, anchorViewEdge: .trailing, offset: -50)\n\n    // Setup the crown control within *self*\n    crownControl = CrownControl(attributes: attributes, delegate: self)\n    crownControl.layout(in: view, horizontalConstaint: horizontalConstraint, verticalConstraint: verticalConstraint)\n}\n```\n\nTo make the crown respond to scrolling events that emanates from any other invoker but the crown, add to `scrollViewDidScroll(_:)` the following:\n\n```Swift\nfunc scrollViewDidScroll(_ scrollView: UIScrollView) {\n    crownControl?.spinToMatchScrollViewOffset()\n}\n```\n\n### Crown Attributes\n\n`CrownAttributes` is the crown appearance descriptor. \nIts nested properties describe the look and feel of the crown.\n\n#### Scroll Axis\n\nThe axis of the scroll view is a `.horizontal` or `.vertical`. It must be set during `CrownAttributes` initialization.\n\n####  Anchor Position\n\nThe anchor position of the foreground indicator. Indicates where the foreground is initially positioned.\n\n```Swift\nattributes.anchorPosition = .left\n```\n\nThe posssible values are `.left`, `.right`, `.top`, `.bottom`.\nThe default value is `.top`.\n\n#### Spin Direction\n\nThe direction to which the the indicator spins.\n\nExample for setting the spin direction to be counter-clockwise.\n```Swift\nattributes.spinDirection = .counterClockwise\n```\n\nThe default value is `clockwise`.\n\n#### User Interaction\n\nDescribes the user interaction with the crown.\nCurrently supported user interaction gestures: tap, double tap, long-press, and force-touch events.\n\n##### Tap Gestures\n\nWhen a single tap event occurs, scroll forward with the specified offset value: \n```Swift\nattributes.userInteraction.singleTap = .scrollsForwardWithOffset(value: 20, animated: true)\n```\n\nWhen a single tap event occurs, perform a custom action. \n```Swift\nattributes.userInteraction.singleTap = .custom(action: {\n    /* Do something */\n})\n```\n\nWhen a double tap event occurs, scroll to the leading edge of the scroll view. \n```Swift\nattributes.userInteraction.doubleTap = .scrollsToLeadingEdge\n```\n\n##### Drag and Drop\n\nThe crown can be dragged and dropped using force-touch if the force-touch trait is supported by the device hardware. If not, there is a fallback to long-press gesture.\n```Swift\nattributes.repositionGesture = .prefersForceTouch(attributes: .init())\n```\n\n#### Style\n\nThe background and foreground surfaces can be customized with various styles.\n\nExample for setting the crown background to a gradient style, and its border to a specific color and width. \n```Swift\nattributes.backgroundStyle.content = .gradient(gradient: .init(colors: [.white, .gray], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))\nattributes.backgroundStyle.border = .value(color: .gray, width: 1)\n```\n\n#### Sizes\n\nDescribes the size of the crown and relations between the foreground and the background surfaces. \n\nIn the following example, setting `scrollRelation` property to 10 means that 10 full spins of the foreground would make the scroll view offset reach its trailing edge.\n```Swift\nattributes.sizes.scrollRelation = 10\n```\n\nExample for setting the edge size (width and height) of the crown to 60pts, and the foreground edge ratio to 25 precent of that size, which is 15pts.\n```Swift\nattributes.sizes.backgroundSurfaceDiameter = 60\nattributes.sizes.foregroundSurfaceEdgeRatio = 0.25\n```\n\n#### Feedback\n\nFeedback descriptor for the foreground when it reaches the anchor point on the crown surface.\n\nThe device generates impact-haptic-feedback when the scroll-view offset reaches the leading edge.\nThe background surface of the crown flashes with color.\n```Swift\nattributes.feedback.leading.impactHaptic = .light\nattributes.feedback.leading.backgroundFlash = .active(color: .white, fadeDuration: 0.3)\n```\n\n## Author\n\nDaniel Huri, huri000@gmail.com\n\n## License\n\nCrownControl is available under the MIT license. See the [LICENSE](/LICENSE) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuri000%2FCrownControl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhuri000%2FCrownControl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhuri000%2FCrownControl/lists"}