{"id":1833,"url":"https://github.com/RxSwiftCommunity/RxAnimated","last_synced_at":"2025-08-02T04:32:39.479Z","repository":{"id":46602502,"uuid":"100164823","full_name":"RxSwiftCommunity/RxAnimated","owner":"RxSwiftCommunity","description":"Animated RxCocoa bindings","archived":false,"fork":false,"pushed_at":"2021-10-04T10:17:48.000Z","size":2515,"stargazers_count":692,"open_issues_count":12,"forks_count":36,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-07-24T03:20:37.826Z","etag":null,"topics":[],"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/RxSwiftCommunity.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":"2017-08-13T08:50:42.000Z","updated_at":"2025-05-21T03:45:00.000Z","dependencies_parsed_at":"2022-08-21T04:50:42.765Z","dependency_job_id":null,"html_url":"https://github.com/RxSwiftCommunity/RxAnimated","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/RxSwiftCommunity/RxAnimated","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxSwiftCommunity%2FRxAnimated","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxSwiftCommunity%2FRxAnimated/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxSwiftCommunity%2FRxAnimated/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxSwiftCommunity%2FRxAnimated/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RxSwiftCommunity","download_url":"https://codeload.github.com/RxSwiftCommunity/RxAnimated/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RxSwiftCommunity%2FRxAnimated/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268334618,"owners_count":24233793,"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-08-02T02:00:12.353Z","response_time":74,"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":[],"created_at":"2024-01-05T20:15:56.886Z","updated_at":"2025-08-02T04:32:39.049Z","avatar_url":"https://github.com/RxSwiftCommunity.png","language":"Swift","funding_links":[],"categories":["Reactive Programming","Libraries"],"sub_categories":["Other free courses","Prototyping","Other Parsing"],"readme":"# RxAnimated - animated bindings\n\n[![CI Status](http://img.shields.io/travis/icanzilb/RxAnimated.svg?style=flat)](https://travis-ci.org/icanzilb/RxAnimated)\n[![Version](https://img.shields.io/cocoapods/v/RxAnimated.svg?style=flat)](http://cocoapods.org/pods/RxAnimated)\n[![License](https://img.shields.io/cocoapods/l/RxAnimated.svg?style=flat)](http://cocoapods.org/pods/RxAnimated)\n[![Platform](https://img.shields.io/cocoapods/p/RxAnimated.svg?style=flat)](http://cocoapods.org/pods/RxAnimated)\n\n**RxAnimated** provides animation interface to RxCocoa's bindings.\n\nIt comes with few predefined animation bindings, and provides a flexible mechanism for you to add your own predefined animations and use them when binding with RxCocoa.\n\n## Usage\n\n## Built-in animations\n\nWhen binding values with RxCocoa you write something like:\n\n```swift\ntextObservable\n  .bind(to: labelFlip.rx.text)\n```\n\n![](etc/label-noanim.gif)\n\nThis updates the label's text each time the observable emits a new string value. But this happens abruptly and without any transition. With RxAnimated you can use the `animated` extension to **bind values with animations**, like so:\n\n```swift\ntextObservable\n  .bind(animated: labelFlip.rx.animated.flip(.top, duration: 0.33).text)\n```\n\n![](etc/label-anim.gif)\n\nThe \"difference\" is that you use `bind(animated:)` instead of `bind(to:)` and you insert `animated.flip(.top, duration: 0.33)` (or one of the other provided or custom animation methods) between `rx` and the property sink you want to use, e.g. `text` in the example above.\n\nThe same built-in fade and flip animations work on any `UIView` element. And also on specific properties like `UILabel.rx.text` or `UIImageView.rx.image`.\n\n### Animation List\n\nList of built-in animated sinks:\n\n```swift\nUIView.rx.animated...isHidden\nUIView.rx.animated...alpha\nUILabel.rx.animated...text\nUILabel.rx.animated...attributedText\nUIControl.rx.animated...isEnabled\nUIControl.rx.animated...isSelected\nUIButton.rx.animated...title\nUIButton.rx.animated...image\nUIButton.rx.animated...backgroundImage\nUIImageView.rx.animated...image\nNSLayoutConstraint.rx.animated...constant\nNSLayoutConstraint.rx.animated...isActive\n```\n\nList of the built-in animations:\n\n```swift\nUIView.rx.animated.fade(duration: TimeInterval)\nUIView.rx.animated.flip(FlipDirection, duration: TimeInterval)\nUIView.rx.animated.tick(FlipDirection, duration: TimeInterval)\nUIView.rx.animated.animation(duration: TimeInterval, animations: ()-\u003eVoid)\nNSLayoutConstraint.rx.animated.layout(duration: TimeInterval)\n```\n\nCheck the demo app for a number of examples.\n\n## Custom animations\n\nYou can easily add your custom bind animations to match the visual style of your app.\n\nI. (Optional) If you are animating a new binding sink that has no animated binding (e.g. `UIImageView.rx.image`, `UILabel.rx.text` and more are already included but you need another property)\n\n\n```swift\n// This is your class `UILabel`\nextension AnimatedSink where Base: UILabel { \n    // This is your property name `text` and value type `String`\n    public var text: Binder\u003cString\u003e { \n        let animation = self.type!\n        return Binder(self.base) { label, text in\n            animation.animate(view: label, block: {\n                guard let label = label as? UILabel else { return }\n                // Here you update the property\n                label.text = text \n            })\n        }\n    }\n}\n```\n\nII. Add your new animation method:\n\n```swift\n// This is your class `UIView`\nextension AnimatedSink where Base: UIView { \n    // This is your animation name `tick`\n    public func tick(_ direction: FlipDirection = .right, duration: TimeInterval) -\u003e AnimatedSink\u003cBase\u003e { \n        // use one of the animation types and provide `setup` and `animation` blocks\n        let type = AnimationType\u003cBase\u003e(type: RxAnimationType.spring(damping: 0.33, velocity: 0), duration: duration, setup: { view in\n            view.alpha = 0\n            view.transform = CGAffineTransform(rotationAngle: direction == .right ?  -0.3 : 0.3)\n        }, animations: { view in\n            view.alpha = 1\n            view.transform = CGAffineTransform.identity\n        })\n        \n        //return AnimatedSink\n        return AnimatedSink\u003cBase\u003e(base: self.base, type: type) \n    }\n}\n```\n\nIII. Now you can use your new animation to bind subscriptions. Here's how usually binding `UIImageView.rx.image` looks like:\n\n```swift\nimageObservable\n    .bind(to: imageView.rx.image)\n```\nAnd the result is non-animated binding:\n\n![](etc/custom-noanim.gif)\n\nIf you use your new custom animation binding like so:\n\n```swift\nimageObservable\n    .bind(to: imageView.rx.animated.tick(.right, duration: 0.33).image)\n```\n\nThe effect will be:\n\n![](etc/custom-anim.gif)\n\nAnd if you use the same animation on a `UILabel`:\n\n```swift\ntextObservable\n    .bind(to: labelCustom.rx.animated.tick(.left, duration: 0.75).text)\n```\n\n![](etc/custom-label-anim.gif)\n\nThe sky is the limit! (And good taste.)\n\n## Example\n\nThe demo app shows few animations in action, download the repo and give it a try.\n\n## Installation\n\nRxAnimated depends on RxSwift 5+.\n\nRxAnimated is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:\n\n```ruby\npod \"RxAnimated\"\n```\n\n## License\n\nRxAnimated is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRxSwiftCommunity%2FRxAnimated","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRxSwiftCommunity%2FRxAnimated","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRxSwiftCommunity%2FRxAnimated/lists"}