Browse Source

直播间点击老师头像跳转老师主页

Steven 2 years ago
parent
commit
6e0303c051
27 changed files with 815 additions and 59 deletions
  1. 10 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. BIN
      KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate
  3. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/Contents.json
  4. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/metro_hightSpot@2x.png
  5. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/metro_hightSpot@3x.png
  6. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/Contents.json
  7. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/metro_whiteSpot@2x.png
  8. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/metro_whiteSpot@3x.png
  9. 23 4
      KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m
  10. 1 0
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.h
  11. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.h
  12. 8 1
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.m
  13. 12 1
      KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.xib
  14. 190 15
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/WidgetViewController.m
  15. 24 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.h
  16. 57 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.m
  17. 59 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.xib
  18. 12 1
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetDotView.h
  19. 270 1
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetDotView.m
  20. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.h
  21. 47 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.m
  22. 1 1
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.xib
  23. 4 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.h
  24. 17 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.m
  25. 3 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.xib
  26. 2 2
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetSpeedView.h
  27. 27 32
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetSpeedView.m

+ 10 - 0
KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj

@@ -466,6 +466,8 @@
 		BC4CF29D28D0758700961C61 /* WidgetSpeedView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC4CF29C28D0758700961C61 /* WidgetSpeedView.xib */; };
 		BC4CF2A028D075CC00961C61 /* WidgetFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC4CF29F28D075CC00961C61 /* WidgetFunctionView.m */; };
 		BC4CF2A228D075D400961C61 /* WidgetFunctionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC4CF2A128D075D400961C61 /* WidgetFunctionView.xib */; };
+		BC4CF2A528D1B07800961C61 /* WidgetBottomButtonView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC4CF2A428D1B07800961C61 /* WidgetBottomButtonView.m */; };
+		BC4CF2A728D1B08000961C61 /* WidgetBottomButtonView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC4CF2A628D1B08000961C61 /* WidgetBottomButtonView.xib */; };
 		BC50171227FC0D5600F8BCBC /* SubjectChooseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC50171127FC0D5600F8BCBC /* SubjectChooseViewController.m */; };
 		BC50171527FC0D8300F8BCBC /* SubjectChooseBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC50171427FC0D8300F8BCBC /* SubjectChooseBodyView.m */; };
 		BC50171727FC0D8E00F8BCBC /* SubjectChooseBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC50171627FC0D8D00F8BCBC /* SubjectChooseBodyView.xib */; };
@@ -1791,6 +1793,9 @@
 		BC4CF29E28D075CC00961C61 /* WidgetFunctionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WidgetFunctionView.h; sourceTree = "<group>"; };
 		BC4CF29F28D075CC00961C61 /* WidgetFunctionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WidgetFunctionView.m; sourceTree = "<group>"; };
 		BC4CF2A128D075D400961C61 /* WidgetFunctionView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WidgetFunctionView.xib; sourceTree = "<group>"; };
+		BC4CF2A328D1B07800961C61 /* WidgetBottomButtonView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WidgetBottomButtonView.h; sourceTree = "<group>"; };
+		BC4CF2A428D1B07800961C61 /* WidgetBottomButtonView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WidgetBottomButtonView.m; sourceTree = "<group>"; };
+		BC4CF2A628D1B08000961C61 /* WidgetBottomButtonView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WidgetBottomButtonView.xib; sourceTree = "<group>"; };
 		BC50171027FC0D5600F8BCBC /* SubjectChooseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SubjectChooseViewController.h; sourceTree = "<group>"; };
 		BC50171127FC0D5600F8BCBC /* SubjectChooseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SubjectChooseViewController.m; sourceTree = "<group>"; };
 		BC50171327FC0D8300F8BCBC /* SubjectChooseBodyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SubjectChooseBodyView.h; sourceTree = "<group>"; };
@@ -4473,6 +4478,9 @@
 				BC4CF29E28D075CC00961C61 /* WidgetFunctionView.h */,
 				BC4CF29F28D075CC00961C61 /* WidgetFunctionView.m */,
 				BC4CF2A128D075D400961C61 /* WidgetFunctionView.xib */,
+				BC4CF2A328D1B07800961C61 /* WidgetBottomButtonView.h */,
+				BC4CF2A428D1B07800961C61 /* WidgetBottomButtonView.m */,
+				BC4CF2A628D1B08000961C61 /* WidgetBottomButtonView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -6336,6 +6344,7 @@
 				BC71D24E288804CD0010F14B /* img_16.png in Resources */,
 				27F9033727E87C8B00C08A19 /* MineNavView.xib in Resources */,
 				BC8A45AB283DC33400094BBB /* TrackChooseView.xib in Resources */,
+				BC4CF2A728D1B08000961C61 /* WidgetBottomButtonView.xib in Resources */,
 				BCB9FA47286EDCD7005D766B /* KSTipsAlert.xib in Resources */,
 				BCFDA64C28BCA2000022B497 /* live_animation_0.png in Resources */,
 				BC542E40284079E300633781 /* UserAuthBodyView.xib in Resources */,
@@ -6976,6 +6985,7 @@
 				BC4CF28E28D072C000961C61 /* WidgetViewController.m in Sources */,
 				BCB6353627F6D2A300ACFDCF /* TimeStampCell.m in Sources */,
 				BCB6354D27F6D2A300ACFDCF /* EmptyView.m in Sources */,
+				BC4CF2A528D1B07800961C61 /* WidgetBottomButtonView.m in Sources */,
 				2723B63327F157D500E0B90B /* ChatComplainBodyView.m in Sources */,
 				2779357927E324A70010E277 /* KSImageButton.m in Sources */,
 				BC802D9228B897610079E350 /* LiveApplyingView.m in Sources */,

BIN
KulexiuForStudent/KulexiuForStudent.xcworkspace/xcuserdata/wangzhi.xcuserdatad/UserInterfaceState.xcuserstate


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "metro_hightSpot@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "metro_hightSpot@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/metro_hightSpot@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_hightSpot.imageset/metro_hightSpot@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "metro_whiteSpot@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "metro_whiteSpot@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/metro_whiteSpot@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/Home/metronome/metro_whiteSpot.imageset/metro_whiteSpot@3x.png


+ 23 - 4
KulexiuForStudent/KulexiuForStudent/Module/Live/Controller/LiveVideoRoomViewController.m

@@ -1889,13 +1889,22 @@ static int clickPraiseBtnTimes  = 0;
     if (!_headView) {
         _headView = [LiveRoomHeadView shareInstance];
         MJWeakSelf;
-        [_headView quitAction:^{
-            [weakSelf showQuitAlert];
+        [_headView quitAction:^(BOOL isQuit) {
+            if (isQuit) {
+                [weakSelf showQuitAlert];
+            }
+            else {
+                [weakSelf displayTeacherInfo:CART_TYPE_NONE];
+            }
         }];
+
     }
     return _headView;
 }
 
+- (void)showTeacherCenter {
+    
+}
 - (void)showQuitAlert {
     if (self.isCloseRoom) { // 如果直播结束 直接点击退出房间
         [self quitRoom];
@@ -2261,6 +2270,11 @@ static int clickPraiseBtnTimes  = 0;
     
     NSString *tabs = @"";
     switch (type) {
+        case CART_TYPE_NONE:
+        {
+            tabs = @"";
+        }
+            break;
         case CART_TYPE_ACCOMPANY:
         {
             tabs = @"practice";
@@ -2284,8 +2298,13 @@ static int clickPraiseBtnTimes  = 0;
         default:
             break;
     }
-
-    NSString *url = [NSString stringWithFormat:@"%@%@%@&tabs=%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId,tabs];
+    NSString *url = @"";
+    if ([NSString isEmptyString:tabs]) {
+        url = [NSString stringWithFormat:@"%@%@%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId];
+    }
+    else {
+        url = [NSString stringWithFormat:@"%@%@%@&tabs=%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId,tabs];
+    }
     KSLiveWebViewController *ctrl = [[KSLiveWebViewController alloc] init];
     ctrl.url = url;
     [self.navigationController pushViewController:ctrl animated:YES];

+ 1 - 0
KulexiuForStudent/KulexiuForStudent/Module/Live/View/KSShopCardView.h

@@ -7,6 +7,7 @@
 
 #import <UIKit/UIKit.h>
 typedef NS_ENUM(NSInteger, CART_TYPE) {
+    CART_TYPE_NONE,
     CART_TYPE_ACCOMPANY = 2,
     CART_TYPE_LIVE,
     CART_TYPE_VIDEO,

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.h

@@ -8,7 +8,7 @@
 
 #import <UIKit/UIKit.h>
 
-typedef void(^QuitRoomaAtion)(void);
+typedef void(^QuitRoomaAtion)(BOOL isQuit);
 
 NS_ASSUME_NONNULL_BEGIN
 

+ 8 - 1
KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.m

@@ -29,9 +29,16 @@
 }
 - (IBAction)quitButtonAction:(id)sender {
     if (self.callback) {
-        self.callback();
+        self.callback(YES);
     }
 }
+
+- (IBAction)showTeacherDetail:(id)sender {
+    if (self.callback) {
+        self.callback(NO);
+    }
+}
+
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 12 - 1
KulexiuForStudent/KulexiuForStudent/Module/Live/View/LiveRoomHeadView.xib

@@ -16,7 +16,7 @@
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yl0-aO-J0L">
                     <rect key="frame" x="11" y="10" width="120" height="38"/>
                     <subviews>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="GvE-me-Ml5">
+                        <imageView clipsSubviews="YES" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="GvE-me-Ml5">
                             <rect key="frame" x="2" y="2" width="34" height="34"/>
                             <constraints>
                                 <constraint firstAttribute="height" constant="34" id="7xb-3N-CS9"/>
@@ -37,16 +37,27 @@
                             <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <nil key="highlightedColor"/>
                         </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Af2-9U-Vd7">
+                            <rect key="frame" x="0.0" y="0.0" width="120" height="38"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="showTeacherDetail:" destination="iN0-l3-epB" eventType="touchUpInside" id="9Is-4k-ige"/>
+                            </connections>
+                        </button>
                     </subviews>
                     <color key="backgroundColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="0.25" colorSpace="calibratedRGB"/>
                     <constraints>
+                        <constraint firstItem="Af2-9U-Vd7" firstAttribute="leading" secondItem="Yl0-aO-J0L" secondAttribute="leading" id="Bj5-8z-7Dl"/>
                         <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="120" id="DDG-zg-TAQ"/>
                         <constraint firstItem="kNd-90-9MX" firstAttribute="leading" secondItem="GvE-me-Ml5" secondAttribute="trailing" constant="9" id="GgJ-2q-QA2"/>
+                        <constraint firstItem="Af2-9U-Vd7" firstAttribute="top" secondItem="Yl0-aO-J0L" secondAttribute="top" id="UxZ-g1-Y16"/>
+                        <constraint firstAttribute="bottom" secondItem="Af2-9U-Vd7" secondAttribute="bottom" id="Z3x-oY-nvu"/>
                         <constraint firstItem="kNd-90-9MX" firstAttribute="centerY" secondItem="Yl0-aO-J0L" secondAttribute="centerY" id="d4Z-K1-iLE"/>
                         <constraint firstAttribute="trailing" secondItem="kNd-90-9MX" secondAttribute="trailing" constant="15" id="gVZ-4e-6sG"/>
                         <constraint firstItem="GvE-me-Ml5" firstAttribute="leading" secondItem="Yl0-aO-J0L" secondAttribute="leading" constant="2" id="qbW-p1-2YX"/>
                         <constraint firstItem="GvE-me-Ml5" firstAttribute="centerY" secondItem="Yl0-aO-J0L" secondAttribute="centerY" id="sl9-mk-v0u"/>
                         <constraint firstAttribute="height" constant="38" id="une-x9-BHQ"/>
+                        <constraint firstAttribute="trailing" secondItem="Af2-9U-Vd7" secondAttribute="trailing" id="wCc-gA-5E0"/>
                     </constraints>
                     <userDefinedRuntimeAttributes>
                         <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">

+ 190 - 15
KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/WidgetViewController.m

@@ -10,6 +10,9 @@
 #import "WidgetDotView.h"
 #import "WidgetSpeedView.h"
 #import "WidgetFunctionView.h"
+#import "KSChoosePicker.h"
+#import "WidgetBottomButtonView.h"
+#import <AVFoundation/AVFoundation.h>
 
 @interface WidgetViewController ()<MetronomeControlViewDelegate,MetronomeFunctionDelegate>
 
@@ -23,6 +26,27 @@
 
 @property (nonatomic, assign) int speed;
 
+@property (nonatomic, assign) KSMetronomeType metronomeType;
+
+@property (nonatomic, strong) KSChoosePicker *pickerView;
+
+@property (nonatomic, strong) WidgetBottomButtonView *bottomView;
+
+/** 定时器 */
+@property (nonatomic, strong) NSTimer *timer;
+
+/** 定时器多少秒循环一次 */
+@property (nonatomic, assign) float timerLength;
+
+/** 发出"嘀"声的播放器 */
+@property (nonatomic, strong) AVAudioPlayer *audioPlayDI;
+
+/** 发出"咚"声的播放器 */
+@property (nonatomic, strong) AVAudioPlayer *audioPlayDONG;
+
+@property (nonatomic, assign) int currentNo;
+
+@property (nonatomic, assign) NSInteger totalNoCount;
 
 @end
 
@@ -33,18 +57,20 @@
     // Do any additional setup after loading the view.
     self.ks_prefersNavigationBarHidden = YES;
     [self configUI];
+    [self setDefaultConfig];
+}
+
+- (void)setDefaultConfig {
     self.speed = 90;
     [self updateSpeedUI];
+    self.metronomeType = KSMetronomeType4V4;
+    [self changeBeat];
 }
 
 
 - (void)configUI {
     [self.scrollView removeFromSuperview];
-//    self.view.backgroundColor = [UIColor whiteColor];
-    
-    CAGradientLayer *layer = [self createGradientLayerFromColor:HexRGB(0x2DC7AA) startPoint:CGPointMake(0.5, 0) endColor:HexRGB(0xA0A0A0) endPoint:CGPointMake(0.5, 1) bounds:CGRectMake(0, 0, KPortraitWidth, KPortraitHeight)];
-//    layer.masksToBounds = YES;
-//    [self.view.layer addSublayer:layer];
+    self.view.backgroundColor = HexRGB(0xECF9F7);
     
     [self.view addSubview:self.navView];
     [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -55,7 +81,7 @@
     [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);
+        make.top.mas_equalTo(self.navView.mas_bottom).offset(10);
         make.height.mas_equalTo(44);
     }];
     
@@ -72,13 +98,28 @@
         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)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) {
+        KSMetronomeType type = chooseIndex;
+        weakSelf.metronomeType = type;
+        [weakSelf changeBeat];
+    } cancel:^{
+        
+    }];
+    [self.pickerView showPicker];
 }
 
 - (void)clickChangeSpeed:(int)speed {
@@ -107,6 +148,10 @@
 - (WidgetNavView *)navView {
     if (!_navView) {
         _navView = [WidgetNavView shareInstance];
+        MJWeakSelf;
+        [_navView navBackAction:^{
+            [weakSelf backAction];
+        }];
     }
     return _navView;
 }
@@ -134,15 +179,145 @@
     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.timer setFireDate:[NSDate distantPast]];
+}
+
+- (void)stopBeat {
+    [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器
+}
+
 
-- (CAGradientLayer *)createGradientLayerFromColor:(UIColor *)fromColor startPoint:(CGPoint)startPoint endColor:(UIColor *)endColor endPoint:(CGPoint)endPoint bounds:(CGRect)bounds {
-    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
-    gradientLayer.colors = @[(__bridge id)fromColor.CGColor, (__bridge id)endColor.CGColor];
-    gradientLayer.startPoint = startPoint;
-    gradientLayer.endPoint = endPoint;
-    gradientLayer.frame = bounds;
-    gradientLayer.locations = @[@(0),@(1.0f)];
-    return gradientLayer;
+- (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);
+}
+
+- (AVAudioPlayer *)audioPlayDI{
+    
+    if (!_audioPlayDI) {
+        
+        NSString *soundPath = [[NSBundle mainBundle]pathForResource:@"tick" ofType:@"wav"];
+        NSURL *soundUrl = [NSURL fileURLWithPath:soundPath];
+        //        初始化播放器对象
+        self.audioPlayDI = [[AVAudioPlayer alloc]initWithContentsOfURL:soundUrl error:nil];
+        //        设置循环次数,如果为负数,就是无限循环
+        self.audioPlayDI.numberOfLoops = 0;
+        //        是否可以更改播放速率
+        //        self.audioPlay.enableRate = YES;
+        
+    }
+    
+    return _audioPlayDI;
+}
+
+- (AVAudioPlayer *)audioPlayDONG{
+    
+    if (!_audioPlayDONG) {
+        
+        NSString *soundPath = [[NSBundle mainBundle]pathForResource:@"tock" ofType:@"wav"];
+        NSURL *soundUrl = [NSURL fileURLWithPath:soundPath];
+        self.audioPlayDONG = [[AVAudioPlayer alloc]initWithContentsOfURL:soundUrl error:nil];
+        self.audioPlayDONG.numberOfLoops = 0;
+        
+    }
+    return _audioPlayDONG;
+}
+
+- (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 {
+    
+    
+    if (_metronomeType == KSMetronomeType1V2 || _metronomeType == KSMetronomeType1V4) {
+        [self.audioPlayDI play];
+//        [self.audioPlayDONG stop];
+    }
+    else {
+        
+        if (_metronomeType == KSMetronomeType2V4 && self.currentNo %2 == 0) {
+            [self.audioPlayDI play];
+//            [self.audioPlayDONG stop];
+        }else if (_metronomeType == KSMetronomeType3V4 && self.currentNo %3 == 0){
+            [self.audioPlayDI play];
+//            [self.audioPlayDONG stop];
+        }else if (_metronomeType == KSMetronomeType4V4 && self.currentNo %4 == 0){
+            [self.audioPlayDI play];
+//            [self.audioPlayDONG stop];
+        }else if (_metronomeType == KSMetronomeType3V8 && self.currentNo %3 == 0){
+            [self.audioPlayDI play];
+//            [self.audioPlayDONG stop];
+        }else if (_metronomeType == KSMetronomeType6V8 && self.currentNo %6 == 0){
+            [self.audioPlayDI play];
+//            [self.audioPlayDONG stop];
+        }else{
+//            [self.audioPlayDI stop];
+            [self.audioPlayDONG play];
+        }
+    }
+    
+    [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;
+    }
+    
+    if (_audioPlayDI) {
+        _audioPlayDI = nil;
+    }
+    
+    if (_audioPlayDONG) {
+        _audioPlayDONG = nil;
+    }
+}
+- (void)dealloc {
+    [self removeAll];
 }
 /*
 #pragma mark - Navigation

+ 24 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.h

@@ -0,0 +1,24 @@
+//
+//  WidgetBottomButtonView.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/9/14.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^WidgetPlayAction)(BOOL isPlay);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface WidgetBottomButtonView : UIView
+
+@property (nonatomic, assign) BOOL isPlay;
+
++ (instancetype)shareInstance;
+
+- (void)metronomePlayCallback:(WidgetPlayAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 57 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.m

@@ -0,0 +1,57 @@
+//
+//  WidgetBottomButtonView.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2022/9/14.
+//
+
+#import "WidgetBottomButtonView.h"
+
+@interface WidgetBottomButtonView ()
+
+@property (nonatomic, copy) WidgetPlayAction callback;
+@property (weak, nonatomic) IBOutlet UIButton *actionButton;
+
+@end
+
+@implementation WidgetBottomButtonView
+
+
++ (instancetype)shareInstance {
+    WidgetBottomButtonView *view = [[[NSBundle mainBundle] loadNibNamed:@"WidgetBottomButtonView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)metronomePlayCallback:(WidgetPlayAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+
+- (IBAction)playAction:(id)sender {
+    self.isPlay = !self.isPlay;
+    if (self.callback) {
+        self.callback(self.isPlay);
+    }
+}
+
+- (void)setIsPlay:(BOOL)isPlay {
+    _isPlay = isPlay;
+    if (isPlay) {
+        [self.actionButton setTitle:@"暂停" forState:UIControlStateNormal];
+    }
+    else {
+        [self.actionButton setTitle:@"播放" forState:UIControlStateNormal];
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 59 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetBottomButtonView.xib

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="WidgetBottomButtonView">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="75"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dUf-b4-rpL">
+                    <rect key="frame" x="69" y="10" width="276" height="45"/>
+                    <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="276" id="IAr-m9-HBE"/>
+                        <constraint firstAttribute="height" constant="45" id="neJ-fh-cFC"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" title="播放"/>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="22.5"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="size" keyPath="shadowOffset">
+                            <size key="value" width="0.0" height="6"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowOpacity">
+                            <real key="value" value="1"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
+                            <real key="value" value="12"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="shadowUIColor">
+                            <color key="value" red="1" green="1" blue="1" alpha="0.71999999999999997" colorSpace="custom" customColorSpace="sRGB"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="playAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="VaJ-tx-TKv"/>
+                    </connections>
+                </button>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="dUf-b4-rpL" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="YIX-HD-67L"/>
+                <constraint firstItem="dUf-b4-rpL" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="kjy-H9-oV0"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="131.8840579710145" y="-159.04017857142856"/>
+        </view>
+    </objects>
+</document>

+ 12 - 1
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetDotView.h

@@ -9,10 +9,13 @@
 
 // 节拍器节拍选择
 typedef NS_ENUM(NSInteger, KSMetronomeType) {
-    KSMetronomeType1V4 =0,     // 1/4
+    KSMetronomeType1V2 = 0,    // 1/2
+    KSMetronomeType2V2,        // 2/2
+    KSMetronomeType1V4,        // 1/4
     KSMetronomeType2V4,        // 2/4
     KSMetronomeType3V4,        // 3/4
     KSMetronomeType4V4,        // 4/4
+    KSMetronomeType3V8,        // 3/8
     KSMetronomeType6V8         // 6/8
 };
 
@@ -25,7 +28,15 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (instancetype)shareInstance;
 
+/** 更新当前点View(显示几个点) */
+- (void)updateSpotView:(KSMetronomeType)metronomeStat;
 
+/**
+ 更新某个点闪烁
+
+ @param currentTotalNo 可以被currentTotalNo余0的闪烁一下
+ */
+- (void)updateSpotViewHeightState:(int)currentTotalNo;
 
 @end
 

+ 270 - 1
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetDotView.m

@@ -7,17 +7,286 @@
 
 #import "WidgetDotView.h"
 
-@interface WidgetDotView ()
+#define SPOT_WHDTH (24)
 
+@interface WidgetDotView ()
 
+@property (nonatomic, assign) KSMetronomeType currentMetronomeType;
 
 @end
 
 @implementation WidgetDotView
+
+
 + (instancetype)shareInstance {
     WidgetDotView *view = [[[NSBundle mainBundle] loadNibNamed:@"WidgetDotView" owner:nil options:nil] firstObject];
     return view;
 }
+
+- (void)createUI {
+    
+}
+
+
+- (void)updateSpotViewHeightState:(int)currentTotalNo {
+    //    当前圆个数
+    int spotNo;
+    
+    if (self.currentMetronomeType == KSMetronomeType1V4) {
+        spotNo = 1;
+    }else if (self.currentMetronomeType == KSMetronomeType2V4){
+        spotNo = 2;
+    }else if (self.currentMetronomeType == KSMetronomeType3V4){
+        spotNo = 3;
+    }else if (self.currentMetronomeType == KSMetronomeType4V4){
+        spotNo = 4;
+    }else{
+        spotNo = 6;
+    }
+    
+    UIImageView *currentImageView = [self viewWithTag:currentTotalNo % spotNo +100];
+    currentImageView.highlighted = YES;
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        currentImageView.highlighted = NO;
+    });
+}
+
+- (void)updateSpotView:(KSMetronomeType)metronomeStat {
+    
+    self.currentMetronomeType = metronomeStat;
+    [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
+
+    [self creatSpotImageView:metronomeStat];
+}
+
+- (void)creatSpotImageView:(KSMetronomeType)metronomeStat {
+    if (metronomeStat == KSMetronomeType1V2) {
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType2V2) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 2) / 3;
+        
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.centerY.mas_equalTo(0);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType1V4) {
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.centerX.mas_equalTo(self.mas_centerX);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType2V4) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 2) / 3;
+        
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.centerY.mas_equalTo(0);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType3V4) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 3) / 4;
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView2 = [self createWhiteImageView];
+        spotView2.tag = 102;
+        [self addSubview:spotView2];
+        [spotView2 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView1.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType4V4) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 4) / 5;
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView2 = [self createWhiteImageView];
+        spotView2.tag = 102;
+        [self addSubview:spotView2];
+        [spotView2 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView1.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView3 = [self createWhiteImageView];
+        spotView3.tag = 103;
+        [self addSubview:spotView3];
+        [spotView3 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView2.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType3V8) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 3) / 4;
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView2 = [self createWhiteImageView];
+        spotView2.tag = 102;
+        [self addSubview:spotView2];
+        [spotView2 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView1.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+    else if (metronomeStat == KSMetronomeType6V8) {
+        CGFloat xSpace = (KPortraitWidth - SPOT_WHDTH * 6) / 7;
+        UIImageView *spotView = [self creatSpotImageView];
+        spotView.tag = 100;
+        [self addSubview:spotView];
+        [spotView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(self.mas_left).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView1 = [self createWhiteImageView];
+        spotView1.tag = 101;
+        [self addSubview:spotView1];
+        [spotView1 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView2 = [self createWhiteImageView];
+        spotView2.tag = 102;
+        [self addSubview:spotView2];
+        [spotView2 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView1.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView3 = [self createWhiteImageView];
+        spotView3.tag = 103;
+        [self addSubview:spotView3];
+        [spotView3 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView2.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView4 = [self createWhiteImageView];
+        spotView4.tag = 104;
+        [self addSubview:spotView4];
+        [spotView4 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView3.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+        
+        UIImageView *spotView5 = [self createWhiteImageView];
+        spotView5.tag = 105;
+        [self addSubview:spotView5];
+        [spotView5 mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.mas_equalTo(spotView4.mas_right).offset(xSpace);
+            make.bottom.mas_equalTo(self.mas_bottom).offset(-12);
+            make.width.height.mas_equalTo(SPOT_WHDTH);
+        }];
+    }
+}
+
+#pragma mark -- 创建大圆View
+- (UIImageView *)creatSpotImageView{
+    
+    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"metro_whiteSpot"] highlightedImage:[UIImage imageNamed:@"metro_hightSpot"]];
+    return imageView;
+}
+
+- (UIImageView *)createWhiteImageView {
+    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"metro_whiteSpot"] highlightedImage:[UIImage imageNamed:@"metro_hightSpot"]];
+    return imageView;
+}
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 3 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.h

@@ -6,6 +6,7 @@
 //
 
 #import <UIKit/UIKit.h>
+#import "WidgetDotView.h"
 
 @protocol MetronomeFunctionDelegate <NSObject>
 
@@ -20,6 +21,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface WidgetFunctionView : UIView
 
+@property (nonatomic, assign) KSMetronomeType currentMetronomeType;
+
 @property (nonatomic, assign) int speed;
 
 @property (weak, nonatomic) IBOutlet UIButton *signatureButton;

+ 47 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.m

@@ -65,6 +65,53 @@
     }
 }
 
+- (void)setCurrentMetronomeType:(KSMetronomeType)currentMetronomeType {
+    _currentMetronomeType = currentMetronomeType;
+    switch (currentMetronomeType) {
+        case KSMetronomeType1V2:
+        {
+            [self.signatureButton setTitle:@"1/2" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType2V2:
+        {
+            [self.signatureButton setTitle:@"2/2" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType1V4:
+        {
+            [self.signatureButton setTitle:@"1/4" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType2V4:
+        {
+            [self.signatureButton setTitle:@"2/4" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType3V4:
+        {
+            [self.signatureButton setTitle:@"3/4" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType4V4:
+        {
+            [self.signatureButton setTitle:@"4/4" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType3V8:
+        {
+            [self.signatureButton setTitle:@"3/8" forState:UIControlStateNormal];
+        }
+            break;
+        case KSMetronomeType6V8:
+        {
+            [self.signatureButton setTitle:@"6/8" forState:UIControlStateNormal];
+        }
+            break;
+        default:
+            break;
+    }
+}
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 1 - 1
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetFunctionView.xib

@@ -33,7 +33,7 @@
                     </constraints>
                     <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
                     <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                    <state key="normal" title="6/4" backgroundImage="metronome_bg">
+                    <state key="normal" title="4/4" backgroundImage="metronome_bg">
                         <color key="titleColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     </state>
                     <connections>

+ 4 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.h

@@ -9,10 +9,14 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+typedef void(^WidgeNavCallback)(void);
+
 @interface WidgetNavView : UIView
 
 + (instancetype)shareInstance;
 
+- (void)navBackAction:(WidgeNavCallback)callback;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 17 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.m

@@ -7,6 +7,12 @@
 
 #import "WidgetNavView.h"
 
+@interface WidgetNavView ()
+
+@property (nonatomic, copy) WidgeNavCallback callback;
+
+@end
+
 @implementation WidgetNavView
 
 
@@ -15,6 +21,17 @@
     return view;
 }
 
+- (void)navBackAction:(WidgeNavCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+- (IBAction)backAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 3 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetNavView.xib

@@ -25,6 +25,9 @@
                                 <constraint firstAttribute="width" constant="44" id="j2f-oU-zP6"/>
                             </constraints>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="SpQ-th-fns"/>
+                            </connections>
                         </button>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="节拍器" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yk0-dS-WZy">
                             <rect key="frame" x="179" y="11" width="56" height="22"/>

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetSpeedView.h

@@ -6,7 +6,7 @@
 //
 
 #import <UIKit/UIKit.h>
-
+#import "WidgetDotView.h"
 // 代理
 @protocol MetronomeControlViewDelegate <NSObject>
 
@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
 + (instancetype)shareInstance;
 
 /** 节拍类型 */
-//@property (nonatomic, assign) KSMetronomeType currentType;
+@property (nonatomic, assign) KSMetronomeType currentType;
 
 /** 代理 */
 @property (nonatomic, weak) id <MetronomeControlViewDelegate> delegate;

+ 27 - 32
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/WidgetSpeedView.m

@@ -98,38 +98,33 @@
 }
 
 
-//- (void)setCurrentType:(KSMetronomeType)currentType {
-//    _currentType = currentType;
-//    switch (currentType) {
-//        case KSMetronomeType1V4:
-//        {
-//            self.beatLabel.text = @"1 | 4";
-//        }
-//            break;
-//        case KSMetronomeType2V4:
-//        {
-//            self.beatLabel.text = @"2 | 4";
-//        }
-//            break;
-//        case KSMetronomeType3V4:
-//        {
-//            self.beatLabel.text = @"3 | 4";
-//        }
-//            break;
-//        case KSMetronomeType4V4:
-//        {
-//            self.beatLabel.text = @"4 | 4";
-//        }
-//            break;
-//        case KSMetronomeType6V8:
-//        {
-//            self.beatLabel.text = @"6 | 8";
-//        }
-//            break;
-//        default:
-//            break;
-//    }
-//}
+- (void)setCurrentType:(KSMetronomeType)currentType {
+    _currentType = currentType;
+    switch (currentType) {
+        case KSMetronomeType1V2:
+        case KSMetronomeType2V2:
+        {
+            [self.nodeImage setImage:[UIImage imageNamed:@"half_node"]];
+        }
+            break;
+        case KSMetronomeType1V4:
+        case KSMetronomeType2V4:
+        case KSMetronomeType3V4:
+        case KSMetronomeType4V4:
+        {
+            [self.nodeImage setImage:[UIImage imageNamed:@"quarter_node"]];
+        }
+            break;
+        case KSMetronomeType3V8:
+        case KSMetronomeType6V8:
+        {
+            [self.nodeImage setImage:[UIImage imageNamed:@"eighth_node"]];
+        }
+            break;
+        default:
+            break;
+    }
+}
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.