iOS中的震动反馈

一、震动反馈的来源
为了增强交互性,我们经常会在用户触发某个动作时候,给用户一定的硬件反馈。比如切换tabbar,下拉刷新列表,点击某个btn。

二、<1>实现原理
较早的系统版本,我们会使用AudioTool.framework。
主要在这个AudioTool.framework里

#import 

一般震动

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 *)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];
}

你可能感兴趣的:(iOS中的震动反馈)