I created a subclass of a UICollectionViewController that is used as the custom inputAccessoryViewController
in a UITextView
.
https://developer.apple.com/reference/uikit/uiresponder/1621124-inputaccessoryviewcontroller
I want to play the keyboard click sound when you tap a cell in the collection view using playInputClick. https://developer.apple.com/reference/uikit/uidevice/1620050-playinputclick
I cannot figure out how to get this to work in a collection view. It works for a simple view like this using the inputAccessoryView
property of a UITextView
but I'm not sure what view to subclass in the collection view controller hierarchy to get the keyboard click sound to play.
@interface KeyboardClickView : UIView <UIInputViewAudioFeedback>
@end
@implementation KeyboardClickView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[self addGestureRecognizer:tap];
}
return self;
}
- (void)tap:(id)sender
{
[[UIDevice currentDevice] playInputClick];
}
- (BOOL)enableInputClicksWhenVisible
{
return YES;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_inputAccessoryView = [[KeyboardClickView alloc] initWithFrame:CGRectMake(0, 0, 0, 50)];
_inputAccessoryView.backgroundColor = [UIColor redColor];
[[UITextView appearance] setInputAccessoryView:_inputAccessoryView];
// ...
}
@end
I'm also aware that you can play the keyboard click sound using AudioServicesPlaySystemSound(1104)
but this doesn't respect the user's settings if they have the keyboard click sounds disabled.
To use the benefits of playInputClick
in UIViewController
:
Dummy input accessory view:
@interface Clicker : UIView <UIInputViewAudioFeedback>
@end
@implementation Clicker
- (BOOL)enableInputClicksWhenVisible
{
return YES;
}
@end
View with input accessory view:
@interface ControllerView : UIView
@end
@implementation ControllerView
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (UIView *)inputAccessoryView
{
return [[Clicker alloc] init];
}
@end
View Controller with custom view:
@implementation ViewController
- (void)loadView
{
self.view = [[ControllerView alloc] init];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.view resignFirstResponder];
}
@end
When the responder object becomes the first responder and inputView (or inputAccessoryView) is not nil, UIKit animates the input view into place below the parent view (or attaches the input accessory view to the top of the input view).
There is no visual consequences since the height of Clicker
view is zero, and conforming to UIInputViewAudioFeedback
protocol enables [[UIDevice currentDevice] playInputClick]
functionality within ViewController
.
Look here for responder chains and here for input accessory views.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With