The Ripple component provides a radial action in the form of a visual ripple expanding outward from the user's touch. Ripple is a visual form of feedback for touch events providing users a clear signal that an element is being touched.
MDCRippleView is a material design implementation of touch feedback and is a successor of Ink.
Ripple is currently a beta component. Therefore, clients that wish to use Ripple in their app will need to manually clone the repo and add the code to their project.
Add the following to your Podfile:
pod 'MaterialComponentsBeta/Ripple'
Then, run the following command:
pod install
Before using Ripple, you'll need to import it:
import MaterialComponentsBeta.MaterialRipple
#import "MaterialRipple.h"
The Ripple component exposes two interfaces that you can use to add material-like feedback to the user:
MDCRippleView is a subclass of UIView that draws and animates ripples and can be placed anywhere in your view hierarchy.MDCRippleTouchController bundles an MDCRippleView instance with a UITapGestureRecognizer instance to conveniently drive the ripples from the user's touches.The simplest method of using ripple in your views is to use a MDCRippleTouchController:
let myButton = UIButton(type: .system) myButton.setTitle("Tap Me", for: .normal) let rippleTouchController = MDCRippleTouchController(view: myButton)
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeSystem]; [myButton setTitle:@"Tap me" forState:UIControlStateNormal]; MDCRippleTouchController *rippleTouchController = [[MDCRippleTouchController alloc] initWithView:myButton];
The MDCRippleTouchControllerDelegate gives you some control over aspects of the ripple/touch relationship, such as to temporarily disable ripple touches, the following code uses the delegate's rippleTouchController:shouldProcessRippleTouchesAtTouchLocation: method:
class MyDelegate: NSObject, MDCRippleTouchControllerDelegate { func rippleTouchController(_ rippleTouchController: MDCRippleTouchController, shouldProcessRippleTouchesAtTouchLocation location: CGPoint) -> Bool { // Determine if we want to display the ink return true } } ... let myButton = UIButton(type: .system) myButton.setTitle("Tap Me", for: .normal) let myDelegate = MyDelegate() let rippleTouchController = MDCRippleTouchController(view: myButton) rippleTouchController.delegate = myDelegate
@interface MyDelegate: NSObject <MDCRippleTouchControllerDelegate> @end @implementation MyDelegate - (BOOL)rippleTouchController:(MDCRippleTouchController *)rippleTouchController shouldProcessRippleTouchesAtTouchLocation:(CGPoint)location { return YES; } @end ... UIButton *myButton = [UIButton buttonWithType:UIButtonTypeSystem]; [myButton setTitle:@"Tap me" forState:UIControlStateNormal]; MyDelegate *myDelegate = [[MyDelegate alloc] init]; MDCRippleTouchController *rippleTouchController = [[MDCRippleTouchController alloc] initWithView:myButton]; rippleTouchController.delegate = myDelegate;
NOTE: The ripple touch controller does not keep a strong reference to the view to which it is attaching the ripple view. An easy way to prevent the ripple touch controller from being deallocated prematurely is to make it a property of a view controller (like in these examples.)
Alternatively, you can use MDCRippleView directly to display ripples using your own touch processing:
let myCustomView = MyCustomView(frame: CGRect.zero) let rippleView = MDCRippleView() rippleView.inkColor = UIColor.red myCustomView.addSubview(rippleView) ... // When the touches begin, there is one animation rippleView.beginRippleTouchDownAtPoint(at: touchPoint, animated: true, completion: nil) ... // When the touches end, there is another animation inkView.beginRippleTouchUpAnimated(animated: true, completion: nil)
MyCustomView *myCustomView = [[MyCustomView alloc] initWithFrame:CGRectZero]; MDCInkView *rippleView = [[MDCRippleView alloc] init]; rippleView.inkColor = [UIColor redColor]; [myCustomView addSubview:rippleView]; ... // When the touches begin, there is one animation [inkView beginRippleTouchDownAtPoint:touchPoint animated:YES completion:nil]; ... // When the touches end, there is another animation [inkView beginRippleTouchUpAnimated:YES completion:nil];