Skip to content

Commit

Permalink
Add: 下拉小程序振动反馈
Browse files Browse the repository at this point in the history
  • Loading branch information
CoderMikeHe committed Aug 3, 2020
1 parent 254eec1 commit bddf1e0
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 361 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## iOS微信开发
## iOS 微信开发

<img src="https://github.com/CoderMikeHe/WeChat_Resource/blob/master/snapshots/logo.png" width="256px" height="256px" />

Expand Down Expand Up @@ -34,13 +34,15 @@

### 🚀 模块

- ✅ 登陆/注册/登出 (ps: UI 尚未适配,逻辑正常)
- ✅ 登陆/注册/登出 (ps: UI 尚未适配,逻辑正常)

- ✅ 我

- ✅ 个人信息
- ✅ 设置

- ✅ 发现

- ✅ 朋友圈

- ✅ 通讯录
Expand All @@ -52,7 +54,7 @@

---

### ️使用
### ️ 使用

- [Cocoapods 安装教程](https://www.cnblogs.com/chuancheng/p/8443677.html)

Expand Down Expand Up @@ -121,6 +123,12 @@

### 🌈 预览

###### 🏳️‍🌈 微信模块

| ![](https://github.com/CoderMikeHe/WeChat_Resource/blob/master/gif/mainframe/ios_mainframe_pulldown_applet_page.gif) | 虚位以待 | 虚位以待 | 虚位以待 |
| :------------------------------------------------------------------------------------------------------------------: | :------: | :------: | :------: |


###### 🏳️‍🌈 通讯录模块

| ![](https://github.com/CoderMikeHe/WeChat_Resource/blob/master/snapshots/contacts/ios_contacts_page_0.png) | ![](https://github.com/CoderMikeHe/WeChat_Resource/blob/master/snapshots/contacts/ios_contacts_page_1.png) | 虚位以待 | 虚位以待 |
Expand Down
6 changes: 6 additions & 0 deletions WeChat/WeChat.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@
DE562495246C1ED0009CFF82 /* MHSearchMiniprogramViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DE562494246C1ED0009CFF82 /* MHSearchMiniprogramViewController.m */; };
DE562499246C1EF8009CFF82 /* MHSearchMusicViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DE562498246C1EF8009CFF82 /* MHSearchMusicViewController.m */; };
DE56249D246C1F18009CFF82 /* MHSearchStickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DE56249C246C1F18009CFF82 /* MHSearchStickerViewController.m */; };
DE61FEDB24D65687008596C4 /* MHAudioHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DE61FEDA24D65687008596C4 /* MHAudioHelper.m */; };
DE66C0C4246AC5C2000E9915 /* MHSearchMomentsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DE66C0C2246AC5C2000E9915 /* MHSearchMomentsCell.m */; };
DE66C0C5246AC5C2000E9915 /* MHSearchMomentsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DE66C0C3246AC5C2000E9915 /* MHSearchMomentsCell.xib */; };
DE66C0C9246ACABD000E9915 /* MHSearchMomentsItemViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = DE66C0C8246ACABD000E9915 /* MHSearchMomentsItemViewModel.m */; };
Expand Down Expand Up @@ -1464,6 +1465,8 @@
DE562498246C1EF8009CFF82 /* MHSearchMusicViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHSearchMusicViewController.m; sourceTree = "<group>"; };
DE56249B246C1F18009CFF82 /* MHSearchStickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHSearchStickerViewController.h; sourceTree = "<group>"; };
DE56249C246C1F18009CFF82 /* MHSearchStickerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHSearchStickerViewController.m; sourceTree = "<group>"; };
DE61FED924D65687008596C4 /* MHAudioHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MHAudioHelper.h; sourceTree = "<group>"; };
DE61FEDA24D65687008596C4 /* MHAudioHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MHAudioHelper.m; sourceTree = "<group>"; };
DE66C0C1246AC5C2000E9915 /* MHSearchMomentsCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MHSearchMomentsCell.h; sourceTree = "<group>"; };
DE66C0C2246AC5C2000E9915 /* MHSearchMomentsCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MHSearchMomentsCell.m; sourceTree = "<group>"; };
DE66C0C3246AC5C2000E9915 /* MHSearchMomentsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MHSearchMomentsCell.xib; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2925,6 +2928,8 @@
263D371C1F667D2C007267C3 /* Helper */ = {
isa = PBXGroup;
children = (
DE61FED924D65687008596C4 /* MHAudioHelper.h */,
DE61FEDA24D65687008596C4 /* MHAudioHelper.m */,
849135E82466966E00450D94 /* ISRDataHelper.h */,
849135E92466966E00450D94 /* ISRDataHelper.m */,
2664F5361FEA6BE5005C10CF /* MHMomentHelper.h */,
Expand Down Expand Up @@ -5092,6 +5097,7 @@
84278CA824B41C9900F5C337 /* MHPulldownAppletWrapperViewController.m in Sources */,
26FE65721F93142400642615 /* MHPlugViewController.m in Sources */,
262ADA491FCA741800B0F4FD /* MHDebugTouchView.m in Sources */,
DE61FEDB24D65687008596C4 /* MHAudioHelper.m in Sources */,
2605C5CD1F66323800B1F66E /* MHDiscoverViewModel.m in Sources */,
26FE8E931F9514D100EC8BE0 /* UIView+Layout.m in Sources */,
84D7469D24AD7200004B3CDA /* UIScrollView+MHExtension.m in Sources */,
Expand Down
8 changes: 4 additions & 4 deletions WeChat/WeChat/Macros/MHConstant.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,13 @@ FOUNDATION_EXTERN CGFloat const MHMomentCommentToolViewWithNoTextViewHeight;


//// ---------------- 微信首页模块 ----------------
/// 下拉显示小程序 临界点0 60.0f
/// 下拉显示小程序 临界点0 80.0f
FOUNDATION_EXTERN CGFloat const MHPulldownAppletCriticalPoint0;
/// 下拉显示小程序 临界点1 90.0f
/// 下拉显示小程序 临界点1 130.0f
FOUNDATION_EXTERN CGFloat const MHPulldownAppletCriticalPoint1;
/// 下拉显示小程序 临界点2 130.0f
/// 下拉显示小程序 临界点2 160.0f
FOUNDATION_EXTERN CGFloat const MHPulldownAppletCriticalPoint2;
/// 下拉显示小程序 临界点3 180.0f
/// 下拉显示小程序 临界点3 240.0f
FOUNDATION_EXTERN CGFloat const MHPulldownAppletCriticalPoint3;

/// 下拉显示小程序和隐藏小程序 动画时间 .35f
Expand Down
6 changes: 3 additions & 3 deletions WeChat/WeChat/Macros/MHConstant.m
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@

//// ---------------- 微信首页模块 ----------------
/// 下拉显示小程序 临界点0
CGFloat const MHPulldownAppletCriticalPoint0 = 60.0f;
CGFloat const MHPulldownAppletCriticalPoint0 = 80.0f;
/// 下拉显示小程序 临界点1
CGFloat const MHPulldownAppletCriticalPoint1 = 90.0f;
CGFloat const MHPulldownAppletCriticalPoint1 = 130.0f;
/// 下拉显示小程序 临界点2
CGFloat const MHPulldownAppletCriticalPoint2 = 130.0f;
CGFloat const MHPulldownAppletCriticalPoint2 = 160.0f;
/// 下拉显示小程序 临界点3
CGFloat const MHPulldownAppletCriticalPoint3 = 240.0f;

Expand Down
34 changes: 34 additions & 0 deletions WeChat/WeChat/Utils/Helper/MHAudioHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// MHAudioHelper.h
// MascotAlarmClock-mobile
//
// Created by senba on 2017/10/26.
// 音频播放工具类

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface MHAudioHelper : NSObject

MHSingletonH(Instance)


/// 是否正在震动
@property (nonatomic, readonly, assign , getter = isVibration) BOOL vibration;


/// 播放震动
- (void)playVibration;
/// 停止震动
- (void)stopVibration;


/// 播放音频文件
+ (void)playSoundWithName:(NSString *)soundName;
/// 播放音乐文件
+ (AVAudioPlayer *)playMusicWithName:(NSString *)musicName;
/// 暂停音乐
+ (void)pauseMusicWithName:(NSString *)musicName;
/// 停止音乐
+ (void)stopMusicWithName:(NSString *)musicName;
@end
161 changes: 161 additions & 0 deletions WeChat/WeChat/Utils/Helper/MHAudioHelper.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//
// MHAudioHelper.m
// MascotAlarmClock-mobile
//
// Created by senba on 2017/10/26.
//

#import "MHAudioHelper.h"

/**
* 系统铃声播放完成后的回调
*/
void SBSystemSoundFinishedPlayingCallback(SystemSoundID sound_id, void* user_data){
/// 执行方法
[[MHAudioHelper sharedInstance] performSelector:@selector(playVibration) withObject:nil afterDelay:.5];
}


@interface MHAudioHelper ()

/// 是否正在震动
@property (nonatomic, readwrite, assign , getter = isVibration) BOOL vibration;

@end


@implementation MHAudioHelper
static NSMutableDictionary *_soundDict;
static NSMutableDictionary *_musicDict;

+ (void)initialize{
_soundDict = [NSMutableDictionary dictionary];
_musicDict = [NSMutableDictionary dictionary];
}


MHSingletonM(Instance)


// 播放震动
- (void)playVibration{
// /// 播放震动 (PS 解决震动太过于连续的的用户体验)
// AudioServicesPlaySystemSoundWithCompletion(kSystemSoundID_Vibrate, ^{
// /// 整理搞个递归
// /// CoderMikeHe Fixed: 这里必须要延迟一段时间,否则不起作用
//// [self performSelector:@selector(playVibration) withObject:nil afterDelay:.5];
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self performSelector:@selector(playVibration) withObject:nil afterDelay:.4];
// });
// });



/// 播放
// Register the sound completion callback.
AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate,
NULL, // uses the main run loop
NULL, // uses kCFRunLoopDefaultMode
NULL, // the name of our custom callback function
NULL // for user data, but we don't need to do that in this case, so we just pass NULL
);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

self.vibration = YES;
}

/// 停止震动
- (void)stopVibration{
/// 取消掉
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(playVibration) object:nil];
/// remove
AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
/// dispose
AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);

self.vibration = NO;
}






+ (void)playSoundWithName:(NSString *)soundName{
// 1.从字典中取出对应的声音文件的SoundID
SystemSoundID soundId = [_soundDict[soundName] unsignedIntValue];

// 2.如果取出为空,则创建对应的音效文件
if (soundId == 0) {
// 2.1.获取对应音频的URL
CFURLRef urlRef = (__bridge CFURLRef)([[NSBundle mainBundle] URLForResource:soundName withExtension:nil]);

// 2.2.创建对应的音效文件
AudioServicesCreateSystemSoundID(urlRef, &soundId);

// 2.3.存到字典中
[_soundDict setObject:@(soundId) forKey:soundName];
}

// 3.播放音效
AudioServicesPlaySystemSound(soundId);
}

+ (AVAudioPlayer *)playMusicWithName:(NSString *)musicName{
// 0.判断传入的字符串是否为空
assert(musicName);

// 1.从字典中取出播放器
AVAudioPlayer *player = _musicDict[musicName];

// 2.如果取出为空,则创建对应的播放器
if (player == nil) {
// 2.1.获取音乐对应的URL
NSURL *url = [[NSBundle mainBundle] URLForResource:musicName withExtension:@"mp3"];

// 2.2.创建对应的播放器
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];

// 2.3 循环播放
player.numberOfLoops = -1;

// 2.4将播放器存到字典中
[_musicDict setObject:player forKey:musicName];
}

// 3.播放音乐
[player prepareToPlay];
[player play];

return player;
}

+ (void)pauseMusicWithName:(NSString *)musicName{
// 0.判断传入的字符串是否为空
assert(musicName);

// 1.取出对应的播放器
AVAudioPlayer *player = _musicDict[musicName];

// 2.暂停歌曲
if (player && player.isPlaying) {
[player pause];
}
}

+ (void)stopMusicWithName:(NSString *)musicName{
// 0.判断传入的字符串是否为空
assert(musicName);

// 1.取出对应的播放器
AVAudioPlayer *player = _musicDict[musicName];

// 2.停止播放
if (player) {
[player stop];
[_musicDict removeObjectForKey:musicName];
player = nil;
}
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#import "MHMainFrameMoreView.h"
#import "MHBouncyBallsView.h"


#import "MHAudioHelper.h"



Expand Down Expand Up @@ -68,6 +68,8 @@ @interface MHMainFrameViewController ()
@property (nonatomic, readwrite, weak) MHBouncyBallsView *ballsView;
/// appletWrapperController
@property (nonatomic, readwrite, strong) MHPulldownAppletWrapperViewController *appletWrapperController;
/// 是否需要振动反馈
@property (nonatomic, readwrite, assign, getter=isFeedback) BOOL feedback;
@end

@implementation MHMainFrameViewController
Expand Down Expand Up @@ -378,9 +380,13 @@ - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// 记录刚开始拖拽的值
self.startDragOffsetY = scrollView.contentOffset.y;
/// 需要增加振动反馈
self.feedback = YES;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

self.feedback = NO;
// 记录刚开始拖拽的值
self.endDragOffsetY = scrollView.contentOffset.y;
// decelerate: YES 说明还有速度或者说惯性,会继续滚动 停止时调用scrollViewDidEndDecelerating
Expand Down Expand Up @@ -438,6 +444,16 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.state == MHRefreshStateIdle && -delta < normal2pullingOffsetY && offsetY < self.lastOffsetY) {
// 转为即将刷新状态
self.state = MHRefreshStatePulling;

/// iOS 10.0+ 下拉增加振动反馈 https://www.jianshu.com/p/ef7eadfae188
if (self.isFeedback) {
/// 只震动一次
self.feedback = NO;
/// 开启振动反馈 iOS 10.0+
UIImpactFeedbackGenerator *feedBackGenertor = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
[feedBackGenertor impactOccurred];
}

} else if (self.state == MHRefreshStatePulling && (-delta >= normal2pullingOffsetY || offsetY >= self.lastOffsetY)) {
// 转为普通状态
self.state = MHRefreshStateIdle;
Expand Down
Loading

0 comments on commit bddf1e0

Please sign in to comment.