iOS中的震动反馈
2020-06-02 本文已影响0人
爱笑的猫mi
一、震动反馈的来源
为了增强交互性,我们经常会在用户触发某个动作时候,给用户一定的硬件反馈。比如切换tabbar,下拉刷新列表,点击某个btn。
二、<1>实现原理
较早的系统版本,我们会使用AudioTool.framework。
主要在这个AudioTool.framework里
#import <AudioToolbox/AudioToolbox.h>
一般震动
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
普通短震(类似3D Touch的 Peek 反馈 )
AudioServicesPlaySystemSound(1519);
普通短震 (类似3D Touch Pop 反馈)
AudioServicesPlaySystemSound(1520);
连续三次短震
AudioServicesPlaySystemSound(1521);
<2>iOS 10之后提供了一套Objective-C的接口 UIImpactFeedbackGenerator
这个枚举定义震动等级
typedef NS_ENUM(NSInteger, UIImpactFeedbackStyle) {
UIImpactFeedbackStyleLight,
UIImpactFeedbackStyleMedium,
UIImpactFeedbackStyleHeavy,
UIImpactFeedbackStyleSoft API_AVAILABLE(ios(13.0)),
UIImpactFeedbackStyleRigid API_AVAILABLE(ios(13.0))
};
@interface UIImpactFeedbackGenerator : UIFeedbackGenerator
- (instancetype)initWithStyle:(UIImpactFeedbackStyle)style;
// 调用后立刻开始震动
- (void)impactOccurred;
// 调用后立刻开始震动,伴随着强度等级 0 到 1
- (void)impactOccurredWithIntensity:(CGFloat)intensity API_AVAILABLE(ios(13.0));
使用方式
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
[generator impactOccurred];
三、<实战操作>
MJRefresh增加震动反馈
发现有的app在下拉刷新的时候有一下震动反馈,感觉用户体验很棒,所以想在现有的项目中也增加一个这样的效果。但是项目中使用的MJRefresh 并没有提供这样的接口,自己重新实现下拉刷新也不现实。
既然如此就需要手动去监听下拉的状态改变。
MJRefresh中刷新控件的基类MJRefreshComponent有一个state属性,是一个枚举:
/** 刷新控件的状态 */
typedef NS_ENUM(NSInteger, MJRefreshState) {
/** 普通闲置状态 */
MJRefreshStateIdle = 1,
/** 松开就可以进行刷新的状态 */
MJRefreshStatePulling,
/** 正在刷新中的状态 */
MJRefreshStateRefreshing,
/** 即将刷新的状态 */
MJRefreshStateWillRefresh,
/** 所有数据加载完毕,没有更多的数据了 */
MJRefreshStateNoMoreData
};
这个就属性就是刷新控件的状态值,可以使用KVO的方式在列表中监听控件状态的变化,从而增加震动反馈。
// 增加KVO监听
[_tableView.mj_header addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
[_tableView.mj_footer addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
实现监听方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([object isEqual:self.tableView.mj_header] && self.tableView.mj_header.state == MJRefreshStatePulling) {
[self feedbackGenerator];
}
else if ([object isEqual:self.tableView.mj_footer] && self.tableView.mj_footer.state == MJRefreshStatePulling) {
[self feedbackGenerator];
}
}
震动反馈
- (void)feedbackGenerator {
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
[generator prepare];
[generator impactOccurred];
}