123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- //
- // WidgetViewController.m
- // KulexiuForStudent
- //
- // Created by 王智 on 2022/9/13.
- //
- #import "WidgetViewController.h"
- #import "WidgetNavView.h"
- #import "WidgetDotView.h"
- #import "WidgetSpeedView.h"
- #import "WidgetFunctionView.h"
- #import "KSChoosePicker.h"
- #import "WidgetBottomButtonView.h"
- #import <AVFoundation/AVFoundation.h>
- #import "KSMetronomePlayer.h"
- @interface WidgetViewController ()<MetronomeControlViewDelegate,MetronomeFunctionDelegate>
- @property (nonatomic, strong) WidgetNavView *navView;
- @property (nonatomic, strong) WidgetDotView *dotView;
- @property (nonatomic, strong) WidgetSpeedView *speedView;
- @property (nonatomic, strong) WidgetFunctionView *functionView;
- @property (nonatomic, assign) int speed;
- @property (nonatomic, assign) KSWidgeMetronomeType metronomeType;
- @property (nonatomic, strong) KSChoosePicker *pickerView;
- @property (nonatomic, strong) WidgetBottomButtonView *bottomView;
- /** 定时器 */
- @property (nonatomic, strong) NSTimer *timer;
- /** 定时器多少秒循环一次 */
- @property (nonatomic, assign) float timerLength;
- @property (nonatomic, assign) int currentNo;
- @property (nonatomic, assign) NSInteger totalNoCount;
- @property (nonatomic, assign) float playVolume;
- @property (nonatomic, strong) KSMetronomePlayer *nodePlayer;
- @end
- @implementation WidgetViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view.
- self.ks_prefersNavigationBarHidden = YES;
- [self configUI];
- [self setDefaultConfig];
- }
- - (void)backAction {
- [self removeAll];
- [self.navigationController popViewControllerAnimated:YES];
- }
- - (void)setDefaultConfig {
- self.speed = 90;
- self.playVolume = 1.0f;
- [self updateSpeedUI];
- self.metronomeType = KSWidgeMetronomeType4V4;
- [self changeBeat];
- self.functionView.volumeRate = 1.0f;
- }
- - (void)configUI {
- [self.scrollView removeFromSuperview];
- self.view.backgroundColor = HexRGB(0xECF9F7);
-
- [self.view addSubview:self.navView];
- [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.top.mas_equalTo(self.view);
- make.height.mas_equalTo(kNaviBarHeight);
- }];
-
- [self.view addSubview:self.dotView];
- [self.dotView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.mas_equalTo(self.view);
- make.top.mas_equalTo(self.navView.mas_bottom).offset(10);
- make.height.mas_equalTo(44);
- }];
-
- [self.view addSubview:self.speedView];
- [self.speedView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.mas_equalTo(self.view);
- make.top.mas_equalTo(self.dotView.mas_bottom);
- make.height.mas_equalTo(300);
- }];
-
- [self.view addSubview:self.functionView];
- [self.functionView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.mas_equalTo(self.view);
- make.top.mas_equalTo(self.speedView.mas_bottom);
- make.height.mas_equalTo(115);
- }];
-
- [self.view addSubview:self.bottomView];
- [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.left.right.mas_equalTo(self.view);
- make.top.mas_equalTo(self.functionView.mas_bottom).offset(10);
- make.height.mas_equalTo(60);
- }];
- }
- #pragma mark --- delegate
- - (void)volumeChange:(float)volume {
- self.playVolume = volume;
- self.nodePlayer.volume = volume;
- }
- - (void)clickChangeBeat {
- // 显示节拍选择弹窗
- MJWeakSelf;
- self.pickerView = [[KSChoosePicker alloc] initWithTitle:@"节拍" sourceData:@[@"1/2",@"2/2",@"1/4",@"2/4",@"3/4",@"4/4",@"3/8",@"6/8"] chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
- KSWidgeMetronomeType type = chooseIndex;
- weakSelf.metronomeType = type;
- [weakSelf changeBeat];
- } cancel:^{
-
- }];
- [self.pickerView showPicker];
- }
- - (void)clickChangeSpeed:(int)speed {
- self.speed = speed;
- // 更新UI
- [self updateSpeedUI];
- }
- - (void)changeSpeedWithIsAdd:(BOOL)isAdd speed:(int)speed {
- if (isAdd) {
- self.speed = MIN(self.speed +speed, 200);
- }else{
- self.speed = MAX(self.speed -speed, 50);
- }
-
- // 更新UI
- [self updateSpeedUI];
- }
- - (void)updateSpeedUI {
- self.speedView.speed = self.speed;
- self.functionView.speed = self.speed;
- }
- #pragma mark --- lazying
- - (WidgetNavView *)navView {
- if (!_navView) {
- _navView = [WidgetNavView shareInstance];
- MJWeakSelf;
- [_navView navBackAction:^{
- [weakSelf backAction];
- }];
- }
- return _navView;
- }
- - (WidgetDotView *)dotView {
- if (!_dotView) {
- _dotView = [WidgetDotView shareInstance];
- }
- return _dotView;
- }
- - (WidgetSpeedView *)speedView {
- if (!_speedView) {
- _speedView = [WidgetSpeedView shareInstance];
- _speedView.delegate = self;
- }
- return _speedView;
- }
- - (WidgetFunctionView *)functionView {
- if (!_functionView) {
- _functionView = [WidgetFunctionView shareInstance];
- _functionView.delegate = self;
- }
- return _functionView;
- }
- - (WidgetBottomButtonView *)bottomView {
- if (!_bottomView) {
- _bottomView = [WidgetBottomButtonView shareInstance];
- MJWeakSelf;
- [_bottomView metronomePlayCallback:^(BOOL isPlay) {
- if (isPlay) {
- [weakSelf playBeat];
- }
- else {
- [weakSelf stopBeat];
- }
- }];
- }
- return _bottomView;
- }
- - (void)playBeat {
- // 重置
- self.currentNo = -1;
- // 开始播放
- [self.timer setFireDate:[NSDate distantPast]];
- [self.nodePlayer playAction:self.speed metronomeTyle:self.metronomeType];
-
- }
- - (void)stopBeat {
- [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器
- [self.nodePlayer stopPlay];
- self.currentNo = -1;
- }
- - (void)changeBeat {
- [self.dotView updateSpotView:self.metronomeType];
- self.functionView.currentMetronomeType = self.metronomeType;
- self.speedView.currentType = self.metronomeType;
-
- }
- - (void)setSpeed:(int)speed {
- _speed = speed;
- CGFloat rateFloat = speed;
- self.timerLength = 1 / (rateFloat / 60);
- }
- - (KSMetronomePlayer *)nodePlayer {
- if (!_nodePlayer) {
- _nodePlayer = [[KSMetronomePlayer alloc] init];
- }
- return _nodePlayer;
- }
- - (NSTimer *)timer{
-
- if (!_timer) {
- _timer = [NSTimer scheduledTimerWithTimeInterval:self.timerLength target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
- }
- return _timer;
- }
- - (void)timerAction {
-
- [self.dotView updateSpotViewHeightState:self.currentNo];
- self.currentNo++;
- }
- #pragma mark -- 重置定时器
- - (void)resetTimer{
- [_timer invalidate];
- _timer = nil;
- [self.timer setFireDate:[NSDate distantPast]];
-
- }
- - (void)removeAll{
-
- if (_timer) {
- [_timer invalidate];
- _timer = nil;
- }
- }
- - (void)dealloc {
- NSLog(@"----dealloc ");
- [self removeAll];
- }
- /*
- #pragma mark - Navigation
- // In a storyboard-based application, you will often want to do a little preparation before navigation
- - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
- // Get the new view controller using [segue destinationViewController].
- // Pass the selected object to the new view controller.
- }
- */
- @end
|