Browse Source

节拍器支持节奏

Steven 10 months ago
parent
commit
b3a6f43557
94 changed files with 1461 additions and 752 deletions
  1. 25 21
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. 2 2
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/Contents.json
  3. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/beat_button_bg@2x.png
  4. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/beat_button_bg@3x.png
  5. 2 2
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/Contents.json
  6. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/bpm_desc@2x.png
  7. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/bpm_desc@3x.png
  8. 4 4
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/Contents.json
  9. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/metronome_bg_s@2x.png
  10. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/metronome_bg_s@3x.png
  11. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_volume.imageset/metronome_volume@2x.png
  12. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_volume.imageset/metronome_volume@3x.png
  13. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/slider_image.imageset/slider_image@2x.png
  14. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/slider_image.imageset/slider_image@3x.png
  15. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_add.imageset/speed_add@2x.png
  16. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_add.imageset/speed_add@3x.png
  17. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_minus.imageset/speed_minus@2x.png
  18. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_minus.imageset/speed_minus@3x.png
  19. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome_image.imageset/metronome_image@2x.png
  20. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome_image.imageset/metronome_image@3x.png
  21. 6 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/Contents.json
  22. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/Contents.json
  23. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/rhythm_dottedEighth_and_sixteenthNote@2x.png
  24. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/rhythm_dottedEighth_and_sixteenthNote@3x.png
  25. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/Contents.json
  26. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/rhythm_dottedEighth_and_sixteenthNote_selected@2x.png
  27. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/rhythm_dottedEighth_and_sixteenthNote_selected@3x.png
  28. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/Contents.json
  29. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/rhythm_eighth_and_two_sixteenthNote@2x.png
  30. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/rhythm_eighth_and_two_sixteenthNote@3x.png
  31. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/Contents.json
  32. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/rhythm_eighth_and_two_sixteenthNote_selected@2x.png
  33. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/rhythm_eighth_and_two_sixteenthNote_selected@3x.png
  34. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/Contents.json
  35. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/rhythm_four_sixteenthNote@2x.png
  36. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/rhythm_four_sixteenthNote@3x.png
  37. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/Contents.json
  38. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/rhythm_four_sixteenthNote_selected@2x.png
  39. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/rhythm_four_sixteenthNote_selected@3x.png
  40. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/Contents.json
  41. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/rhythm_quarterNote@2x.png
  42. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/rhythm_quarterNote@3x.png
  43. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/Contents.json
  44. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/rhythm_quarterNote_selected@2x.png
  45. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/rhythm_quarterNote_selected@3x.png
  46. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/Contents.json
  47. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/rhythm_quarter_and_eighth_riplet@2x.png
  48. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/rhythm_quarter_and_eighth_riplet@3x.png
  49. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/Contents.json
  50. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/rhythm_quarter_and_eighth_riplet_selected@2x.png
  51. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/rhythm_quarter_and_eighth_riplet_selected@3x.png
  52. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/Contents.json
  53. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/rhythm_quarter_riplet@2x.png
  54. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/rhythm_quarter_riplet@3x.png
  55. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/Contents.json
  56. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/rhythm_quarter_riplet_selected@2x.png
  57. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/rhythm_quarter_riplet_selected@3x.png
  58. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/Contents.json
  59. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/rhythm_two_eighthNote@2x.png
  60. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/rhythm_two_eighthNote@3x.png
  61. 22 0
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/Contents.json
  62. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/rhythm_two_eighthNote_selected@2x.png
  63. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/rhythm_two_eighthNote_selected@3x.png
  64. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/tone_tuning.imageset/tone_tuning@2x.png
  65. BIN
      KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/tone_tuning.imageset/tone_tuning@3x.png
  66. 0 16
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/SmallToolViewController.h
  67. 0 67
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/SmallToolViewController.m
  68. 18 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/ToneTuningViewController.m
  69. 39 24
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/WidgetViewController.m
  70. 15 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/KSMetronomePlayer.h
  71. 201 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/KSMetronomePlayer.m
  72. 10 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/MetronomeManager.h
  73. 34 47
      KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/MetronomeManager.m
  74. 25 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.h
  75. 139 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.m
  76. 111 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.xib
  77. 26 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.h
  78. 78 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.m
  79. 73 0
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.xib
  80. 7 7
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetBottomButtonView.xib
  81. 11 8
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.h
  82. 38 85
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.m
  83. 97 97
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.xib
  84. 3 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetNavView.xib
  85. 0 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.h
  86. 30 2
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.m
  87. 44 29
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.xib
  88. 0 27
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.h
  89. 0 77
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.m
  90. 0 168
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.xib
  91. 3 2
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.h
  92. 7 6
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.m
  93. 102 43
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.xib
  94. 3 3
      KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/TuningNavView.xib

+ 25 - 21
KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj

@@ -339,16 +339,13 @@
 		BC2DFF5D28C097DC0056105A /* styleAnimation.json in Resources */ = {isa = PBXBuildFile; fileRef = BC2DFF5C28C097DC0056105A /* styleAnimation.json */; };
 		BC31BF0D2B21925700F7D538 /* WidgetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEC62B21925700F7D538 /* WidgetViewController.m */; };
 		BC31BF0E2B21925700F7D538 /* ToneTuningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEC72B21925700F7D538 /* ToneTuningViewController.m */; };
-		BC31BF0F2B21925700F7D538 /* SmallToolViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEC92B21925700F7D538 /* SmallToolViewController.m */; };
 		BC31BF102B21925700F7D538 /* MetronomeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BECB2B21925700F7D538 /* MetronomeManager.m */; };
 		BC31BF112B21925700F7D538 /* tick.wav in Resources */ = {isa = PBXBuildFile; fileRef = BC31BECE2B21925700F7D538 /* tick.wav */; };
 		BC31BF122B21925700F7D538 /* tock.wav in Resources */ = {isa = PBXBuildFile; fileRef = BC31BECF2B21925700F7D538 /* tock.wav */; };
 		BC31BF152B21925700F7D538 /* KSMetronomePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BED22B21925700F7D538 /* KSMetronomePlayer.m */; };
-		BC31BF162B21925700F7D538 /* SmallToolBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BED52B21925700F7D538 /* SmallToolBodyView.m */; };
 		BC31BF172B21925700F7D538 /* KSGaugeView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEDA2B21925700F7D538 /* KSGaugeView.m */; };
 		BC31BF182B21925700F7D538 /* KSGaugeColorView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEDB2B21925700F7D538 /* KSGaugeColorView.m */; };
 		BC31BF192B21925700F7D538 /* KSGaugeSectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEDC2B21925700F7D538 /* KSGaugeSectorView.m */; };
-		BC31BF1A2B21925700F7D538 /* SmallToolBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC31BEDD2B21925700F7D538 /* SmallToolBodyView.xib */; };
 		BC31BF1B2B21925700F7D538 /* TuningNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC31BEDF2B21925700F7D538 /* TuningNavView.xib */; };
 		BC31BF1C2B21925700F7D538 /* TuningNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC31BEE12B21925700F7D538 /* TuningNavView.m */; };
 		BC31BF1D2B21925700F7D538 /* TuningForkSettingView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC31BEE22B21925700F7D538 /* TuningForkSettingView.xib */; };
@@ -428,6 +425,10 @@
 		BC40BA202812552300DEC0D1 /* KSHomeButton.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC40BA1D2812552200DEC0D1 /* KSHomeButton.xib */; };
 		BC40BA23281255F700DEC0D1 /* HomeCourseTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC40BA22281255F700DEC0D1 /* HomeCourseTipsView.m */; };
 		BC40BA252812560100DEC0D1 /* HomeCourseTipsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC40BA242812560100DEC0D1 /* HomeCourseTipsView.xib */; };
+		BC42CAA42BEC8272001F076E /* RhythmView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC42CA9E2BEC8271001F076E /* RhythmView.xib */; };
+		BC42CAA52BEC8272001F076E /* RhythmChooseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC42CAA02BEC8271001F076E /* RhythmChooseView.xib */; };
+		BC42CAA62BEC8272001F076E /* RhythmChooseView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC42CAA12BEC8272001F076E /* RhythmChooseView.m */; };
+		BC42CAA72BEC8272001F076E /* RhythmView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC42CAA22BEC8272001F076E /* RhythmView.m */; };
 		BC43CAC92A88C9570011EB5D /* KSTXGroupChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC43CAC52A88C9570011EB5D /* KSTXGroupChatViewController.m */; };
 		BC43CACA2A88C9570011EB5D /* KSTXC2CChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC43CAC62A88C9570011EB5D /* KSTXC2CChatViewController.m */; };
 		BC43CACB2A88C9570011EB5D /* KSTXBaseChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC43CAC72A88C9570011EB5D /* KSTXBaseChatViewController.m */; };
@@ -1590,25 +1591,21 @@
 		BC2DFF5A28C097D60056105A /* talentAnimation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = talentAnimation.json; sourceTree = "<group>"; };
 		BC2DFF5C28C097DC0056105A /* styleAnimation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = styleAnimation.json; sourceTree = "<group>"; };
 		BC31BEC42B21925700F7D538 /* ToneTuningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToneTuningViewController.h; sourceTree = "<group>"; };
-		BC31BEC52B21925700F7D538 /* SmallToolViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallToolViewController.h; sourceTree = "<group>"; };
 		BC31BEC62B21925700F7D538 /* WidgetViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WidgetViewController.m; sourceTree = "<group>"; };
 		BC31BEC72B21925700F7D538 /* ToneTuningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToneTuningViewController.m; sourceTree = "<group>"; };
 		BC31BEC82B21925700F7D538 /* WidgetViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetViewController.h; sourceTree = "<group>"; };
-		BC31BEC92B21925700F7D538 /* SmallToolViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SmallToolViewController.m; sourceTree = "<group>"; };
 		BC31BECB2B21925700F7D538 /* MetronomeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MetronomeManager.m; sourceTree = "<group>"; };
 		BC31BECC2B21925700F7D538 /* KSMetronomePlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSMetronomePlayer.h; sourceTree = "<group>"; };
 		BC31BECE2B21925700F7D538 /* tick.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tick.wav; sourceTree = "<group>"; };
 		BC31BECF2B21925700F7D538 /* tock.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = tock.wav; sourceTree = "<group>"; };
 		BC31BED22B21925700F7D538 /* KSMetronomePlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSMetronomePlayer.m; sourceTree = "<group>"; };
 		BC31BED32B21925700F7D538 /* MetronomeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetronomeManager.h; sourceTree = "<group>"; };
-		BC31BED52B21925700F7D538 /* SmallToolBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SmallToolBodyView.m; sourceTree = "<group>"; };
 		BC31BED72B21925700F7D538 /* KSGaugeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSGaugeView.h; sourceTree = "<group>"; };
 		BC31BED82B21925700F7D538 /* KSGaugeColorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSGaugeColorView.h; sourceTree = "<group>"; };
 		BC31BED92B21925700F7D538 /* KSGaugeSectorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSGaugeSectorView.h; sourceTree = "<group>"; };
 		BC31BEDA2B21925700F7D538 /* KSGaugeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSGaugeView.m; sourceTree = "<group>"; };
 		BC31BEDB2B21925700F7D538 /* KSGaugeColorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSGaugeColorView.m; sourceTree = "<group>"; };
 		BC31BEDC2B21925700F7D538 /* KSGaugeSectorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSGaugeSectorView.m; sourceTree = "<group>"; };
-		BC31BEDD2B21925700F7D538 /* SmallToolBodyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SmallToolBodyView.xib; sourceTree = "<group>"; };
 		BC31BEDF2B21925700F7D538 /* TuningNavView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TuningNavView.xib; sourceTree = "<group>"; };
 		BC31BEE02B21925700F7D538 /* TunerSettingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TunerSettingView.h; sourceTree = "<group>"; };
 		BC31BEE12B21925700F7D538 /* TuningNavView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TuningNavView.m; sourceTree = "<group>"; };
@@ -1623,7 +1620,6 @@
 		BC31BEEA2B21925700F7D538 /* TuningNavView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TuningNavView.h; sourceTree = "<group>"; };
 		BC31BEEB2B21925700F7D538 /* ToneTuningBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToneTuningBodyView.m; sourceTree = "<group>"; };
 		BC31BEEC2B21925700F7D538 /* ToneTuningBodyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ToneTuningBodyView.xib; sourceTree = "<group>"; };
-		BC31BEED2B21925700F7D538 /* SmallToolBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallToolBodyView.h; sourceTree = "<group>"; };
 		BC31BEEF2B21925700F7D538 /* WMGaugeViewStyle3D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMGaugeViewStyle3D.h; sourceTree = "<group>"; };
 		BC31BEF02B21925700F7D538 /* WMGaugeViewStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMGaugeViewStyle.h; sourceTree = "<group>"; };
 		BC31BEF12B21925700F7D538 /* WMGaugeViewStyleFlatThin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WMGaugeViewStyleFlatThin.m; sourceTree = "<group>"; };
@@ -1740,6 +1736,12 @@
 		BC40BA21281255F700DEC0D1 /* HomeCourseTipsView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeCourseTipsView.h; sourceTree = "<group>"; };
 		BC40BA22281255F700DEC0D1 /* HomeCourseTipsView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeCourseTipsView.m; sourceTree = "<group>"; };
 		BC40BA242812560100DEC0D1 /* HomeCourseTipsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeCourseTipsView.xib; sourceTree = "<group>"; };
+		BC42CA9E2BEC8271001F076E /* RhythmView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RhythmView.xib; sourceTree = "<group>"; };
+		BC42CA9F2BEC8271001F076E /* RhythmChooseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RhythmChooseView.h; sourceTree = "<group>"; };
+		BC42CAA02BEC8271001F076E /* RhythmChooseView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RhythmChooseView.xib; sourceTree = "<group>"; };
+		BC42CAA12BEC8272001F076E /* RhythmChooseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RhythmChooseView.m; sourceTree = "<group>"; };
+		BC42CAA22BEC8272001F076E /* RhythmView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RhythmView.m; sourceTree = "<group>"; };
+		BC42CAA32BEC8272001F076E /* RhythmView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RhythmView.h; sourceTree = "<group>"; };
 		BC43CAC32A88C9570011EB5D /* KSTXBaseChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSTXBaseChatViewController.h; sourceTree = "<group>"; };
 		BC43CAC42A88C9570011EB5D /* KSTXC2CChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSTXC2CChatViewController.h; sourceTree = "<group>"; };
 		BC43CAC52A88C9570011EB5D /* KSTXGroupChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSTXGroupChatViewController.m; sourceTree = "<group>"; };
@@ -4266,8 +4268,6 @@
 		BC31BEC32B21925700F7D538 /* Controller */ = {
 			isa = PBXGroup;
 			children = (
-				BC31BEC52B21925700F7D538 /* SmallToolViewController.h */,
-				BC31BEC92B21925700F7D538 /* SmallToolViewController.m */,
 				BC31BEC42B21925700F7D538 /* ToneTuningViewController.h */,
 				BC31BEC72B21925700F7D538 /* ToneTuningViewController.m */,
 				BC31BEC82B21925700F7D538 /* WidgetViewController.h */,
@@ -4302,9 +4302,6 @@
 			children = (
 				BC31BED62B21925700F7D538 /* KSGaugeView */,
 				BC31BEF62B21925700F7D538 /* Metronome */,
-				BC31BEED2B21925700F7D538 /* SmallToolBodyView.h */,
-				BC31BED52B21925700F7D538 /* SmallToolBodyView.m */,
-				BC31BEDD2B21925700F7D538 /* SmallToolBodyView.xib */,
 				BC31BEDE2B21925700F7D538 /* toneTuning */,
 				BC31BEEE2B21925700F7D538 /* WMGaugeView */,
 			);
@@ -4378,6 +4375,12 @@
 				BC31BEFB2B21925700F7D538 /* WidgetSpeedView.h */,
 				BC31BF072B21925700F7D538 /* WidgetSpeedView.m */,
 				BC31BEF92B21925700F7D538 /* WidgetSpeedView.xib */,
+				BC42CA9F2BEC8271001F076E /* RhythmChooseView.h */,
+				BC42CAA12BEC8272001F076E /* RhythmChooseView.m */,
+				BC42CAA02BEC8271001F076E /* RhythmChooseView.xib */,
+				BC42CAA32BEC8272001F076E /* RhythmView.h */,
+				BC42CAA22BEC8272001F076E /* RhythmView.m */,
+				BC42CA9E2BEC8271001F076E /* RhythmView.xib */,
 			);
 			path = Metronome;
 			sourceTree = "<group>";
@@ -4385,12 +4388,12 @@
 		BC31BF002B21925700F7D538 /* RoundSlider */ = {
 			isa = PBXGroup;
 			children = (
-				BC31BF012B21925700F7D538 /* IACircularSlider.h */,
 				BC31BF022B21925700F7D538 /* IACircleSliderThumbLayer.h */,
-				BC31BF032B21925700F7D538 /* IACircularSliderTrackLayer.m */,
+				BC31BF062B21925700F7D538 /* IACircleSliderThumbLayer.m */,
+				BC31BF012B21925700F7D538 /* IACircularSlider.h */,
 				BC31BF042B21925700F7D538 /* IACircularSlider.m */,
 				BC31BF052B21925700F7D538 /* IACircularSliderTrackLayer.h */,
-				BC31BF062B21925700F7D538 /* IACircleSliderThumbLayer.m */,
+				BC31BF032B21925700F7D538 /* IACircularSliderTrackLayer.m */,
 			);
 			path = RoundSlider;
 			sourceTree = "<group>";
@@ -5255,10 +5258,10 @@
 		BC8A4579283DC33400094BBB /* SpeedSlider */ = {
 			isa = PBXGroup;
 			children = (
-				BC8A457A283DC33400094BBB /* KSTrackingSlider.h */,
+				BC8A457D283DC33400094BBB /* KSSliderView.h */,
 				BC8A457B283DC33400094BBB /* KSSliderView.m */,
+				BC8A457A283DC33400094BBB /* KSTrackingSlider.h */,
 				BC8A457C283DC33400094BBB /* KSTrackingSlider.m */,
-				BC8A457D283DC33400094BBB /* KSSliderView.h */,
 			);
 			path = SpeedSlider;
 			sourceTree = "<group>";
@@ -6406,6 +6409,7 @@
 				BC71D254288804CD0010F14B /* img_4.png in Resources */,
 				2723B62127F157D500E0B90B /* NoticeEditBodyView.xib in Resources */,
 				BC802DB328BC70370079E350 /* HomeHotTalentCell.xib in Resources */,
+				BC42CAA52BEC8272001F076E /* RhythmChooseView.xib in Resources */,
 				BC2DFF5B28C097D60056105A /* talentAnimation.json in Resources */,
 				BC89AC152AB0844700B077AF /* TenantHotMusicView.xib in Resources */,
 				BCCE95D32AB0410600AB6385 /* darkEmptyAnimation.json in Resources */,
@@ -6514,7 +6518,6 @@
 				BC8418412AC2D96C00D8F90E /* PasswordCheckBodyView.xib in Resources */,
 				BCC0F6622A8CD8F500C4EFA4 /* MainDisplayView.xib in Resources */,
 				BC71D278288804CD0010F14B /* img_20.png in Resources */,
-				BC31BF1A2B21925700F7D538 /* SmallToolBodyView.xib in Resources */,
 				BC71D247288804CD0010F14B /* img_0.png in Resources */,
 				27F9032D27E87C2E00C08A19 /* KSNetworkAlert.xib in Resources */,
 				BC71D260288804CD0010F14B /* img_44.png in Resources */,
@@ -6536,6 +6539,7 @@
 				BCC583C728A9EC6400BAB4CF /* cloud_animation_12.png in Resources */,
 				BCECE24B2B3D670500C0D555 /* KSSortButtonView.xib in Resources */,
 				BC71D26D288804CD0010F14B /* img_18.png in Resources */,
+				BC42CAA42BEC8272001F076E /* RhythmView.xib in Resources */,
 				BC9AA0B72ABC1C2A00CD954D /* GroupQuitAlert.xib in Resources */,
 				BCB6348127F6D29600ACFDCF /* LiveSeatApplyCell.xib in Resources */,
 				BC8A45A4283DC33400094BBB /* KSCloudSettingView.xib in Resources */,
@@ -6935,7 +6939,6 @@
 				BC12636D28FEA20100509E90 /* RecentMusicView.m in Sources */,
 				BC8C2C5F2823F57100FBA5D5 /* MyAddressListCell.m in Sources */,
 				275FA22C27E7356B00CFEA2E /* CourseViewController.m in Sources */,
-				BC31BF162B21925700F7D538 /* SmallToolBodyView.m in Sources */,
 				BC106C102A933829000759A9 /* TXLiveMessageUnBlockUser.m in Sources */,
 				BC84183F2AC2D96600D8F90E /* PasswordCheckBodyView.m in Sources */,
 				BCD457A1286313D70010B493 /* NotiferNavView.m in Sources */,
@@ -7069,6 +7072,7 @@
 				BC106C162A933829000759A9 /* TXLiveTextMessage.m in Sources */,
 				BC11924E280EDD5500A716F7 /* HomeworkListViewController.m in Sources */,
 				2723B5BC27F157B100E0B90B /* GroupCreateView.m in Sources */,
+				BC42CAA72BEC8272001F076E /* RhythmView.m in Sources */,
 				BC0D95192AC280CB00E54D3F /* KSWebLoadRefreshView.m in Sources */,
 				BC802D8D28B896460079E350 /* LiveApplyView.m in Sources */,
 				2723B63027F157D500E0B90B /* GroupApplyChooseAllCell.m in Sources */,
@@ -7144,7 +7148,6 @@
 				BCCC36272AAF4346000D60CA /* KSTenantHomeViewController.m in Sources */,
 				BC38C3EA2AF893B400ABFCC2 /* KSVideoPlayerView.m in Sources */,
 				BCFDA61228BC8FCE0022B497 /* HomeHotVideoCell.m in Sources */,
-				BC31BF0F2B21925700F7D538 /* SmallToolViewController.m in Sources */,
 				BCECE24D2B3D670500C0D555 /* FeedbackListNavView.m in Sources */,
 				BC106C182A933829000759A9 /* TXLiveMessageShopRush.m in Sources */,
 				BC756CB928FE7D1D00AA9ECB /* KSChatUserDetailViewController.m in Sources */,
@@ -7291,6 +7294,7 @@
 				27F9032F27E87C2E00C08A19 /* AudioPlayManager.m in Sources */,
 				BCC0F66A2A8CD8F500C4EFA4 /* TXDanMuView.m in Sources */,
 				BC28885C2A80F9880064B773 /* AppDelegate+AppService.m in Sources */,
+				BC42CAA62BEC8272001F076E /* RhythmChooseView.m in Sources */,
 				2779357C27E324A70010E277 /* NSString+MD5.m in Sources */,
 				BC0D952E2AC2AA6F00E54D3F /* ForgetPasswordViewController.m in Sources */,
 				BC106C112A933829000759A9 /* TXConstMessage.m in Sources */,

+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome_image.imageset/Contents.json → KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/Contents.json

@@ -5,12 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "metronome_image@2x.png",
+      "filename" : "beat_button_bg@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "metronome_image@3x.png",
+      "filename" : "beat_button_bg@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/beat_button_bg@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/beat_button_bg.imageset/beat_button_bg@3x.png


+ 2 - 2
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/tone_tuning.imageset/Contents.json → KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/Contents.json

@@ -5,12 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "tone_tuning@2x.png",
+      "filename" : "bpm_desc@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "tone_tuning@3x.png",
+      "filename" : "bpm_desc@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/bpm_desc@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/bpm_desc.imageset/bpm_desc@3x.png


+ 4 - 4
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/Contents.json

@@ -9,8 +9,8 @@
       "idiom" : "universal",
       "resizing" : {
         "cap-insets" : {
-          "left" : 72,
-          "right" : 72
+          "left" : 59,
+          "right" : 59
         },
         "center" : {
           "mode" : "tile",
@@ -25,8 +25,8 @@
       "idiom" : "universal",
       "resizing" : {
         "cap-insets" : {
-          "left" : 107,
-          "right" : 107
+          "left" : 88,
+          "right" : 88
         },
         "center" : {
           "mode" : "tile",

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/metronome_bg_s@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_bg_s.imageset/metronome_bg_s@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_volume.imageset/metronome_volume@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/metronome_volume.imageset/metronome_volume@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/slider_image.imageset/slider_image@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/slider_image.imageset/slider_image@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_add.imageset/speed_add@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_add.imageset/speed_add@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_minus.imageset/speed_minus@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome/speed_minus.imageset/speed_minus@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome_image.imageset/metronome_image@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/metronome_image.imageset/metronome_image@3x.png


+ 6 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/rhythm_dottedEighth_and_sixteenthNote@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote.imageset/rhythm_dottedEighth_and_sixteenthNote@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/rhythm_dottedEighth_and_sixteenthNote_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_dottedEighth_and_sixteenthNote_selected.imageset/rhythm_dottedEighth_and_sixteenthNote_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/rhythm_eighth_and_two_sixteenthNote@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote.imageset/rhythm_eighth_and_two_sixteenthNote@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/rhythm_eighth_and_two_sixteenthNote_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_eighth_and_two_sixteenthNote_selected.imageset/rhythm_eighth_and_two_sixteenthNote_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/rhythm_four_sixteenthNote@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote.imageset/rhythm_four_sixteenthNote@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/rhythm_four_sixteenthNote_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_four_sixteenthNote_selected.imageset/rhythm_four_sixteenthNote_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/rhythm_quarterNote@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote.imageset/rhythm_quarterNote@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/rhythm_quarterNote_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarterNote_selected.imageset/rhythm_quarterNote_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/rhythm_quarter_and_eighth_riplet@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet.imageset/rhythm_quarter_and_eighth_riplet@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/rhythm_quarter_and_eighth_riplet_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_and_eighth_riplet_selected.imageset/rhythm_quarter_and_eighth_riplet_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/rhythm_quarter_riplet@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet.imageset/rhythm_quarter_riplet@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/rhythm_quarter_riplet_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_quarter_riplet_selected.imageset/rhythm_quarter_riplet_selected@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/rhythm_two_eighthNote@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote.imageset/rhythm_two_eighthNote@3x.png


+ 22 - 0
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/Contents.json

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

BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/rhythm_two_eighthNote_selected@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/rhythmNote/rhythm_two_eighthNote_selected.imageset/rhythm_two_eighthNote_selected@3x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/tone_tuning.imageset/tone_tuning@2x.png


BIN
KulexiuForStudent/KulexiuForStudent/Assets.xcassets/SmallTool/tone_tuning.imageset/tone_tuning@3x.png


+ 0 - 16
KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/SmallToolViewController.h

@@ -1,16 +0,0 @@
-//
-//  SmallToolViewController.h
-//  KulexiuForStudent
-//
-//  Created by 王智 on 2022/10/13.
-//
-
-#import "KSBaseViewController.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface SmallToolViewController : KSBaseViewController
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 67
KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/SmallToolViewController.m

@@ -1,67 +0,0 @@
-//
-//  SmallToolViewController.m
-//  KulexiuForStudent
-//
-//  Created by 王智 on 2022/10/13.
-//
-
-#import "SmallToolViewController.h"
-#import "WidgetViewController.h"
-#import "SmallToolBodyView.h"
-#import "ToneTuningViewController.h"
-
-@interface SmallToolViewController ()
-
-
-@end
-
-@implementation SmallToolViewController
-
-- (void)viewDidLoad {
-    [super viewDidLoad];
-    // Do any additional setup after loading the view.
-    [self allocTitle:@"小工具"];
-    [self configUI];
-}
-
-- (void)configUI {
-    SmallToolBodyView *bodyView = [SmallToolBodyView shareInstance];
-    bodyView.frame = CGRectMake(0, 0, KPortraitWidth, KPortraitHeight - kNaviBarHeight);
-    [self.scrollView addSubview:bodyView];
-    
-    MJWeakSelf;
-    [bodyView chooseToolCallback:^(TOOLTYPE type) {
-        [weakSelf chooseToolFunction:type];
-    }];
-}
-
-- (void)chooseToolFunction:(TOOLTYPE)type {
-    switch (type) {
-        case TOOLTYPE_METRONOME:
-        {
-            WidgetViewController *ctrl = [[WidgetViewController alloc] init];
-            [self.navigationController pushViewController:ctrl animated:YES];
-        }
-            break;
-        case TOOLTYPE_TONE:
-        {
-            ToneTuningViewController *ctrl = [[ToneTuningViewController alloc] init];
-            [self.navigationController pushViewController:ctrl animated:YES];
-        }
-            break;
-        default:
-            break;
-    }
-}
-
-/*
-#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

+ 18 - 3
KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/ToneTuningViewController.m

@@ -118,12 +118,10 @@
 
     [self.scrollView addSubview:self.bodyView];
     self.bodyView.A4Frequence = self.A4Frequence;
-    CGFloat viewHeight = [ToneTuningBodyView getViewHeight];
     [self.bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.right.mas_equalTo(self.view);
         make.top.mas_equalTo(self.scrollView.mas_top);
         make.bottom.mas_equalTo(self.scrollView.mas_bottom);
-        make.height.mas_equalTo(viewHeight);
     }];
     [self.bodyView.plateView addSubview:self.plateView];
     [self.plateView mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -138,9 +136,10 @@
 
 - (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
-    self.bodyView.speedValue.text = [NSString stringWithFormat:@"%d",METRONOME_MANAGER.speed];
+    self.bodyView.speedValue.text = [NSString stringWithFormat:@"BPM=%d",METRONOME_MANAGER.speed];
     self.bodyView.metronomePlayStatus = METRONOME_MANAGER.isPlaying;
     self.bodyView.beatType.text = [METRONOME_MANAGER getTypeString];
+    [self changeRhythm];
 }
 
 - (void)viewWillDisappear:(BOOL)animated {
@@ -332,6 +331,11 @@
             [self beatChoose];
         }
             break;
+        case TUNINGACTION_RHYTHMCHOOSE: // 选择节奏
+        {
+            [self chooseRhythmType];
+        }
+            break;
         case TUNINGACTION_METRONOME:
         {
             WidgetViewController *ctrl = [[WidgetViewController alloc] init];
@@ -343,7 +347,18 @@
     }
 }
 
+- (void)chooseRhythmType {
+    [METRONOME_MANAGER rhythmChooseCallback:^(RHYTHM_TYPE thythmType) {
+        [self stopPlayBeat];
+        [self changeRhythm];
+    }];
+}
 
+- (void)changeRhythm {
+    // 显示
+    NSString *imageName = [METRONOME_MANAGER imageWithType:METRONOME_MANAGER.rhythmType];
+    [self.bodyView.rhythmImage setImage:[UIImage imageNamed:imageName]];
+}
 
 - (void)startForkPlay {
     

+ 39 - 24
KulexiuForStudent/KulexiuForStudent/Module/Widget/Controller/WidgetViewController.m

@@ -10,7 +10,6 @@
 #import "WidgetDotView.h"
 #import "WidgetSpeedView.h"
 #import "WidgetFunctionView.h"
-#import <KSToolLibrary/KSChoosePicker.h>
 #import "WidgetBottomButtonView.h"
 #import <AVFoundation/AVFoundation.h>
 #import "KSMetronomePlayer.h"
@@ -28,9 +27,9 @@
 
 @property (nonatomic, assign) int speed;
 
-@property (nonatomic, assign) KSWidgeMetronomeType metronomeType;
+@property (nonatomic, assign) RHYTHM_TYPE rhythmType;
 
-@property (nonatomic, strong) KSChoosePicker *pickerView;
+@property (nonatomic, assign) NSInteger beatNumber;
 
 @property (nonatomic, strong) WidgetBottomButtonView *bottomView;
 
@@ -45,8 +44,8 @@
     [self configUI];
 }
 
-- (void)viewDidAppear:(BOOL)animated {
-    [super viewDidAppear:animated];
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
     [self setDefaultConfig];
 }
 
@@ -57,12 +56,13 @@
 - (void)setDefaultConfig {
     _speed = METRONOME_MANAGER.speed;
     self.speedView.speed = self.speed;
-    self.functionView.speed = self.speed;
-    self.metronomeType = METRONOME_MANAGER.metronomeType;
+    self.rhythmType = METRONOME_MANAGER.rhythmType;
     [self changeBeat];
     self.functionView.volumeRate = METRONOME_MANAGER.playVolume;
     METRONOME_MANAGER.delegate = self;
     self.bottomView.isPlay = METRONOME_MANAGER.isPlaying;
+    self.functionView.beatLabel.text = [NSString stringWithFormat:@"%zd",METRONOME_MANAGER.beatNumber];
+    [self changeRhythmDisplay];
 }
 
 
@@ -83,27 +83,30 @@
         make.left.right.top.mas_equalTo(self.view);
         make.height.mas_equalTo(kNaviBarHeight);
     }];
-    CGFloat topSpace = IS_IPAD ? 100 : 10;
-    [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(topSpace);
-        make.height.mas_equalTo(44);
-    }];
     
+//    [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);
+//    }];
+    CGFloat topSpace = IS_IPAD ? 100 + 44 : 10 + 44;
+
     CGFloat speedViewHeight = [WidgetSpeedView getViewHeight];
     [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.top.mas_equalTo(self.dotView.mas_bottom);
+        make.top.mas_equalTo(self.navView.mas_bottom).offset(topSpace);
         make.height.mas_equalTo(speedViewHeight);
     }];
     
+    CGFloat functionHeight = [WidgetFunctionView getViewHeight];
     [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);
+        make.height.mas_equalTo(functionHeight);
     }];
     
     [self.view addSubview:self.bottomView];
@@ -121,13 +124,26 @@
 }
 
 - (void)clickChangeBeat {
-    [METRONOME_MANAGER beatChooseCallback:^(KSWidgeMetronomeType type) {
+    [METRONOME_MANAGER beatChooseCallback:^(NSInteger beatNumber) {
         [self stopBeat];
-        self.metronomeType = type;
+        self.beatNumber = beatNumber;
         [self changeBeat];
+        self.functionView.beatLabel.text = [NSString stringWithFormat:@"%zd",beatNumber];
     }];
 }
 
+- (void)clickChangeRhythm {
+    [METRONOME_MANAGER rhythmChooseCallback:^(RHYTHM_TYPE thythmType) {
+        [self stopBeat];
+        self.rhythmType = thythmType;
+        [self changeRhythmDisplay];
+    }];
+}
+
+- (void)changeRhythmDisplay {
+    [self.functionView.rhythmImage setImage:[UIImage imageNamed:[METRONOME_MANAGER imageWithType:METRONOME_MANAGER.rhythmType]]];
+}
+
 - (void)clickChangeSpeed:(int)speed {
     self.speed = speed;
     [self.speedView.slider resetInitially];
@@ -144,7 +160,6 @@
 
 - (void)updateSpeedUI {
     self.speedView.speed = self.speed;
-    self.functionView.speed = self.speed;
     METRONOME_MANAGER.speed = self.speed;
     [self stopBeat];
 }
@@ -213,12 +228,12 @@
 
 
 - (void)changeBeat {
-    [self.dotView updateSpotView:self.metronomeType];
-    self.functionView.currentMetronomeType = self.metronomeType;
-    self.speedView.currentType = self.metronomeType;
+    self.functionView.beatNumber = self.beatNumber;
 }
 
-
+- (void)changeRhythm {
+    self.functionView.rhythmType = self.rhythmType;
+}
 - (void)setSpeed:(int)speed {
     _speed = speed;
     [self stopBeat];
@@ -230,7 +245,7 @@
 }
 
 - (void)updateSpotHightState:(int)currentNo {
-    [self.dotView updateSpotViewHeightState:currentNo];
+//    [self.dotView updateSpotViewHeightState:currentNo];
 }
 
 - (void)dealloc {

+ 15 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/KSMetronomePlayer.h

@@ -8,6 +8,17 @@
 #import <Foundation/Foundation.h>
 #import "WidgetDotView.h"
 
+typedef NS_ENUM(NSInteger, RHYTHM_TYPE) {
+    RHYTHM_TYPE_ONE_QUARTERNOTES = 0, // 一个四分音符
+    RHYTHM_TYPE_TWO_EIGHTHNOTES = 1,  // 两个八分音符  时值 = 一个4分音符
+    RHYTHM_TYPE_QUARTERT_RIPLET = 2, //  8分音符三连音 时值 = 2个8分音符 = 一个4分音符
+    RHYTHM_TYPE_FOUR_SIXTEENTHNOTES = 3,  // 4个16分音符 时值 = 一个4分音符
+    RHYTHM_TYPE_QUARTER_AND_EIGHTHT_RIPLET = 4, // 4分音符+8分音符组成3连音 时值 = 2个8分音符 = 1个4分音符
+    RHYTHM_TYPE_DOTTEDEIGHTH_AND_SIXTEENTHNOTES = 5,  // 附点8分音符+16分音符 时值 =  1个4分音符
+    RHYTHM_TYPE_EIGHTH_AND_TWO_SIXTEENTHNOTES = 6,  // 八分音符 + 2个16分音符 时值 =  1个4分音符
+};
+
+
 NS_ASSUME_NONNULL_BEGIN
 
 @protocol KSMetronomePlayerDelegate <NSObject>
@@ -26,8 +37,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) float volume;
 
+@property (nonatomic, assign) NSInteger beatNumber;
+
 - (void)playAction:(int)bpm metronomeTyle:(KSWidgeMetronomeType)type;
 
+- (void)playRhythmAction:(int)speed rhythmType:(RHYTHM_TYPE)type beatNumber:(NSInteger)beatNumber;
+
 - (void)stopPlay;
 
 @end

+ 201 - 3
KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/KSMetronomePlayer.m

@@ -7,6 +7,7 @@
 
 #import "KSMetronomePlayer.h"
 #import <AVFoundation/AVFoundation.h>
+//#import "KSLogManager.h"
 
 @interface KSMetronomePlayer ()
 
@@ -87,8 +88,28 @@
 
     [self.audioEngine attachNode:self.playerNode];
     [self.audioEngine connect:self.playerNode to:self.audioEngine.mainMixerNode format:self.audioDIFile.processingFormat];
-    
-    [self.audioEngine startAndReturnError:nil];
+    NSError *error = nil;
+    [self.audioEngine startAndReturnError:&error];
+    if (error) {
+#pragma mark ----- 错误上报
+//        NSLog(@"-- error desc - %@", error.description);
+//        NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+//        [parm setValue:UserDefault(UIDKey) forKey:@"userId"];
+//        [parm setValue:@"metronomePlay" forKey:@"Location"];
+//        [parm setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] forKey:@"version"];
+//        [parm setValue:@(error.code) forKey:@"errorCode"];
+//        [parm setValue:error.description forKey:@"errorDesc"];
+//        NSString *content = [parm mj_JSONString];
+//        NSMutableDictionary *uploadParm = [KSLogManager generateLogMessageWithContent:content type:@"ERROR"];
+//        NSMutableArray *uploadArray = [NSMutableArray arrayWithObject:uploadParm];
+//        [KSNetworkingManager sysExceptionLogUpdate:KS_POST logArray:uploadArray success:^(NSDictionary * _Nonnull dic) {
+//            if ([dic ks_integerValueForKey:@"code"] == 200) {
+//                
+//            }
+//        } faliure:^(NSError * _Nonnull error) {
+//            
+//        }];
+    }
     self.audioEngine.autoShutdownEnabled = YES;
 }
 
@@ -144,12 +165,15 @@
     }
     
     NSMutableArray *barArray = [NSMutableArray array];
-    
+    // 先添加ding
     [barArray addObjectsFromArray:dingClickArray];
     NSInteger dongCount = [self getDongCount:type];
+    
+    // 在添加多个 dong
     for (int i = 0; i < dongCount; i++) {
         [barArray addObjectsFromArray:dongClickArray];
     }
+    
     for (NSInteger i = 0; i < channerCount * bufferBar.frameLength; i++) {
         double temp = 0;
         if (i < barArray.count) {
@@ -230,6 +254,180 @@
     [self.playerNode scheduleBuffer:buffer atTime:nil options:AVAudioPlayerNodeBufferLoops completionHandler:nil];
 }
 
+
+- (void)playRhythmAction:(int)speed rhythmType:(RHYTHM_TYPE)type beatNumber:(NSInteger)beatNumber {
+    self.beatNumber = beatNumber;
+    if (self.audioEngine.isRunning == NO) {
+        [self.audioEngine startAndReturnError:nil];
+    }
+    AVAudioPCMBuffer *buffer = [self generateThythmBuffer:speed rhythmType:type];
+    if (self.playerNode.isPlaying) {
+        [self.playerNode stop];
+    }
+    [self.playerNode play];
+    
+    [self.playerNode scheduleBuffer:buffer atTime:nil options:AVAudioPlayerNodeBufferLoops completionHandler:nil];
+}
+
+- (AVAudioPCMBuffer *)generateThythmBuffer:(int)speed rhythmType:(RHYTHM_TYPE)type {
+    self.audioDIFile.framePosition = 0;
+    self.audioDongFile.framePosition = 0;
+        
+    AVAudioFrameCount dingBeatLength = [self getFrameCountWithSpeed:speed type:type isDing:YES];
+    
+    AVAudioPCMBuffer *dingBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioDIFile.processingFormat frameCapacity:dingBeatLength];
+    [self.audioDIFile readIntoBuffer:dingBuffer error:nil];
+    dingBuffer.frameLength = dingBeatLength;
+    
+    AVAudioFrameCount dongBeatLength = [self getFrameCountWithSpeed:speed type:type isDing:NO];
+    AVAudioPCMBuffer *dongBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioDIFile.processingFormat frameCapacity:dongBeatLength];
+    [self.audioDongFile readIntoBuffer:dongBuffer error:nil];
+    dongBuffer.frameLength = dongBeatLength;
+    
+    int channerCount = (int)self.audioDIFile.processingFormat.channelCount;
+
+    
+    int dongCount = [self getRhythmDongCount:type];
+    if (type == RHYTHM_TYPE_ONE_QUARTERNOTES) {
+        if (self.beatNumber > 1) {
+            dongCount = (int)(self.beatNumber - 1);
+        }
+    }
+    AVAudioFrameCount frameLength = (dingBeatLength + dongBeatLength * dongCount);
+    AVAudioPCMBuffer *bufferBar = [[AVAudioPCMBuffer alloc] initWithPCMFormat:self.audioDIFile.processingFormat frameCapacity:frameLength];
+    bufferBar.frameLength = frameLength;
+    
+    // 数据填充
+    NSMutableArray *dingClickArray = [NSMutableArray array];
+    NSMutableArray *dongClickArray = [NSMutableArray array];
+    // ding
+    for (int i = 0 ; i < channerCount *(int)dingBeatLength; i++) {
+        double tempMain = *(dingBuffer.floatChannelData[0]+i);
+        [dingClickArray addObject:@(tempMain)];
+    }
+    // dong
+    for (int i = 0 ; i < channerCount *(int)dongBeatLength; i++) {
+        double temp = *(dongBuffer.floatChannelData[0]+i);
+        [dongClickArray addObject:@(temp)];
+    }
+    
+    NSMutableArray *barArray = [NSMutableArray array];
+    [barArray addObjectsFromArray:dingClickArray];
+    
+    if (type == RHYTHM_TYPE_ONE_QUARTERNOTES) {
+        if (self.beatNumber > 1) {
+            for (int i = 0; i < self.beatNumber - 1; i++) {
+                [barArray addObjectsFromArray:dongClickArray];
+            }
+        }
+        else if (self.beatNumber == 0) { // 如果只有轻拍
+            barArray = [NSMutableArray array];
+            [barArray addObjectsFromArray:dongClickArray];
+        }
+    }
+    else {
+        for (int i = 0; i < dongCount; i++) {
+            [barArray addObjectsFromArray:dongClickArray];
+        }
+    }
+    
+    
+    for (NSInteger i = 0; i < channerCount * bufferBar.frameLength; i++) {
+        double temp = 0;
+        if (i < barArray.count) {
+            temp = [barArray[i] doubleValue];
+        }
+        *(bufferBar.floatChannelData[0]+i) = temp;
+    }
+    
+    return bufferBar;
+}
+
+- (AVAudioFrameCount)getFrameCountWithSpeed:(int)speed type:(RHYTHM_TYPE)type isDing:(BOOL)isDing {
+    double rate = [self getRhythmRate:type isDing:isDing];
+    int bmp = speed * rate;
+    
+    AVAudioFrameCount beatLength = 0;
+    if (isDing) {
+        beatLength = self.audioDIFile.processingFormat.sampleRate * 60 / bmp;
+    }
+    else {
+        beatLength = self.audioDIFile.processingFormat.sampleRate * 60 / bmp;
+    }
+    return beatLength;
+}
+
+- (CGFloat)getRhythmRate:(RHYTHM_TYPE)type isDing:(BOOL)isDing {
+    switch (type) {
+        case RHYTHM_TYPE_ONE_QUARTERNOTES: // 1个四分音符
+            return 1.0f;
+        case RHYTHM_TYPE_TWO_EIGHTHNOTES: // 两个八分音符
+            return 2.0f;
+            
+        case RHYTHM_TYPE_QUARTERT_RIPLET: //  8分音符三连音 4分音符时值的1/3
+            return 1.0f * 3;
+        case RHYTHM_TYPE_FOUR_SIXTEENTHNOTES: // 4个16分音符
+            return 4.0f;
+        case RHYTHM_TYPE_QUARTER_AND_EIGHTHT_RIPLET: // 4分音符+8分音符组成3连音
+        {
+            if (isDing) {
+                return 1.0f * 3 / 2;
+            }
+            else {
+                return 1.0f * 3;
+            }
+        }
+            break;
+        case RHYTHM_TYPE_DOTTEDEIGHTH_AND_SIXTEENTHNOTES:
+        {
+            if (isDing) {
+                return 4.0f / 3;
+            }
+            else {
+                return 4.0f;
+            }
+        }
+            break;
+        case RHYTHM_TYPE_EIGHTH_AND_TWO_SIXTEENTHNOTES:
+        {
+            if (isDing) {
+                return 2.0f;
+            }
+            else {
+                return 4.0f;
+            }
+        }
+            break;
+    }
+}
+
+- (int)getRhythmDongCount:(RHYTHM_TYPE)type {
+    if (type == RHYTHM_TYPE_ONE_QUARTERNOTES) {
+        return 0;
+    }
+    if (type == RHYTHM_TYPE_TWO_EIGHTHNOTES) {
+        return 1;
+    }
+    else if (type == RHYTHM_TYPE_QUARTERT_RIPLET) {
+        return 2;
+    }
+    else if (type == RHYTHM_TYPE_FOUR_SIXTEENTHNOTES) {
+        return 3;
+    }
+    else if (type == RHYTHM_TYPE_QUARTER_AND_EIGHTHT_RIPLET) {
+        return 1;
+    }
+    else if (type == RHYTHM_TYPE_DOTTEDEIGHTH_AND_SIXTEENTHNOTES) {
+        return 1;
+    }
+    else if (type == RHYTHM_TYPE_EIGHTH_AND_TWO_SIXTEENTHNOTES) {
+        return 2;
+    }
+    else {
+        return 1;
+    }
+}
+
 - (void)stopPlay {
     [self.playerNode stop];
 }

+ 10 - 3
KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/MetronomeManager.h

@@ -19,7 +19,9 @@
 
 @end
 
-typedef void(^BeatChangeCallback)(KSWidgeMetronomeType type);
+typedef void(^BeatChangeCallback)(NSInteger beatNumber);
+
+typedef void(^RhythmChangeCallback)(RHYTHM_TYPE thythmType);
 
 #define METRONOME_MANAGER ([MetronomeManager shareInstance])
 
@@ -33,7 +35,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, assign) BOOL isPlaying;
 
-@property (nonatomic, assign) KSWidgeMetronomeType metronomeType;
+@property (nonatomic, assign) RHYTHM_TYPE rhythmType;
+
+@property (nonatomic, assign) NSInteger beatNumber;
 
 @property (nonatomic, assign) int speed;
 
@@ -53,9 +57,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (NSString *)getTypeString;
 
-
 - (void)beatChooseCallback:(BeatChangeCallback)callback;
 
+- (void)rhythmChooseCallback:(RhythmChangeCallback)callback;
+
+- (NSString *)imageWithType:(RHYTHM_TYPE)type;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 34 - 47
KulexiuForStudent/KulexiuForStudent/Module/Widget/Model/MetronomeManager.m

@@ -7,6 +7,7 @@
 
 #import "MetronomeManager.h"
 #import <KSToolLibrary/KSChoosePicker.h>
+#import "RhythmChooseView.h"
 
 @interface MetronomeManager ()<KSMetronomePlayerDelegate>
 
@@ -45,11 +46,13 @@
 
 - (void)configDefault {
     self.speed = 90;
-    self.metronomeType = KSWidgeMetronomeType4V4;
+    self.rhythmType = RHYTHM_TYPE_ONE_QUARTERNOTES;
     self.timerLength = 60.0 / (1.0 * self.speed) / ([self getRate]);
     [self resetTimerPlay];
     [self createPlayer];
     self.playVolume = 1.0f;
+    self.beatNumber = 4;
+    self.lastChooseIndex = 4;
 }
 
 - (void)setPlayVolume:(float)playVolume {
@@ -67,8 +70,9 @@
     if (self.isPlaying == NO) {
         // 重置
         self.currentNo = -1;
-        int bpm = self.speed * [self getRate];
-        [self.player playAction:bpm metronomeTyle:self.metronomeType];
+//        int bpm = self.speed * [self getRate];
+
+        [self.player playRhythmAction:self.speed rhythmType:self.rhythmType beatNumber:self.beatNumber];
       // 开始播放
         [self.timer setFireDate:[NSDate distantPast]];
     }
@@ -99,23 +103,7 @@
     }
 }
 - (CGFloat)getRate {
-    switch (self.metronomeType) {
-        case KSWidgeMetronomeType1V2:
-        case KSWidgeMetronomeType2V2:
-            return 0.5f;
-        case KSWidgeMetronomeType1V4:
-        case KSWidgeMetronomeType2V4:
-        case KSWidgeMetronomeType3V4:
-        case KSWidgeMetronomeType4V4:
-            return 1.0f;
-        case KSWidgeMetronomeType3V8:
-        case KSWidgeMetronomeType6V8:
-            return 2.0f;
-        case KSWidgeMetronomeType8V16:
-            return 4.0f;
-        default:
-            return 1.0f;
-    }
+    return 1.0;
 }
 - (void)resetTimerPlay {
     if (_timer) {
@@ -186,39 +174,18 @@
 }
 
 - (NSString *)getTypeString {
-    switch (self.metronomeType) {
-        case KSWidgeMetronomeType1V2:
-            return @"1/2";
-        case KSWidgeMetronomeType2V2:
-            return @"2/2";
-        case KSWidgeMetronomeType1V4:
-            return @"1/4";
-        case KSWidgeMetronomeType2V4:
-            return @"2/4";
-        case KSWidgeMetronomeType3V4:
-            return @"3/4";
-        case KSWidgeMetronomeType4V4:
-            return @"4/4";
-        case KSWidgeMetronomeType3V8:
-            return @"3/8";
-        case KSWidgeMetronomeType6V8:
-            return @"6/8";
-        case KSWidgeMetronomeType8V16:
-            return @"8/16";
-        default:
-            return @"4/4";
-    }
+    return [NSString stringWithFormat:@"%zd", self.beatNumber];
 }
 
 - (void)beatChooseCallback:(BeatChangeCallback)callback {
-    // 显示节拍选择弹窗 @[@"1/2",@"2/2",@"1/4",@"2/4",@"3/4",@"4/4",@"3/8",@"6/8",@"8/16"]
-    KSChoosePicker *pickerView = [[KSChoosePicker alloc] initWithTitle:@"调整拍数" sourceData:@[@"1/2",@"1/4",@"2/2",@"2/4",@"3/4",@"3/8",@"4/4",@"6/8",@"8/16"] lastChooseIndex:self.lastChooseIndex sureButtonColor:CLIENT_THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
+
+    KSChoosePicker *pickerView = [[KSChoosePicker alloc] initWithTitle:@"节拍" sourceData:@[@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"] lastChooseIndex:self.lastChooseIndex sureButtonColor:THEMECOLOR chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
         self.lastChooseIndex = chooseIndex;
-        KSWidgeMetronomeType type = chooseIndex;
-        self.metronomeType = type;
+        NSInteger beatNumber = [returnValue integerValue];
+        self.beatNumber = beatNumber;
         [self changeBeat];
         if (callback) {
-            callback(type);
+            callback(beatNumber);
         }
     } cancel:^{
         
@@ -226,10 +193,30 @@
     [pickerView showPicker];
 }
 
+
+- (void)rhythmChooseCallback:(RhythmChangeCallback)callback {
+    RhythmChooseView *chooseView = [RhythmChooseView shareInstance];
+    [chooseView configWithRhythmChooseViewWithPreChoose:METRONOME_MANAGER.rhythmType displayView:[NSObject getKeyWindow]];
+    [chooseView chooseCallback:^(RHYTHM_TYPE type) {
+        self.rhythmType = type;
+        [self changeBeat];
+        if (callback) {
+            callback(type);
+        }
+    }];
+}
+
 - (void)changeBeat {
     self.timerLength = 60.0 / (1.0 * self.speed) / ([self getRate]);
     [self resetTimerPlay];
     [self stopPlay];
+}
+
+
 
+- (NSString *)imageWithType:(RHYTHM_TYPE)type {
+    NSInteger index = type;
+    NSArray *array = @[@"rhythm_quarterNote",@"rhythm_two_eighthNote",@"rhythm_quarter_riplet",@"rhythm_four_sixteenthNote",@"rhythm_quarter_and_eighth_riplet",@"rhythm_dottedEighth_and_sixteenthNote",@"rhythm_eighth_and_two_sixteenthNote"];
+    return array[index];
 }
 @end

+ 25 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.h

@@ -0,0 +1,25 @@
+//
+//  RhythmChooseView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/6.
+//
+
+#import <UIKit/UIKit.h>
+#import "KSMetronomePlayer.h"
+
+typedef void(^RhythmChooseCallback)(RHYTHM_TYPE type);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RhythmChooseView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)configWithRhythmChooseViewWithPreChoose:(RHYTHM_TYPE)preChoose displayView:(UIView *)displayView;
+
+- (void)chooseCallback:(RhythmChooseCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 139 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.m

@@ -0,0 +1,139 @@
+//
+//  RhythmChooseView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/6.
+//
+
+#import "RhythmChooseView.h"
+#import "RhythmView.h"
+
+@interface RhythmChooseView ()<UIGestureRecognizerDelegate>
+
+@property (weak, nonatomic) IBOutlet UIView *bgView;
+
+@property (weak, nonatomic) IBOutlet UIView *buttonContainer;
+
+@property (nonatomic, strong) NSMutableArray *nomalImageArray;
+
+@property (nonatomic, strong) NSMutableArray *selectedImageArray;
+
+@property (nonatomic, assign) RHYTHM_TYPE preType;
+
+@property (nonatomic, copy) RhythmChooseCallback callback;
+
+@end
+
+@implementation RhythmChooseView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.frame = CGRectMake(0, 0, KPortraitWidth, KPortraitHeight);
+    self.bgView.layer.cornerRadius = 12.0f;
+    self.bgView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner;
+    
+    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
+    tapGesture.delegate = self;
+    [self addGestureRecognizer:tapGesture];
+}
+
++ (instancetype)shareInstance {
+    RhythmChooseView *view = [[[NSBundle mainBundle] loadNibNamed:@"RhythmChooseView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)configWithRhythmChooseViewWithPreChoose:(RHYTHM_TYPE)preChoose displayView:(UIView *)displayView {
+    [displayView addSubview:self];
+    
+    self.preType = preChoose;
+    
+    CGFloat leftSpace = 12.0f;
+    CGFloat midSpace = 10.0f;
+    CGFloat topSpace = 12.0f;
+    NSInteger count = 3; // 每行3个
+    CGFloat width = (KPortraitWidth - leftSpace * 2 - midSpace * (count - 1)) / 3;
+    CGFloat height = 48.0f;
+    for (NSInteger index = 0; index < self.nomalImageArray.count; index++) {
+        CGRect frame = CGRectMake(leftSpace + (index % 3) * (width + midSpace), (index / 3) * (height + topSpace), width, height);
+        RhythmView *button = [RhythmView shareInstance];
+        button.frame = frame;
+        NSString *nomalImage = self.nomalImageArray[index];
+        NSString *selectedImage = self.selectedImageArray[index];
+        BOOL isChoose = index == preChoose ? YES : NO;
+        [button configWithImage:nomalImage selectedImage:selectedImage chooseStatus:isChoose];
+        button.tag = index + 1000;
+        [self.buttonContainer addSubview:button];
+        MJWeakSelf;
+        [button chooseAction:^(NSInteger tag) {
+            [weakSelf chooseRhythmAction:tag];
+        }];
+    }
+    
+}
+
+
+
+- (void)chooseRhythmAction:(NSInteger)tag {
+    if (self.preType == tag - 1000) {
+        return;
+    }
+    
+    RhythmView *button = (RhythmView *)[self.buttonContainer viewWithTag:tag];
+    button.isChoose = YES;
+    RhythmView *preButton = (RhythmView *)[self.buttonContainer viewWithTag:self.preType+1000];
+    preButton.isChoose = NO;
+    self.preType = tag-1000;
+}
+
+- (void)chooseCallback:(RhythmChooseCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)cancelAction:(id)sender {
+    [self removeFromSuperview];
+}
+
+- (IBAction)sureAction:(id)sender {
+    if (self.callback) {
+        self.callback(self.preType);
+    }
+    [self removeFromSuperview];
+}
+
+- (void)tapAction:(UITapGestureRecognizer *)gesture {
+    [self removeFromSuperview];
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
+    if ([touch.view isDescendantOfView:self.bgView]) {
+        return NO;
+    }
+    return YES;
+}
+
+
+#pragma mark ---- lazying
+- (NSMutableArray *)nomalImageArray {
+    if (!_nomalImageArray) {
+        _nomalImageArray = [NSMutableArray arrayWithArray:@[@"rhythm_quarterNote",@"rhythm_two_eighthNote",@"rhythm_quarter_riplet",@"rhythm_four_sixteenthNote",@"rhythm_quarter_and_eighth_riplet",@"rhythm_dottedEighth_and_sixteenthNote",@"rhythm_eighth_and_two_sixteenthNote"]];
+    }
+    return _nomalImageArray;
+}
+
+- (NSMutableArray *)selectedImageArray {
+    if (!_selectedImageArray) {
+        _selectedImageArray = [NSMutableArray arrayWithArray:@[@"rhythm_quarterNote_selected",@"rhythm_two_eighthNote_selected",@"rhythm_quarter_riplet_selected",@"rhythm_four_sixteenthNote_selected",@"rhythm_quarter_and_eighth_riplet_selected",@"rhythm_dottedEighth_and_sixteenthNote_selected",@"rhythm_eighth_and_two_sixteenthNote_selected"]];
+    }
+    return _selectedImageArray;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 111 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmChooseView.xib

@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <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="RhythmChooseView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LDL-gI-zZR">
+                    <rect key="frame" x="0.0" y="533" width="393" height="319"/>
+                    <subviews>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Obv-iA-UuD">
+                            <rect key="frame" x="0.0" y="0.0" width="70" height="53"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="70" id="LxZ-nu-j8u"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="取消">
+                                <color key="titleColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="cancelAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="dP5-hy-TtW"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ive-V7-mht">
+                            <rect key="frame" x="323" y="0.0" width="70" height="53"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="70" id="Dwx-4C-Rnv"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="确定">
+                                <color key="titleColor" red="0.10980392156862745" green="0.67450980392156867" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="sureAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="bdT-CL-dB2"/>
+                            </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="zTz-B6-1f2">
+                            <rect key="frame" x="168.66666666666666" y="13" width="56" height="25"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="25" id="fKU-av-ZUw"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hRL-Tt-NXW">
+                            <rect key="frame" x="13" y="53" width="367" height="1"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="VfU-dT-dzn"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wvm-ho-jAO">
+                            <rect key="frame" x="0.0" y="70" width="393" height="249"/>
+                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstItem="Obv-iA-UuD" firstAttribute="top" secondItem="LDL-gI-zZR" secondAttribute="top" id="2cE-VL-cnF"/>
+                        <constraint firstItem="hRL-Tt-NXW" firstAttribute="leading" secondItem="LDL-gI-zZR" secondAttribute="leading" constant="13" id="9oS-rt-XI9"/>
+                        <constraint firstItem="hRL-Tt-NXW" firstAttribute="top" secondItem="LDL-gI-zZR" secondAttribute="top" constant="53" id="BI9-av-7tZ"/>
+                        <constraint firstItem="hRL-Tt-NXW" firstAttribute="top" secondItem="zTz-B6-1f2" secondAttribute="bottom" constant="15" id="BLS-2g-xac"/>
+                        <constraint firstAttribute="height" constant="319" id="FsD-v5-PxF"/>
+                        <constraint firstItem="hRL-Tt-NXW" firstAttribute="top" secondItem="ive-V7-mht" secondAttribute="bottom" id="Qqr-S5-8NI"/>
+                        <constraint firstItem="hRL-Tt-NXW" firstAttribute="top" secondItem="Obv-iA-UuD" secondAttribute="bottom" id="TT5-7s-mRo"/>
+                        <constraint firstItem="Obv-iA-UuD" firstAttribute="leading" secondItem="LDL-gI-zZR" secondAttribute="leading" id="VgU-62-wj3"/>
+                        <constraint firstAttribute="trailing" secondItem="hRL-Tt-NXW" secondAttribute="trailing" constant="13" id="XhM-gz-rgq"/>
+                        <constraint firstItem="ive-V7-mht" firstAttribute="top" secondItem="LDL-gI-zZR" secondAttribute="top" id="e2C-nD-blA"/>
+                        <constraint firstItem="Wvm-ho-jAO" firstAttribute="top" secondItem="hRL-Tt-NXW" secondAttribute="bottom" constant="16" id="fX4-Lv-REZ"/>
+                        <constraint firstItem="zTz-B6-1f2" firstAttribute="centerX" secondItem="LDL-gI-zZR" secondAttribute="centerX" id="jrY-jE-wHW"/>
+                        <constraint firstItem="Wvm-ho-jAO" firstAttribute="leading" secondItem="LDL-gI-zZR" secondAttribute="leading" id="nMW-1E-Q0m"/>
+                        <constraint firstAttribute="trailing" secondItem="Wvm-ho-jAO" secondAttribute="trailing" id="oyU-Zs-N07"/>
+                        <constraint firstAttribute="trailing" secondItem="ive-V7-mht" secondAttribute="trailing" id="pL4-Ad-gBP"/>
+                        <constraint firstAttribute="bottom" secondItem="Wvm-ho-jAO" secondAttribute="bottom" id="xPv-5n-WvV"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.69999999999999996" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="LDL-gI-zZR" secondAttribute="bottom" id="ZhO-eg-ULj"/>
+                <constraint firstItem="LDL-gI-zZR" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="dYj-W5-uGS"/>
+                <constraint firstAttribute="trailing" secondItem="LDL-gI-zZR" secondAttribute="trailing" id="hPK-1X-scn"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="bgView" destination="LDL-gI-zZR" id="1vT-io-WIM"/>
+                <outlet property="buttonContainer" destination="Wvm-ho-jAO" id="gPg-T8-lYc"/>
+            </connections>
+            <point key="canvasLocation" x="-11.450381679389313" y="19.718309859154932"/>
+        </view>
+    </objects>
+    <resources>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 26 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.h

@@ -0,0 +1,26 @@
+//
+//  RhythmView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/6.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^RhythmButtonAction)(NSInteger tag);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RhythmView : UIView
+
+@property (nonatomic, assign) BOOL isChoose;
+
++ (instancetype)shareInstance;
+
+- (void)configWithImage:(NSString *)nomalImage selectedImage:(NSString *)selectedImage chooseStatus:(BOOL)chooseStatus;
+
+- (void)chooseAction:(RhythmButtonAction)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 78 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.m

@@ -0,0 +1,78 @@
+//
+//  RhythmView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/6.
+//
+
+#import "RhythmView.h"
+
+@interface RhythmView ()
+
+@property (weak, nonatomic) IBOutlet UIView *bgView;
+
+@property (weak, nonatomic) IBOutlet UIImageView *rhythmImage;
+
+@property (nonatomic, copy) RhythmButtonAction callback;
+
+@property (nonatomic, strong) NSString *nomalImage;
+
+@property (nonatomic, strong) NSString *selectedImage;
+
+@end
+
+@implementation RhythmView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.bgView.backgroundColor = HexRGB(0xF6F6F6);
+    self.bgView.layer.borderColor = HexRGB(0xF6F6F6).CGColor;
+}
+
++ (instancetype)shareInstance {
+    RhythmView *view = [[[NSBundle mainBundle] loadNibNamed:@"RhythmView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)configWithImage:(NSString *)nomalImage selectedImage:(NSString *)selectedImage chooseStatus:(BOOL)chooseStatus {
+    self.nomalImage = nomalImage;
+    self.selectedImage = selectedImage;
+    self.isChoose = chooseStatus;
+}
+
+- (void)chooseAction:(RhythmButtonAction)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)buttonAction:(id)sender {
+    if (self.callback) {
+        self.callback(self.tag);
+    }
+    self.isChoose = YES;
+}
+
+- (void)setIsChoose:(BOOL)isChoose {
+    _isChoose = isChoose;
+    if (isChoose) {
+        self.bgView.backgroundColor = HexRGB(0xEBF8FF);
+        self.bgView.layer.borderColor = HexRGB(0x1CACF1).CGColor;
+        [self.rhythmImage setImage:[UIImage imageNamed:self.selectedImage]];
+    }
+    else {
+        self.bgView.backgroundColor = HexRGB(0xF6F6F6);
+        self.bgView.layer.borderColor = HexRGB(0xF6F6F6).CGColor;
+        [self.rhythmImage setImage:[UIImage imageNamed:self.nomalImage]];
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 73 - 0
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/RhythmView.xib

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <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="RhythmView">
+            <rect key="frame" x="0.0" y="0.0" width="264" height="94"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b4W-F5-Y4I">
+                    <rect key="frame" x="0.0" y="0.0" width="264" height="94"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Kc7-ap-JUc">
+                            <rect key="frame" x="110" y="24" width="44" height="46"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="46" id="78K-oj-Kh3"/>
+                                <constraint firstAttribute="width" constant="44" id="vzO-re-TY2"/>
+                            </constraints>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nOu-TQ-og3">
+                            <rect key="frame" x="0.0" y="0.0" width="264" height="94"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="buttonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="2zr-Pp-WTe"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" red="0.96470588235294119" green="0.96470588235294119" blue="0.96470588235294119" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstItem="Kc7-ap-JUc" firstAttribute="centerY" secondItem="b4W-F5-Y4I" secondAttribute="centerY" id="Dal-K6-nGx"/>
+                        <constraint firstItem="nOu-TQ-og3" firstAttribute="top" secondItem="b4W-F5-Y4I" secondAttribute="top" id="HzU-OE-a6q"/>
+                        <constraint firstAttribute="trailing" secondItem="nOu-TQ-og3" secondAttribute="trailing" id="SpR-sC-l5D"/>
+                        <constraint firstAttribute="bottom" secondItem="nOu-TQ-og3" secondAttribute="bottom" id="fbX-7s-Bfo"/>
+                        <constraint firstItem="nOu-TQ-og3" firstAttribute="leading" secondItem="b4W-F5-Y4I" secondAttribute="leading" id="mLj-Mt-X6w"/>
+                        <constraint firstItem="Kc7-ap-JUc" firstAttribute="centerX" secondItem="b4W-F5-Y4I" secondAttribute="centerX" id="mQ7-01-5Eb"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                            <real key="value" value="1"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="6"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                            <color key="value" red="0.96470588235294119" green="0.96470588235294119" blue="0.96470588235294119" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="b4W-F5-Y4I" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="3h0-gw-i7x"/>
+                <constraint firstAttribute="bottom" secondItem="b4W-F5-Y4I" secondAttribute="bottom" id="Skw-1g-qCi"/>
+                <constraint firstAttribute="trailing" secondItem="b4W-F5-Y4I" secondAttribute="trailing" id="nXq-pa-dla"/>
+                <constraint firstItem="b4W-F5-Y4I" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="uGp-KG-49e"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="bgView" destination="b4W-F5-Y4I" id="Amg-eT-jRm"/>
+                <outlet property="rhythmImage" destination="Kc7-ap-JUc" id="QIZ-JN-Vnp"/>
+            </connections>
+            <point key="canvasLocation" x="-109.9236641221374" y="259.85915492957747"/>
+        </view>
+    </objects>
+</document>

+ 7 - 7
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetBottomButtonView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" 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="21505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -14,10 +14,10 @@
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HTq-QO-Kuw">
-                    <rect key="frame" x="87" y="10" width="240" height="54"/>
+                    <rect key="frame" x="71" y="10" width="272" height="54"/>
                     <subviews>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="播放" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lRq-s8-f8k">
-                            <rect key="frame" x="84.5" y="14.5" width="40" height="25"/>
+                            <rect key="frame" x="100.5" y="14.5" width="40" height="25"/>
                             <constraints>
                                 <constraint firstAttribute="height" constant="25" id="43i-To-0B3"/>
                                 <constraint firstAttribute="width" constant="40" id="pyC-3U-pdM"/>
@@ -27,7 +27,7 @@
                             <nil key="highlightedColor"/>
                         </label>
                         <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_play" translatesAutoresizingMaskIntoConstraints="NO" id="gqZ-Sn-p3R">
-                            <rect key="frame" x="134.5" y="20.5" width="11" height="13"/>
+                            <rect key="frame" x="150.5" y="20.5" width="11" height="13"/>
                         </imageView>
                     </subviews>
                     <color key="backgroundColor" red="0.0" green="0.67450980392156867" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -44,10 +44,10 @@
                     </userDefinedRuntimeAttributes>
                 </view>
                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dUf-b4-rpL">
-                    <rect key="frame" x="87" y="10" width="240" height="54"/>
+                    <rect key="frame" x="71" y="10" width="272" height="54"/>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
-                        <constraint firstAttribute="width" constant="240" id="gcS-Ed-rC7"/>
+                        <constraint firstAttribute="width" constant="272" id="gcS-Ed-rC7"/>
                         <constraint firstAttribute="height" constant="54" id="neJ-fh-cFC"/>
                     </constraints>
                     <fontDescription key="fontDescription" type="system" pointSize="16"/>

+ 11 - 8
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.h

@@ -6,14 +6,15 @@
 //
 
 #import <UIKit/UIKit.h>
-#import "WidgetDotView.h"
+#import "KSMetronomePlayer.h"
 
 @protocol MetronomeFunctionDelegate <NSObject>
 
-/** 加减号改变频率 */
-- (void)clickChangeSpeed:(int)speed;
-
+// 切换拍号
 - (void)clickChangeBeat;
+// 切换节奏
+- (void)clickChangeRhythm;
+
 // 播放音量调整
 - (void)volumeChange:(float)volume;
 
@@ -23,13 +24,13 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface WidgetFunctionView : UIView
 
-@property (nonatomic, assign) KSWidgeMetronomeType currentMetronomeType;
+@property (nonatomic, assign) RHYTHM_TYPE rhythmType;
 
-@property (nonatomic, assign) int speed;
+@property (nonatomic, assign) NSInteger beatNumber;
 
-@property (weak, nonatomic) IBOutlet UILabel *signatureLabel;
+@property (weak, nonatomic) IBOutlet UILabel *beatLabel;
 
-@property (weak, nonatomic) IBOutlet UIButton *signatureButton;
+@property (weak, nonatomic) IBOutlet UIImageView *rhythmImage;
 
 @property (nonatomic, assign) CGFloat volumeRate;
 
@@ -37,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN
 /** 代理 */
 @property (nonatomic, weak) id <MetronomeFunctionDelegate> delegate;
 
++ (CGFloat)getViewHeight;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 38 - 85
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.m

@@ -8,11 +8,6 @@
 #import "WidgetFunctionView.h"
 
 @interface WidgetFunctionView ()
-@property (weak, nonatomic) IBOutlet NSLayoutConstraint *signatureWidth;
-
-@property (weak, nonatomic) IBOutlet UIButton *speedMinusButton;
-
-@property (weak, nonatomic) IBOutlet UIButton *speedAddButton;
 
 @property (weak, nonatomic) IBOutlet UISlider *volumeSlider;
 
@@ -25,12 +20,10 @@
 
 - (void)awakeFromNib {
     [super awakeFromNib];
-    if (IS_IPAD) {
-        self.signatureWidth.constant = 200;
-    }
+    
     [self.volumeSlider setThumbImage:[UIImage imageNamed:@"slider_image"] forState:UIControlStateNormal];
     [self.volumeSlider setThumbImage:[UIImage imageNamed:@"slider_image"] forState:UIControlStateHighlighted];
-    UIImage *image = [self getGradientImageWithColors:@[HexRGB(0x63DAFF),HexRGB(0x1798FF)] imgSize:CGSizeMake(240, 30)];
+    UIImage *image = [self getGradientImageWithColors:@[HexRGB(0x63DAFF),HexRGB(0x1798FF)] imgSize:CGSizeMake(202, 4)];
     [self.volumeSlider setMinimumTrackImage:image forState:UIControlStateNormal];
 }
 
@@ -51,85 +44,12 @@
     }
 }
 
-
-- (IBAction)onReduceButtonClick:(id)sender {
-    if (self.speed > 50) {
-        self.speed --;
-    }else{
-        self.speed = 50;
-    }
-    [self updateSpeed];
-}
-
-
-- (IBAction)onAddButtonClick:(id)sender {
-    if (self.speed < 200) {
-        self.speed ++;
-    }else{
-        self.speed = 200;
-    }
-    [self updateSpeed];
-}
-
-- (void)updateSpeed {
-    
-    if (self.delegate && [self.delegate respondsToSelector:@selector(clickChangeSpeed:)]) {
-        [self.delegate clickChangeSpeed:self.speed];
+- (IBAction)changeRhythmAction:(id)sender {
+    if (self.delegate && [self.delegate respondsToSelector:@selector(clickChangeRhythm)]) {
+        [self.delegate clickChangeRhythm];
     }
 }
 
-- (void)setCurrentMetronomeType:(KSWidgeMetronomeType)currentMetronomeType {
-    _currentMetronomeType = currentMetronomeType;
-    switch (currentMetronomeType) {
-        case KSWidgeMetronomeType1V2:
-        {
-            [self.signatureLabel setText:@"1/2"];
-        }
-            break;
-        case KSWidgeMetronomeType2V2:
-        {
-            [self.signatureLabel setText:@"2/2"];
-        }
-            break;
-        case KSWidgeMetronomeType1V4:
-        {
-            [self.signatureLabel setText:@"1/4"];
-        }
-            break;
-        case KSWidgeMetronomeType2V4:
-        {
-            [self.signatureLabel setText:@"2/4"];
-        }
-            break;
-        case KSWidgeMetronomeType3V4:
-        {
-            [self.signatureLabel setText:@"3/4"];
-        }
-            break;
-        case KSWidgeMetronomeType4V4:
-        {
-            [self.signatureLabel setText:@"4/4"];
-        }
-            break;
-        case KSWidgeMetronomeType3V8:
-        {
-            [self.signatureLabel setText:@"3/8"];
-        }
-            break;
-        case KSWidgeMetronomeType6V8:
-        {
-            [self.signatureLabel setText:@"6/8"];
-        }
-            break;
-        case KSWidgeMetronomeType8V16:
-        {
-            [self.signatureLabel setText:@"8/16"];
-        }
-            break;
-        default:
-            break;
-    }
-}
 
 - (void)setVolumeRate:(CGFloat)volumeRate {
     _volumeRate = volumeRate;
@@ -158,8 +78,41 @@
     CGContextRestoreGState(context);
     CGColorSpaceRelease(colorSpace);
     UIGraphicsEndImageContext();
+    image = [self CGContextClip:image cornerRadius:imgSize.height/2];
     return image;
 }
+
+// CGContext 裁剪
+- (UIImage *)CGContextClip:(UIImage *)img cornerRadius:(CGFloat)c {
+    int w  = img.size.width * img.scale;
+    int h = img.size.height * img.scale;
+    UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), false, 1.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextMoveToPoint(context, 0, c);
+    CGContextAddArcToPoint(context, 0, 0, c, 0, c);
+    CGContextAddLineToPoint(context, w-c, 0);
+    CGContextAddArcToPoint(context, w, 0, w, c, c);
+    CGContextAddLineToPoint(context, w, h-c);
+    CGContextAddArcToPoint(context, w, h, w-c, h, c);
+    CGContextAddLineToPoint(context, c, h);
+    CGContextAddArcToPoint(context, 0, h, 0, h-c, c);
+    CGContextAddLineToPoint(context, 0, c);
+    CGContextClosePath(context);
+    
+     // 先裁剪 context,再画图,就会在裁剪后的 path 中画
+    CGContextClip(context);
+    [img drawInRect:CGRectMake(0, 0, w, h)];       // 画图
+    CGContextDrawPath(context, kCGPathFill);
+    UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    
+    return ret;
+}
+
+
++ (CGFloat)getViewHeight {
+    return 200;
+}
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 97 - 97
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetFunctionView.xib

@@ -1,91 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" 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="22131"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
         <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="WidgetFunctionView">
-            <rect key="frame" x="0.0" y="0.0" width="414" height="115"/>
+            <rect key="frame" x="0.0" y="0.0" width="414" height="200"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Vgr-v5-aHg">
-                    <rect key="frame" x="69" y="0.0" width="72" height="72"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="72" id="Lsq-An-xLd"/>
-                        <constraint firstAttribute="width" constant="72" id="ZRc-yd-VZu"/>
-                    </constraints>
-                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                    <state key="normal" backgroundImage="speed_minus"/>
-                    <connections>
-                        <action selector="onReduceButtonClick:" destination="iN0-l3-epB" eventType="touchUpInside" id="DTz-pP-VFz"/>
-                    </connections>
-                </button>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zZA-L2-xH3">
-                    <rect key="frame" x="146" y="0.0" width="122" height="72"/>
-                    <subviews>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_bg_s" translatesAutoresizingMaskIntoConstraints="NO" id="v7s-8y-OYT">
-                            <rect key="frame" x="0.0" y="0.0" width="122" height="72"/>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="4/4" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="66c-wn-3Yr">
-                            <rect key="frame" x="34.5" y="20" width="30" height="26"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="26" id="2zH-gk-AQd"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
-                            <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="calibratedRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_arrow_down" translatesAutoresizingMaskIntoConstraints="NO" id="a3Y-DI-8bc">
-                            <rect key="frame" x="76.5" y="29.5" width="11" height="7"/>
-                        </imageView>
-                    </subviews>
+                <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" minimumValueImage="metronome_volume" translatesAutoresizingMaskIntoConstraints="NO" id="n9V-6j-N8n">
+                    <rect key="frame" x="75" y="130" width="224" height="31"/>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
-                        <constraint firstAttribute="bottom" secondItem="v7s-8y-OYT" secondAttribute="bottom" id="0FM-4N-k4y"/>
-                        <constraint firstItem="a3Y-DI-8bc" firstAttribute="centerY" secondItem="66c-wn-3Yr" secondAttribute="centerY" id="44T-Kg-1Er"/>
-                        <constraint firstItem="v7s-8y-OYT" firstAttribute="top" secondItem="zZA-L2-xH3" secondAttribute="top" id="7fU-EP-gxi"/>
-                        <constraint firstAttribute="trailing" secondItem="v7s-8y-OYT" secondAttribute="trailing" id="JpM-Tc-Pn6"/>
-                        <constraint firstItem="v7s-8y-OYT" firstAttribute="leading" secondItem="zZA-L2-xH3" secondAttribute="leading" id="VQ2-7f-v0j"/>
-                        <constraint firstItem="66c-wn-3Yr" firstAttribute="centerX" secondItem="zZA-L2-xH3" secondAttribute="centerX" constant="-11.5" id="aL4-i4-ytu"/>
-                        <constraint firstItem="a3Y-DI-8bc" firstAttribute="centerY" secondItem="zZA-L2-xH3" secondAttribute="centerY" constant="-3" id="gHm-XH-BoZ"/>
-                        <constraint firstItem="a3Y-DI-8bc" firstAttribute="leading" secondItem="66c-wn-3Yr" secondAttribute="trailing" constant="12" id="vVw-Ru-dAv"/>
+                        <constraint firstAttribute="width" constant="220" id="3Fb-9V-gAN"/>
                     </constraints>
-                </view>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8S7-tR-fpt">
-                    <rect key="frame" x="146" y="0.0" width="122" height="72"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="72" id="G2q-Lb-C9F"/>
-                        <constraint firstAttribute="width" constant="122" id="GvT-n8-eSh"/>
-                    </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">
-                        <color key="titleColor" red="0.10196078431372549" green="0.10196078431372549" blue="0.10196078431372549" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                    </state>
-                    <connections>
-                        <action selector="changeBeatAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="iQs-c2-I9L"/>
-                    </connections>
-                </button>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xxw-kt-6aa">
-                    <rect key="frame" x="273" y="0.0" width="72" height="72"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="72" id="Sxb-x5-Zj0"/>
-                        <constraint firstAttribute="width" constant="72" id="TLd-GR-oiI"/>
-                    </constraints>
-                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
-                    <state key="normal" backgroundImage="speed_add"/>
-                    <connections>
-                        <action selector="onAddButtonClick:" destination="iN0-l3-epB" eventType="touchUpInside" id="dyG-1d-skC"/>
-                    </connections>
-                </button>
-                <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" minimumValueImage="metronome_volume" translatesAutoresizingMaskIntoConstraints="NO" id="n9V-6j-N8n">
-                    <rect key="frame" x="67" y="77" width="240" height="31"/>
-                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <color key="minimumTrackTintColor" red="0.10980392156862745" green="0.67450980392156867" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     <color key="maximumTrackTintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     <color key="thumbTintColor" red="0.10980392156862745" green="0.67450980392156867" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -94,50 +27,117 @@
                     </connections>
                 </slider>
                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="100" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gL7-N0-yqf">
-                    <rect key="frame" x="321" y="82" width="28" height="20"/>
+                    <rect key="frame" x="313" y="135" width="28" height="20"/>
                     <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
-                    <color key="textColor" red="0.34509803921568627" green="0.63529411764705879" blue="0.92549019607843142" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <color key="textColor" red="0.10980392156862745" green="0.67450980392156867" blue="0.94509803921568625" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     <nil key="highlightedColor"/>
                 </label>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="beat_button_bg" translatesAutoresizingMaskIntoConstraints="NO" id="mlI-P6-CYz">
+                    <rect key="frame" x="57.5" y="19" width="156" height="86"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="156" id="8Gl-cP-DCN"/>
+                        <constraint firstAttribute="height" constant="86" id="kVK-Rn-Bgd"/>
+                    </constraints>
+                </imageView>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="beat_button_bg" translatesAutoresizingMaskIntoConstraints="NO" id="oEh-5g-6lz">
+                    <rect key="frame" x="200.5" y="19" width="156" height="86"/>
+                </imageView>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="01D-J8-XKl">
+                    <rect key="frame" x="57.5" y="19" width="149.5" height="86"/>
+                    <subviews>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="拍" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FIn-DE-nGh">
+                            <rect key="frame" x="75.5" y="33" width="17" height="20"/>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                            <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="4" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AeH-Ym-IiW">
+                            <rect key="frame" x="58.5" y="28.5" width="16" height="29"/>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
+                            <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OO4-h9-q6I">
+                            <rect key="frame" x="10" y="0.0" width="129.5" height="86"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="changeBeatAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="FNs-wY-PSd"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="bottom" secondItem="OO4-h9-q6I" secondAttribute="bottom" id="1vk-iK-V6K"/>
+                        <constraint firstItem="AeH-Ym-IiW" firstAttribute="centerY" secondItem="01D-J8-XKl" secondAttribute="centerY" id="62D-zL-LT8"/>
+                        <constraint firstItem="OO4-h9-q6I" firstAttribute="leading" secondItem="01D-J8-XKl" secondAttribute="leading" constant="10" id="MdS-BP-ubl"/>
+                        <constraint firstItem="OO4-h9-q6I" firstAttribute="top" secondItem="01D-J8-XKl" secondAttribute="top" id="POX-t7-Dgr"/>
+                        <constraint firstAttribute="trailing" secondItem="OO4-h9-q6I" secondAttribute="trailing" constant="10" id="dw4-MD-0Jv"/>
+                        <constraint firstItem="AeH-Ym-IiW" firstAttribute="centerX" secondItem="01D-J8-XKl" secondAttribute="centerX" constant="-8.5" id="gpY-Ph-Rm6"/>
+                        <constraint firstItem="FIn-DE-nGh" firstAttribute="centerY" secondItem="AeH-Ym-IiW" secondAttribute="centerY" id="pMU-bC-ioE"/>
+                        <constraint firstItem="FIn-DE-nGh" firstAttribute="leading" secondItem="AeH-Ym-IiW" secondAttribute="trailing" constant="1" id="wmM-0Y-c5O"/>
+                    </constraints>
+                </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Tuz-ih-MhG">
+                    <rect key="frame" x="207" y="19" width="149.5" height="86"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rhythm_quarterNote" translatesAutoresizingMaskIntoConstraints="NO" id="I5L-Fv-gq1">
+                            <rect key="frame" x="53" y="20" width="44" height="46"/>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hGR-l9-ttz">
+                            <rect key="frame" x="10" y="0.0" width="129.5" height="86"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="changeRhythmAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="cym-NZ-14e"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="hGR-l9-ttz" firstAttribute="top" secondItem="Tuz-ih-MhG" secondAttribute="top" id="Cga-Az-oIW"/>
+                        <constraint firstAttribute="trailing" secondItem="hGR-l9-ttz" secondAttribute="trailing" constant="10" id="KEz-jn-DkQ"/>
+                        <constraint firstItem="I5L-Fv-gq1" firstAttribute="centerX" secondItem="Tuz-ih-MhG" secondAttribute="centerX" id="MHx-8u-ABr"/>
+                        <constraint firstAttribute="bottom" secondItem="hGR-l9-ttz" secondAttribute="bottom" id="eai-sY-nyK"/>
+                        <constraint firstItem="I5L-Fv-gq1" firstAttribute="centerY" secondItem="Tuz-ih-MhG" secondAttribute="centerY" id="j4R-S0-2gD"/>
+                        <constraint firstItem="hGR-l9-ttz" firstAttribute="leading" secondItem="Tuz-ih-MhG" secondAttribute="leading" constant="10" id="tnT-8l-oc7"/>
+                    </constraints>
+                </view>
             </subviews>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="leading" secondItem="Vgr-v5-aHg" secondAttribute="trailing" constant="5" id="8Sy-9T-tOM"/>
-                <constraint firstItem="xxw-kt-6aa" firstAttribute="leading" secondItem="8S7-tR-fpt" secondAttribute="trailing" constant="5" id="Dro-Aa-AjB"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="centerY" secondItem="Vgr-v5-aHg" secondAttribute="centerY" id="KLA-a2-frd"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="trailing" secondItem="zZA-L2-xH3" secondAttribute="trailing" id="Ls5-at-ldT"/>
-                <constraint firstItem="xxw-kt-6aa" firstAttribute="centerY" secondItem="Vgr-v5-aHg" secondAttribute="centerY" id="Rbr-as-gF3"/>
-                <constraint firstItem="n9V-6j-N8n" firstAttribute="leading" secondItem="Vgr-v5-aHg" secondAttribute="leading" id="VYP-Bw-aUN"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="leading" secondItem="zZA-L2-xH3" secondAttribute="leading" id="Yff-pa-H7m"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="dZt-n0-mcE"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="fwC-U3-xfC"/>
+                <constraint firstItem="n9V-6j-N8n" firstAttribute="top" secondItem="mlI-P6-CYz" secondAttribute="bottom" constant="25" id="3g9-qi-yH4"/>
+                <constraint firstItem="mlI-P6-CYz" firstAttribute="leading" secondItem="01D-J8-XKl" secondAttribute="leading" id="55v-lf-b2s"/>
+                <constraint firstItem="oEh-5g-6lz" firstAttribute="bottom" secondItem="mlI-P6-CYz" secondAttribute="bottom" id="5cR-Rm-Dcz"/>
+                <constraint firstItem="Tuz-ih-MhG" firstAttribute="leading" secondItem="oEh-5g-6lz" secondAttribute="leading" constant="6.5" id="6dv-2D-sHP"/>
+                <constraint firstItem="oEh-5g-6lz" firstAttribute="height" secondItem="mlI-P6-CYz" secondAttribute="height" id="GsK-RD-Nkn"/>
+                <constraint firstItem="Tuz-ih-MhG" firstAttribute="bottom" secondItem="oEh-5g-6lz" secondAttribute="bottom" id="JvM-CP-pBJ"/>
+                <constraint firstItem="oEh-5g-6lz" firstAttribute="width" secondItem="mlI-P6-CYz" secondAttribute="width" id="LBn-Ug-Zfa"/>
+                <constraint firstItem="mlI-P6-CYz" firstAttribute="bottom" secondItem="01D-J8-XKl" secondAttribute="bottom" id="caC-Qh-YTP"/>
+                <constraint firstItem="Tuz-ih-MhG" firstAttribute="trailing" secondItem="oEh-5g-6lz" secondAttribute="trailing" id="fUc-vG-L5C"/>
+                <constraint firstItem="mlI-P6-CYz" firstAttribute="top" secondItem="01D-J8-XKl" secondAttribute="top" id="j6M-Rd-mVz"/>
                 <constraint firstItem="gL7-N0-yqf" firstAttribute="centerY" secondItem="n9V-6j-N8n" secondAttribute="centerY" id="k2U-Ep-j6r"/>
                 <constraint firstItem="gL7-N0-yqf" firstAttribute="leading" secondItem="n9V-6j-N8n" secondAttribute="trailing" constant="16" id="kwJ-yb-LT0"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="bottom" secondItem="zZA-L2-xH3" secondAttribute="bottom" id="mT6-u5-VAu"/>
+                <constraint firstItem="mlI-P6-CYz" firstAttribute="trailing" secondItem="01D-J8-XKl" secondAttribute="trailing" constant="6.5" id="oIm-8H-mBa"/>
+                <constraint firstAttribute="bottom" secondItem="n9V-6j-N8n" secondAttribute="bottom" constant="40" id="uuF-DE-fHP"/>
                 <constraint firstItem="n9V-6j-N8n" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="-20" id="wUi-jX-bDm"/>
-                <constraint firstItem="n9V-6j-N8n" firstAttribute="top" secondItem="Vgr-v5-aHg" secondAttribute="bottom" constant="5" id="xV7-rF-gtp"/>
-                <constraint firstItem="8S7-tR-fpt" firstAttribute="top" secondItem="zZA-L2-xH3" secondAttribute="top" id="zvk-Nm-UXi"/>
+                <constraint firstItem="oEh-5g-6lz" firstAttribute="leading" secondItem="mlI-P6-CYz" secondAttribute="trailing" constant="-13" id="wvm-Uv-uiS"/>
+                <constraint firstItem="mlI-P6-CYz" firstAttribute="trailing" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="6.5" id="yDf-eE-8ZR"/>
+                <constraint firstItem="Tuz-ih-MhG" firstAttribute="top" secondItem="oEh-5g-6lz" secondAttribute="top" id="yNo-bH-9bW"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
             <nil key="simulatedBottomBarMetrics"/>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
             <connections>
-                <outlet property="signatureButton" destination="8S7-tR-fpt" id="Lic-ec-FEc"/>
-                <outlet property="signatureLabel" destination="66c-wn-3Yr" id="F08-yR-Wc4"/>
-                <outlet property="signatureWidth" destination="GvT-n8-eSh" id="CT4-C3-bEw"/>
-                <outlet property="speedAddButton" destination="xxw-kt-6aa" id="WQE-Gf-zIz"/>
-                <outlet property="speedMinusButton" destination="Vgr-v5-aHg" id="zux-FN-7kX"/>
+                <outlet property="beatLabel" destination="AeH-Ym-IiW" id="U96-lm-CES"/>
+                <outlet property="rhythmImage" destination="I5L-Fv-gq1" id="fag-Kh-xhz"/>
                 <outlet property="valueLabel" destination="gL7-N0-yqf" id="yXG-GD-Kkd"/>
                 <outlet property="volumeSlider" destination="n9V-6j-N8n" id="c0q-59-r5I"/>
             </connections>
-            <point key="canvasLocation" x="131.8840579710145" y="6.3616071428571423"/>
+            <point key="canvasLocation" x="131.8840579710145" y="-9.7098214285714288"/>
         </view>
     </objects>
     <resources>
-        <image name="metronome_arrow_down" width="11" height="7"/>
-        <image name="metronome_bg_s" width="72.5" height="72"/>
+        <image name="beat_button_bg" width="80.5" height="86"/>
         <image name="metronome_volume" width="18" height="18"/>
-        <image name="speed_add" width="72" height="72"/>
-        <image name="speed_minus" width="72" height="72"/>
+        <image name="rhythm_quarterNote" width="44" height="46"/>
     </resources>
 </document>

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

@@ -29,19 +29,19 @@
                                 <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="SpQ-th-fns"/>
                             </connections>
                         </button>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="beat_title" translatesAutoresizingMaskIntoConstraints="NO" id="9Bq-lB-sRU">
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="beat_title" translatesAutoresizingMaskIntoConstraints="NO" id="BeE-7E-gBM">
                             <rect key="frame" x="180.5" y="13.5" width="53" height="17"/>
                         </imageView>
                     </subviews>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
                         <constraint firstItem="DDF-Ml-1qT" firstAttribute="centerY" secondItem="SUk-Ag-K6M" secondAttribute="centerY" id="9S9-KI-omf"/>
-                        <constraint firstItem="9Bq-lB-sRU" firstAttribute="centerY" secondItem="SUk-Ag-K6M" secondAttribute="centerY" id="JJz-K2-il6"/>
                         <constraint firstItem="yeM-eb-aeH" firstAttribute="leading" secondItem="SUk-Ag-K6M" secondAttribute="leading" id="MBb-cm-NxT"/>
                         <constraint firstItem="DDF-Ml-1qT" firstAttribute="leading" secondItem="SUk-Ag-K6M" secondAttribute="leading" constant="14" id="U6P-oC-62I"/>
                         <constraint firstAttribute="bottom" secondItem="yeM-eb-aeH" secondAttribute="bottom" id="VHC-dZ-gcV"/>
+                        <constraint firstItem="BeE-7E-gBM" firstAttribute="centerY" secondItem="SUk-Ag-K6M" secondAttribute="centerY" id="Y9c-FT-p9G"/>
+                        <constraint firstItem="BeE-7E-gBM" firstAttribute="centerX" secondItem="SUk-Ag-K6M" secondAttribute="centerX" id="dY6-DH-PyV"/>
                         <constraint firstAttribute="height" constant="44" id="de5-7W-Mcn"/>
-                        <constraint firstItem="9Bq-lB-sRU" firstAttribute="centerX" secondItem="SUk-Ag-K6M" secondAttribute="centerX" id="gYk-hc-DEw"/>
                         <constraint firstItem="yeM-eb-aeH" firstAttribute="top" secondItem="SUk-Ag-K6M" secondAttribute="top" id="gln-eQ-4h0"/>
                     </constraints>
                 </view>

+ 0 - 3
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.h

@@ -27,9 +27,6 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (instancetype)shareInstance;
 
-/** 节拍类型 */
-@property (nonatomic, assign) KSWidgeMetronomeType currentType;
-
 /** 代理 */
 @property (nonatomic, weak) id <MetronomeControlViewDelegate> delegate;
 

+ 30 - 2
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.m

@@ -55,7 +55,7 @@
     [slider addTarget:self action:@selector(handleValue:) forControlEvents:UIControlEventValueChanged];
     
     self.slider = slider;
-    [self.slider setFrame:CGRectMake((316-233)/2.0, (316-233)/2.0, 233, 233)];
+    [self.slider setFrame:CGRectMake(([WidgetSpeedView getViewHeight]-233)/2.0, ([WidgetSpeedView getViewHeight]-233)/2.0, 233, 233)];
 }
 
 -(void)handleValue:(IACircularSlider*)slider{
@@ -66,6 +66,34 @@
 }
 
 
+- (IBAction)onReduceButtonClick:(id)sender {
+    if (self.speed > 50) {
+        [self.slider resetInitially];
+        self.speed --;
+    }else{
+        self.speed = 50;
+    }
+    [self updateSpeed];
+}
+
+
+- (IBAction)onAddButtonClick:(id)sender {
+    if (self.speed < 200) {
+        [self.slider resetInitially];
+        self.speed ++;
+    }else{
+        self.speed = 200;
+    }
+    [self updateSpeed];
+}
+
+- (void)updateSpeed {
+    if (self.delegate && [self.delegate respondsToSelector:@selector(modifySpeed:)]) {
+        [self.delegate modifySpeed:self.speed];
+    }
+}
+
+
 - (void)setSpeed:(int)speed {
     _speed = speed;
     self.speedLabel.text = [NSString stringWithFormat:@"%d", speed];
@@ -73,7 +101,7 @@
 }
 
 + (CGFloat)getViewHeight {
-    return 316.0f;
+    return IS_IPAD ? 356.0f : 316.0f;
 }
 /*
 // Only override drawRect: if you perform custom drawing.

+ 44 - 29
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/Metronome/WidgetSpeedView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" 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="21505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -14,55 +14,60 @@
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xgb-CP-q8k">
-                    <rect key="frame" x="28.666666666666657" y="0.0" width="316" height="316"/>
+                    <rect key="frame" x="28.5" y="0.0" width="316" height="316"/>
                     <subviews>
                         <imageView clipsSubviews="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="speed_background" translatesAutoresizingMaskIntoConstraints="NO" id="M3y-XL-rfN">
                             <rect key="frame" x="0.0" y="0.0" width="316" height="316"/>
                         </imageView>
                         <imageView clipsSubviews="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="speed_squre" translatesAutoresizingMaskIntoConstraints="NO" id="PdA-s1-D7c">
-                            <rect key="frame" x="41.333333333333314" y="41.666666666666657" width="233" height="232.99999999999997"/>
+                            <rect key="frame" x="41.5" y="41.5" width="233" height="233"/>
                         </imageView>
                         <imageView clipsSubviews="YES" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="speed_middle" translatesAutoresizingMaskIntoConstraints="NO" id="jI9-v9-Cp6">
                             <rect key="frame" x="69" y="69" width="178" height="178"/>
                         </imageView>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="speed_label_bg" translatesAutoresizingMaskIntoConstraints="NO" id="hrb-WR-z8E">
-                            <rect key="frame" x="110" y="131.66666666666666" width="96" height="53"/>
-                        </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="90" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e9W-bt-jeB">
-                            <rect key="frame" x="139.66666666666669" y="135.66666666666666" width="36.333333333333343" height="44.666666666666657"/>
-                            <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="38"/>
-                            <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="calibratedRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="速度" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tZK-hU-4GH">
-                            <rect key="frame" x="142.33333333333334" y="100.66666666666667" width="31" height="21"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="21" id="me9-RG-SaP"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
-                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
                     </subviews>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
                         <constraint firstItem="PdA-s1-D7c" firstAttribute="centerY" secondItem="xgb-CP-q8k" secondAttribute="centerY" id="2rS-Np-CTU"/>
-                        <constraint firstItem="e9W-bt-jeB" firstAttribute="centerY" secondItem="hrb-WR-z8E" secondAttribute="centerY" id="9gt-B1-WeR"/>
                         <constraint firstAttribute="width" secondItem="xgb-CP-q8k" secondAttribute="height" multiplier="1:1" id="9yL-rE-O7A"/>
-                        <constraint firstItem="e9W-bt-jeB" firstAttribute="centerY" secondItem="xgb-CP-q8k" secondAttribute="centerY" id="Atr-A9-US6"/>
-                        <constraint firstItem="e9W-bt-jeB" firstAttribute="centerX" secondItem="xgb-CP-q8k" secondAttribute="centerX" id="B3Z-Wx-QmF"/>
                         <constraint firstAttribute="trailing" secondItem="M3y-XL-rfN" secondAttribute="trailing" id="Fff-ft-9mF"/>
                         <constraint firstAttribute="bottom" secondItem="M3y-XL-rfN" secondAttribute="bottom" id="ONf-RV-cOi"/>
                         <constraint firstItem="jI9-v9-Cp6" firstAttribute="centerY" secondItem="xgb-CP-q8k" secondAttribute="centerY" id="RDb-xE-Bc3"/>
-                        <constraint firstItem="tZK-hU-4GH" firstAttribute="centerX" secondItem="xgb-CP-q8k" secondAttribute="centerX" id="S64-ef-KGf"/>
                         <constraint firstItem="jI9-v9-Cp6" firstAttribute="centerX" secondItem="xgb-CP-q8k" secondAttribute="centerX" id="Y10-0D-GTs"/>
                         <constraint firstItem="M3y-XL-rfN" firstAttribute="leading" secondItem="xgb-CP-q8k" secondAttribute="leading" id="bS2-Qj-cqY"/>
                         <constraint firstItem="M3y-XL-rfN" firstAttribute="top" secondItem="xgb-CP-q8k" secondAttribute="top" id="m8Z-QB-sEg"/>
-                        <constraint firstItem="hrb-WR-z8E" firstAttribute="top" secondItem="tZK-hU-4GH" secondAttribute="bottom" constant="10" id="oMX-Rd-SM9"/>
-                        <constraint firstItem="e9W-bt-jeB" firstAttribute="centerX" secondItem="hrb-WR-z8E" secondAttribute="centerX" id="tHb-fW-1eh"/>
                         <constraint firstItem="PdA-s1-D7c" firstAttribute="centerX" secondItem="xgb-CP-q8k" secondAttribute="centerX" id="y4L-uA-dtC"/>
                     </constraints>
                 </view>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="bpm_desc" translatesAutoresizingMaskIntoConstraints="NO" id="vdx-fq-pIK">
+                    <rect key="frame" x="157.5" y="146.5" width="20" height="23"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="23" id="KhC-Po-7fS"/>
+                        <constraint firstAttribute="width" constant="20" id="xvv-nJ-Stx"/>
+                    </constraints>
+                </imageView>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="90" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e9W-bt-jeB">
+                    <rect key="frame" x="179.5" y="135.5" width="36" height="45"/>
+                    <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="38"/>
+                    <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KfU-z1-0aQ">
+                    <rect key="frame" x="169.5" y="88.5" width="34" height="37"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" backgroundImage="speed_add"/>
+                    <connections>
+                        <action selector="onAddButtonClick:" destination="iN0-l3-epB" eventType="touchUpInside" id="5hL-hd-tYW"/>
+                    </connections>
+                </button>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rwM-WK-4P2">
+                    <rect key="frame" x="169.5" y="190.5" width="34" height="37"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" backgroundImage="speed_minus"/>
+                    <connections>
+                        <action selector="onReduceButtonClick:" destination="iN0-l3-epB" eventType="touchUpInside" id="sqt-G1-xYQ"/>
+                    </connections>
+                </button>
             </subviews>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
@@ -70,6 +75,14 @@
                 <constraint firstItem="xgb-CP-q8k" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="3dI-sO-kqz"/>
                 <constraint firstItem="xgb-CP-q8k" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="6cd-Mf-ZSX"/>
                 <constraint firstAttribute="bottom" secondItem="xgb-CP-q8k" secondAttribute="bottom" id="Gax-bu-HRd"/>
+                <constraint firstItem="e9W-bt-jeB" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="11" id="Is5-57-dMZ"/>
+                <constraint firstItem="rwM-WK-4P2" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="Tbr-Da-dhX"/>
+                <constraint firstItem="KfU-z1-0aQ" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="WCH-DH-ZnJ"/>
+                <constraint firstItem="e9W-bt-jeB" firstAttribute="top" secondItem="KfU-z1-0aQ" secondAttribute="bottom" constant="10" id="WRp-of-Zkf"/>
+                <constraint firstItem="e9W-bt-jeB" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="aB1-wE-LgM"/>
+                <constraint firstItem="rwM-WK-4P2" firstAttribute="top" secondItem="e9W-bt-jeB" secondAttribute="bottom" constant="10" id="g1P-Hb-UhS"/>
+                <constraint firstItem="vdx-fq-pIK" firstAttribute="centerY" secondItem="e9W-bt-jeB" secondAttribute="centerY" id="lGK-KP-uiJ"/>
+                <constraint firstItem="e9W-bt-jeB" firstAttribute="leading" secondItem="vdx-fq-pIK" secondAttribute="trailing" constant="2" id="rFK-JY-b6w"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
             <nil key="simulatedBottomBarMetrics"/>
@@ -82,9 +95,11 @@
         </view>
     </objects>
     <resources>
+        <image name="bpm_desc" width="20" height="23"/>
+        <image name="speed_add" width="34" height="37"/>
         <image name="speed_background" width="316" height="316"/>
-        <image name="speed_label_bg" width="96" height="53"/>
         <image name="speed_middle" width="178" height="178"/>
+        <image name="speed_minus" width="34" height="37"/>
         <image name="speed_squre" width="233" height="233"/>
     </resources>
 </document>

+ 0 - 27
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.h

@@ -1,27 +0,0 @@
-//
-//  SmallToolBodyView.h
-//  KulexiuForStudent
-//
-//  Created by 王智 on 2022/10/13.
-//
-
-#import <UIKit/UIKit.h>
-
-typedef NS_ENUM(NSInteger, TOOLTYPE) {
-    TOOLTYPE_METRONOME, // 节拍器
-    TOOLTYPE_TONE,      // 调音器
-};
-
-typedef void(^ToolFunctionCallback)(TOOLTYPE type);
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface SmallToolBodyView : UIView
-
-+ (instancetype)shareInstance;
-
-- (void)chooseToolCallback:(ToolFunctionCallback)callback;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 77
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.m

@@ -1,77 +0,0 @@
-//
-//  SmallToolBodyView.m
-//  KulexiuForStudent
-//
-//  Created by 王智 on 2022/10/13.
-//
-
-#import "SmallToolBodyView.h"
-
-@interface SmallToolBodyView ()
-
-@property (weak, nonatomic) IBOutlet UIView *metrnomeBgView;
-
-@property (weak, nonatomic) IBOutlet UIView *toneBgView;
-
-@property (nonatomic, copy) ToolFunctionCallback callback;
-
-@end
-
-@implementation SmallToolBodyView
-
-- (void)awakeFromNib {
-    [super awakeFromNib];
-    CAGradientLayer *layer = [self createGradientLayerFromColor:HexRGB(0xACFBEC) startPoint:CGPointMake(0.5, 0) endColor:HexRGB(0x7FEED9) endPoint:CGPointMake(0.5, 1) bounds:CGRectMake(0, 0, KPortraitWidth - 32, 114)];
-    layer.cornerRadius = 14.0f;
-    layer.masksToBounds = YES;
-    [self.metrnomeBgView.layer addSublayer:layer];
-    
-    CAGradientLayer *colorLayer = [self createGradientLayerFromColor:HexRGB(0xE2D5FF) startPoint:CGPointMake(0.5, 0) endColor:HexRGB(0xCAB2FF) endPoint:CGPointMake(0.5, 1) bounds:CGRectMake(0, 0, KPortraitWidth - 32, 114)];
-    colorLayer.cornerRadius = 14.0f;
-    colorLayer.masksToBounds = YES;
-    [self.toneBgView.layer addSublayer:colorLayer];
-}
-
-+ (instancetype)shareInstance {
-    SmallToolBodyView *view = [[[NSBundle mainBundle] loadNibNamed:@"SmallToolBodyView" owner:nil options:nil] firstObject];
-    return view;
-}
-
-- (void)chooseToolCallback:(ToolFunctionCallback)callback {
-    if (callback) {
-        self.callback = callback;
-    }
-}
-
-- (IBAction)chooseMetronome:(id)sender {
-    if (self.callback) {
-        self.callback(TOOLTYPE_METRONOME);
-    }
-}
-
-- (IBAction)chooseTone:(id)sender {
-    if (self.callback) {
-        self.callback(TOOLTYPE_TONE);
-    }
-}
-
-/*
-// Only override drawRect: if you perform custom drawing.
-// An empty implementation adversely affects performance during animation.
-- (void)drawRect:(CGRect)rect {
-    // Drawing code
-}
-*/
-
-- (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;
-}
-
-
-@end

+ 0 - 168
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/SmallToolBodyView.xib

@@ -1,168 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
-    <device id="retina6_0" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <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="SmallToolBodyView">
-            <rect key="frame" x="0.0" y="0.0" width="390" height="536"/>
-            <autoresizingMask key="autoresizingMask"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7pE-lf-Zsa">
-                    <rect key="frame" x="16" y="18" width="358" height="114"/>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <gestureRecognizers/>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KbL-Cl-bwO">
-                    <rect key="frame" x="16" y="18" width="358" height="114"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="节拍器" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mOb-C9-ek9">
-                            <rect key="frame" x="24" y="24" width="62" height="28"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="28" id="4cy-JE-o1v"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/>
-                            <color key="textColor" red="0.0" green="0.42745098039215684" blue="0.34509803921568627" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="节拍器,练习好节奏" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fYi-C4-Nd8">
-                            <rect key="frame" x="24" y="58" width="128.66666666666666" height="20"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="20" id="d06-5s-M0F"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                            <color key="textColor" red="0.0" green="0.42745098040000001" blue="0.34509803919999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_image" translatesAutoresizingMaskIntoConstraints="NO" id="Bog-1X-TMf">
-                            <rect key="frame" x="226" y="0.0" width="132" height="114"/>
-                            <constraints>
-                                <constraint firstAttribute="width" secondItem="Bog-1X-TMf" secondAttribute="height" multiplier="22:19" id="geJ-Gg-GV4"/>
-                            </constraints>
-                        </imageView>
-                    </subviews>
-                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <constraints>
-                        <constraint firstAttribute="bottom" secondItem="Bog-1X-TMf" secondAttribute="bottom" id="2U1-Ni-Bfu"/>
-                        <constraint firstAttribute="height" constant="114" id="3WE-5U-XPW"/>
-                        <constraint firstItem="mOb-C9-ek9" firstAttribute="top" secondItem="KbL-Cl-bwO" secondAttribute="top" constant="24" id="5IG-oq-ltv"/>
-                        <constraint firstAttribute="trailing" secondItem="Bog-1X-TMf" secondAttribute="trailing" id="CNH-J8-5wM"/>
-                        <constraint firstItem="mOb-C9-ek9" firstAttribute="leading" secondItem="KbL-Cl-bwO" secondAttribute="leading" constant="24" id="WUi-Xk-CB6"/>
-                        <constraint firstItem="fYi-C4-Nd8" firstAttribute="leading" secondItem="mOb-C9-ek9" secondAttribute="leading" id="phj-Lx-O0p"/>
-                        <constraint firstItem="Bog-1X-TMf" firstAttribute="top" secondItem="KbL-Cl-bwO" secondAttribute="top" id="qwC-c0-eGn"/>
-                        <constraint firstItem="fYi-C4-Nd8" firstAttribute="top" secondItem="mOb-C9-ek9" secondAttribute="bottom" constant="6" id="vaN-vB-Gwk"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="14"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                    <connections>
-                        <outletCollection property="gestureRecognizers" destination="9vs-gn-bTj" appends="YES" id="wzz-JZ-nwz"/>
-                    </connections>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6Es-PT-RKh">
-                    <rect key="frame" x="16" y="148" width="358" height="114"/>
-                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-                    <gestureRecognizers/>
-                </view>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Usm-eK-CbE">
-                    <rect key="frame" x="16" y="148" width="358" height="114"/>
-                    <subviews>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="调音器" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="a3D-R7-hIK">
-                            <rect key="frame" x="24" y="24" width="62" height="28"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="28" id="H7M-N6-557"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/>
-                            <color key="textColor" red="0.42352941176470588" green="0.0" blue="0.76470588235294112" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="精准调音,一劳永逸" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="n9K-wq-FY7">
-                            <rect key="frame" x="24" y="58" width="128.66666666666666" height="20"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="20" id="laX-31-CM7"/>
-                            </constraints>
-                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                            <color key="textColor" red="0.42352941176470588" green="0.0" blue="0.76470588235294112" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tone_tuning" translatesAutoresizingMaskIntoConstraints="NO" id="tri-rT-zBB">
-                            <rect key="frame" x="226" y="0.0" width="132" height="114"/>
-                            <constraints>
-                                <constraint firstAttribute="width" secondItem="tri-rT-zBB" secondAttribute="height" multiplier="22:19" id="SY7-Or-Rqy"/>
-                            </constraints>
-                        </imageView>
-                    </subviews>
-                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <constraints>
-                        <constraint firstItem="n9K-wq-FY7" firstAttribute="leading" secondItem="a3D-R7-hIK" secondAttribute="leading" id="3vQ-bM-igo"/>
-                        <constraint firstItem="tri-rT-zBB" firstAttribute="top" secondItem="Usm-eK-CbE" secondAttribute="top" id="KCv-Cp-h9E"/>
-                        <constraint firstItem="a3D-R7-hIK" firstAttribute="top" secondItem="Usm-eK-CbE" secondAttribute="top" constant="24" id="QGE-gc-JwY"/>
-                        <constraint firstItem="n9K-wq-FY7" firstAttribute="top" secondItem="a3D-R7-hIK" secondAttribute="bottom" constant="6" id="Rwh-yq-iaI"/>
-                        <constraint firstAttribute="bottom" secondItem="tri-rT-zBB" secondAttribute="bottom" id="hFh-0A-ete"/>
-                        <constraint firstAttribute="height" constant="114" id="jJn-LN-WQj"/>
-                        <constraint firstItem="a3D-R7-hIK" firstAttribute="leading" secondItem="Usm-eK-CbE" secondAttribute="leading" constant="24" id="t1c-0J-O2x"/>
-                        <constraint firstAttribute="trailing" secondItem="tri-rT-zBB" secondAttribute="trailing" id="y7r-SW-qnQ"/>
-                    </constraints>
-                    <userDefinedRuntimeAttributes>
-                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                            <real key="value" value="14"/>
-                        </userDefinedRuntimeAttribute>
-                    </userDefinedRuntimeAttributes>
-                    <connections>
-                        <outletCollection property="gestureRecognizers" destination="g8h-7k-sbT" appends="YES" id="5CR-UR-wvj"/>
-                    </connections>
-                </view>
-            </subviews>
-            <color key="backgroundColor" red="0.97254901960784312" green="0.97647058823529409" blue="0.9882352941176471" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="6Es-PT-RKh" firstAttribute="top" secondItem="Usm-eK-CbE" secondAttribute="top" id="6dg-GT-Ksh"/>
-                <constraint firstItem="7pE-lf-Zsa" firstAttribute="bottom" secondItem="KbL-Cl-bwO" secondAttribute="bottom" id="GP7-dl-p1G"/>
-                <constraint firstItem="6Es-PT-RKh" firstAttribute="bottom" secondItem="Usm-eK-CbE" secondAttribute="bottom" id="HsQ-Jp-7lQ"/>
-                <constraint firstItem="7pE-lf-Zsa" firstAttribute="trailing" secondItem="KbL-Cl-bwO" secondAttribute="trailing" id="KLk-JI-yy5"/>
-                <constraint firstItem="Usm-eK-CbE" firstAttribute="top" secondItem="KbL-Cl-bwO" secondAttribute="bottom" constant="16" id="NNX-2g-AL1"/>
-                <constraint firstItem="KbL-Cl-bwO" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="18" id="Q2d-d9-jkt"/>
-                <constraint firstItem="7pE-lf-Zsa" firstAttribute="leading" secondItem="KbL-Cl-bwO" secondAttribute="leading" id="SX4-zW-u40"/>
-                <constraint firstItem="6Es-PT-RKh" firstAttribute="leading" secondItem="Usm-eK-CbE" secondAttribute="leading" id="UVc-oT-i8l"/>
-                <constraint firstItem="7pE-lf-Zsa" firstAttribute="top" secondItem="KbL-Cl-bwO" secondAttribute="top" id="eIY-He-vXn"/>
-                <constraint firstItem="KbL-Cl-bwO" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="kZn-jQ-9OT"/>
-                <constraint firstItem="Usm-eK-CbE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="16" id="nNg-ul-d1k"/>
-                <constraint firstAttribute="trailing" secondItem="KbL-Cl-bwO" secondAttribute="trailing" constant="16" id="r6T-3q-ibo"/>
-                <constraint firstAttribute="trailing" secondItem="Usm-eK-CbE" secondAttribute="trailing" constant="16" id="vZr-Ku-Vfw"/>
-                <constraint firstItem="6Es-PT-RKh" firstAttribute="trailing" secondItem="Usm-eK-CbE" secondAttribute="trailing" id="xtt-yt-JZo"/>
-            </constraints>
-            <nil key="simulatedTopBarMetrics"/>
-            <nil key="simulatedBottomBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <connections>
-                <outlet property="metrnomeBgView" destination="7pE-lf-Zsa" id="6s3-XW-LSJ"/>
-                <outlet property="toneBgView" destination="6Es-PT-RKh" id="TbE-VR-gNn"/>
-            </connections>
-            <point key="canvasLocation" x="87.692307692307693" y="68.957345971563981"/>
-        </view>
-        <tapGestureRecognizer id="9vs-gn-bTj">
-            <connections>
-                <action selector="chooseMetronome:" destination="iN0-l3-epB" id="rdo-OF-fwD"/>
-            </connections>
-        </tapGestureRecognizer>
-        <tapGestureRecognizer id="g8h-7k-sbT">
-            <connections>
-                <action selector="chooseTone:" destination="iN0-l3-epB" id="ueq-cr-tj7"/>
-            </connections>
-        </tapGestureRecognizer>
-    </objects>
-    <resources>
-        <image name="metronome_image" width="132" height="114"/>
-        <image name="tone_tuning" width="132" height="114"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>

+ 3 - 2
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.h

@@ -17,6 +17,7 @@ typedef NS_ENUM(NSInteger, TUNINGACTION) {
     TUNINGACTION_STOP,        // 停止播放
     TUNINGACTION_METRONOME,   // 节拍器
     TUNINGACTION_BEATCHOOSE,  // 选择拍号
+    TUNINGACTION_RHYTHMCHOOSE, // 选择节奏
     TUNINGACTION_BEATPLAY,    // 播放节拍器
     TUNINGACTION_BEATSTOP,    // 暂停节拍器
 };
@@ -35,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (weak, nonatomic) IBOutlet UILabel *beatType;
 
+@property (weak, nonatomic) IBOutlet UIImageView *rhythmImage;
+
 @property (weak, nonatomic) IBOutlet UIImageView *metronomeStatus;
 
 @property (weak, nonatomic) IBOutlet UIView *plateView;
@@ -80,8 +83,6 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (void)tuningViewAction:(TuningActionCallback)callback;
 
-+ (CGFloat)getViewHeight;
-
 @end
 
 NS_ASSUME_NONNULL_END

+ 7 - 6
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.m

@@ -66,6 +66,12 @@
     }
 }
 
+- (IBAction)chooseRhythm:(id)sender {
+    if (self.callback) {
+        self.callback(TUNINGACTION_RHYTHMCHOOSE, self.A4Frequence);
+    }
+}
+
 
 - (IBAction)metroPlayAction:(id)sender {
     self.metronomePlayStatus = !self.metronomePlayStatus;
@@ -78,7 +84,7 @@
 - (void)setA4Frequence:(NSInteger)A4Frequence {
     _A4Frequence = A4Frequence;
     self.A4FrequenceLabel.text = [NSString stringWithFormat:@"A4=%zdHz",A4Frequence];
-    if (A4Frequence > 440) {
+    if (A4Frequence > DEFALUT_A4FREQUENCE) {
         self.warningImage.hidden = NO;
     }
     else {
@@ -146,11 +152,6 @@
     }];
 }
 
-+ (CGFloat)getViewHeight {
-    CGFloat leftSpace = KPortraitWidth / 8.0f;
-    CGFloat plateHeight = IS_IPAD ? (KPortraitWidth - leftSpace * 2) / 2 : KPortraitWidth / 2;
-    return plateHeight + 64 + 36 + 32 + 6 + 145 + 3 + 2 + 84 + 3 + 11 + 72 + 29+ 20;
-}
 
 
 - (void)setMetronomePlayStatus:(BOOL)metronomePlayStatus {

+ 102 - 43
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/ToneTuningBodyView.xib

@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina6_0" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
         <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="ToneTuningBodyView">
-            <rect key="frame" x="0.0" y="0.0" width="375" height="704"/>
+            <rect key="frame" x="0.0" y="0.0" width="375" height="701"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PnS-Ku-vsa">
@@ -249,7 +249,7 @@
                     </connections>
                 </button>
                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="toning_bottom" translatesAutoresizingMaskIntoConstraints="NO" id="IXi-hL-in1">
-                    <rect key="frame" x="18.666666666666657" y="655" width="338" height="29"/>
+                    <rect key="frame" x="18.666666666666657" y="652" width="338" height="29"/>
                     <constraints>
                         <constraint firstAttribute="width" constant="338" id="Ohx-Sa-5XQ"/>
                         <constraint firstAttribute="height" constant="29" id="tsc-a8-bbh"/>
@@ -288,28 +288,72 @@
                     </constraints>
                 </imageView>
                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tuning_metronome_play" translatesAutoresizingMaskIntoConstraints="NO" id="kfM-1R-aby">
-                    <rect key="frame" x="132.66666666666666" y="553" width="110" height="110"/>
+                    <rect key="frame" x="132.66666666666666" y="551.66666666666663" width="110" height="110"/>
                 </imageView>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Hjq-pN-uJq">
-                    <rect key="frame" x="233.66666666666663" y="572" width="128.33333333333337" height="72"/>
+                    <rect key="frame" x="233.66666666666663" y="572" width="128.33333333333337" height="69"/>
                     <subviews>
                         <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_bg_s" translatesAutoresizingMaskIntoConstraints="NO" id="o5o-uh-SPK">
-                            <rect key="frame" x="0.0" y="0.0" width="128.33333333333334" height="72"/>
+                            <rect key="frame" x="0.0" y="0.0" width="128.33333333333334" height="69"/>
                         </imageView>
-                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="4/4" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MF9-mi-VE8">
-                            <rect key="frame" x="37.666666666666657" y="20" width="30" height="26"/>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TOb-41-CbM">
+                            <rect key="frame" x="19.999999999999996" y="0.0" width="43.666666666666657" height="69"/>
+                            <subviews>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="4" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MF9-mi-VE8">
+                                    <rect key="frame" x="6.3333333333333419" y="22" width="11.666666666666664" height="25"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="25" id="puI-cv-zSi"/>
+                                    </constraints>
+                                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
+                                    <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="calibratedRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="拍" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l30-hr-Jnm">
+                                    <rect key="frame" x="23.000000000000028" y="24.666666666666629" width="14" height="20"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="14" id="a69-vk-GNK"/>
+                                        <constraint firstAttribute="height" constant="20" id="qsb-YC-GOK"/>
+                                    </constraints>
+                                    <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
+                                    <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <constraints>
-                                <constraint firstAttribute="height" constant="26" id="puI-cv-zSi"/>
+                                <constraint firstItem="l30-hr-Jnm" firstAttribute="leading" secondItem="MF9-mi-VE8" secondAttribute="trailing" constant="5" id="T4W-ff-wsu"/>
+                                <constraint firstItem="MF9-mi-VE8" firstAttribute="centerY" secondItem="TOb-41-CbM" secondAttribute="centerY" id="cMe-gz-GDe"/>
+                                <constraint firstItem="MF9-mi-VE8" firstAttribute="centerX" secondItem="TOb-41-CbM" secondAttribute="centerX" constant="-9.5" id="cxG-QN-f5s"/>
+                                <constraint firstItem="l30-hr-Jnm" firstAttribute="centerY" secondItem="MF9-mi-VE8" secondAttribute="centerY" id="p6e-Ya-Y4e"/>
                             </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
-                            <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="calibratedRGB"/>
-                            <nil key="highlightedColor"/>
-                        </label>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_arrow_down" translatesAutoresizingMaskIntoConstraints="NO" id="rg7-hy-7Wr">
-                            <rect key="frame" x="79.666666666666657" y="29.666666666666629" width="11" height="7"/>
-                        </imageView>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kdo-V4-183">
+                            <rect key="frame" x="64.666666666666657" y="0.0" width="43.666666666666657" height="69"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rhythm_quarterNote" translatesAutoresizingMaskIntoConstraints="NO" id="rg7-hy-7Wr">
+                                    <rect key="frame" x="4.3333333333333712" y="16.333333333333375" width="35" height="36.333333333333343"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="35" id="Lzb-Hh-aXf"/>
+                                        <constraint firstAttribute="width" secondItem="rg7-hy-7Wr" secondAttribute="height" multiplier="22:23" id="ree-Wx-Ba6"/>
+                                    </constraints>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstItem="rg7-hy-7Wr" firstAttribute="centerY" secondItem="kdo-V4-183" secondAttribute="centerY" id="7OB-PY-F5N"/>
+                                <constraint firstItem="rg7-hy-7Wr" firstAttribute="centerX" secondItem="kdo-V4-183" secondAttribute="centerX" id="Sp5-bf-Iv8"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UQQ-ok-hI2">
+                            <rect key="frame" x="63.666666666666657" y="22.666666666666629" width="1" height="24"/>
+                            <color key="backgroundColor" red="0.70196078431372544" green="0.88627450980392153" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="NKS-cQ-MQB"/>
+                                <constraint firstAttribute="width" constant="1" id="ciM-5K-Qod"/>
+                            </constraints>
+                        </view>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eQb-Ay-DFn">
-                            <rect key="frame" x="0.0" y="0.0" width="128.33333333333334" height="72"/>
+                            <rect key="frame" x="0.0" y="0.0" width="58.666666666666664" height="69"/>
                             <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">
@@ -319,25 +363,46 @@
                                 <action selector="chooseBeat:" destination="iN0-l3-epB" eventType="touchUpInside" id="UIb-FA-KWD"/>
                             </connections>
                         </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SFO-Qb-Hry">
+                            <rect key="frame" x="69.666666666666657" y="0.0" width="58.666666666666657" height="69"/>
+                            <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">
+                                <color key="titleColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            </state>
+                            <connections>
+                                <action selector="chooseRhythm:" destination="iN0-l3-epB" eventType="touchUpInside" id="u7B-qi-iaN"/>
+                            </connections>
+                        </button>
                     </subviews>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
+                        <constraint firstAttribute="bottom" secondItem="SFO-Qb-Hry" secondAttribute="bottom" id="0pl-fE-5TT"/>
                         <constraint firstAttribute="bottom" secondItem="o5o-uh-SPK" secondAttribute="bottom" id="2U8-oI-yrN"/>
                         <constraint firstItem="o5o-uh-SPK" firstAttribute="leading" secondItem="Hjq-pN-uJq" secondAttribute="leading" id="2yi-V9-FHL"/>
-                        <constraint firstItem="rg7-hy-7Wr" firstAttribute="centerY" secondItem="MF9-mi-VE8" secondAttribute="centerY" id="Vc8-fw-HUF"/>
-                        <constraint firstAttribute="trailing" secondItem="eQb-Ay-DFn" secondAttribute="trailing" id="YaW-Qa-hMC"/>
-                        <constraint firstItem="MF9-mi-VE8" firstAttribute="centerX" secondItem="Hjq-pN-uJq" secondAttribute="centerX" constant="-11.5" id="b87-mh-sJA"/>
+                        <constraint firstAttribute="trailing" secondItem="kdo-V4-183" secondAttribute="trailing" constant="20" id="9SX-HF-NTH"/>
+                        <constraint firstItem="SFO-Qb-Hry" firstAttribute="top" secondItem="Hjq-pN-uJq" secondAttribute="top" id="INy-Bg-8uc"/>
+                        <constraint firstItem="TOb-41-CbM" firstAttribute="top" secondItem="Hjq-pN-uJq" secondAttribute="top" id="P7m-us-VXN"/>
+                        <constraint firstAttribute="trailing" secondItem="SFO-Qb-Hry" secondAttribute="trailing" id="PUL-dO-NBf"/>
+                        <constraint firstItem="UQQ-ok-hI2" firstAttribute="leading" secondItem="eQb-Ay-DFn" secondAttribute="trailing" constant="5" id="QvL-ov-5K0"/>
+                        <constraint firstAttribute="bottom" secondItem="TOb-41-CbM" secondAttribute="bottom" id="SLN-Ul-07w"/>
+                        <constraint firstItem="UQQ-ok-hI2" firstAttribute="leading" secondItem="TOb-41-CbM" secondAttribute="trailing" id="Vjt-wG-C6f"/>
+                        <constraint firstItem="UQQ-ok-hI2" firstAttribute="centerX" secondItem="Hjq-pN-uJq" secondAttribute="centerX" id="Xbi-jI-GKO"/>
+                        <constraint firstItem="TOb-41-CbM" firstAttribute="leading" secondItem="Hjq-pN-uJq" secondAttribute="leading" constant="20" id="Xex-zQ-GIG"/>
                         <constraint firstItem="eQb-Ay-DFn" firstAttribute="top" secondItem="Hjq-pN-uJq" secondAttribute="top" id="dtg-ms-9dR"/>
                         <constraint firstItem="o5o-uh-SPK" firstAttribute="top" secondItem="Hjq-pN-uJq" secondAttribute="top" id="h3y-pC-Qce"/>
-                        <constraint firstItem="rg7-hy-7Wr" firstAttribute="leading" secondItem="MF9-mi-VE8" secondAttribute="trailing" constant="12" id="mf1-Px-mJr"/>
+                        <constraint firstItem="UQQ-ok-hI2" firstAttribute="centerY" secondItem="Hjq-pN-uJq" secondAttribute="centerY" id="iVA-AN-ZJa"/>
+                        <constraint firstItem="kdo-V4-183" firstAttribute="top" secondItem="Hjq-pN-uJq" secondAttribute="top" id="jyi-EH-7ET"/>
                         <constraint firstItem="eQb-Ay-DFn" firstAttribute="leading" secondItem="Hjq-pN-uJq" secondAttribute="leading" id="mqQ-pi-VmJ"/>
                         <constraint firstAttribute="bottom" secondItem="eQb-Ay-DFn" secondAttribute="bottom" id="nsj-5H-8hH"/>
-                        <constraint firstItem="rg7-hy-7Wr" firstAttribute="centerY" secondItem="Hjq-pN-uJq" secondAttribute="centerY" constant="-3" id="rdR-58-aNl"/>
+                        <constraint firstItem="kdo-V4-183" firstAttribute="leading" secondItem="UQQ-ok-hI2" secondAttribute="trailing" id="qFk-1P-DsT"/>
+                        <constraint firstItem="SFO-Qb-Hry" firstAttribute="leading" secondItem="UQQ-ok-hI2" secondAttribute="trailing" constant="5" id="sin-s6-k1x"/>
                         <constraint firstAttribute="trailing" secondItem="o5o-uh-SPK" secondAttribute="trailing" id="vsK-8i-ieQ"/>
+                        <constraint firstAttribute="bottom" secondItem="kdo-V4-183" secondAttribute="bottom" id="ybo-yW-Bv1"/>
                     </constraints>
                 </view>
                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mfr-Pq-edx">
-                    <rect key="frame" x="148.66666666666666" y="569" width="78" height="78"/>
+                    <rect key="frame" x="150" y="569" width="75" height="75"/>
                     <constraints>
                         <constraint firstAttribute="width" secondItem="Mfr-Pq-edx" secondAttribute="height" multiplier="1:1" id="ly0-Mm-rzd"/>
                     </constraints>
@@ -347,25 +412,22 @@
                     </connections>
                 </button>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8kr-5S-DeP">
-                    <rect key="frame" x="14" y="572" width="128.66666666666666" height="72"/>
+                    <rect key="frame" x="14" y="572" width="128.66666666666666" height="69"/>
                     <subviews>
                         <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="metronome_bg_s" translatesAutoresizingMaskIntoConstraints="NO" id="VAF-j3-DWg">
-                            <rect key="frame" x="0.0" y="0.0" width="128.66666666666666" height="72"/>
-                        </imageView>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="beat_speed" translatesAutoresizingMaskIntoConstraints="NO" id="6kb-g0-vNj">
-                            <rect key="frame" x="36.666666666666664" y="23" width="19" height="20"/>
+                            <rect key="frame" x="0.0" y="0.0" width="128.66666666666666" height="69"/>
                         </imageView>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="90" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ewa-aA-r7P">
-                            <rect key="frame" x="67.666666666666671" y="20" width="24.333333333333329" height="26"/>
+                            <rect key="frame" x="52.666666666666679" y="23" width="23.333333333333336" height="25"/>
                             <constraints>
-                                <constraint firstAttribute="height" constant="26" id="cNr-h8-dg5"/>
+                                <constraint firstAttribute="height" constant="25" id="cNr-h8-dg5"/>
                             </constraints>
-                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
                             <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="calibratedRGB"/>
                             <nil key="highlightedColor"/>
                         </label>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pT0-rO-04P">
-                            <rect key="frame" x="0.0" y="0.0" width="128.66666666666666" height="72"/>
+                            <rect key="frame" x="0.0" y="0.0" width="128.66666666666666" height="69"/>
                             <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">
@@ -378,16 +440,13 @@
                     </subviews>
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
-                        <constraint firstItem="Ewa-aA-r7P" firstAttribute="leading" secondItem="6kb-g0-vNj" secondAttribute="trailing" constant="12" id="2zh-7M-AJh"/>
-                        <constraint firstItem="Ewa-aA-r7P" firstAttribute="centerX" secondItem="8kr-5S-DeP" secondAttribute="centerX" constant="15.5" id="4Dk-3U-fki"/>
+                        <constraint firstItem="Ewa-aA-r7P" firstAttribute="centerX" secondItem="8kr-5S-DeP" secondAttribute="centerX" id="4Dk-3U-fki"/>
+                        <constraint firstItem="Ewa-aA-r7P" firstAttribute="top" secondItem="8kr-5S-DeP" secondAttribute="top" constant="23" id="6ju-mS-1v5"/>
                         <constraint firstItem="pT0-rO-04P" firstAttribute="top" secondItem="8kr-5S-DeP" secondAttribute="top" id="Gp1-iO-AQM"/>
-                        <constraint firstItem="6kb-g0-vNj" firstAttribute="top" secondItem="8kr-5S-DeP" secondAttribute="top" constant="23" id="J8e-q3-gt8"/>
-                        <constraint firstItem="6kb-g0-vNj" firstAttribute="centerY" secondItem="8kr-5S-DeP" secondAttribute="centerY" constant="-3" id="LTb-Ou-zXL"/>
                         <constraint firstAttribute="bottom" secondItem="pT0-rO-04P" secondAttribute="bottom" id="PN1-JA-uLo"/>
                         <constraint firstAttribute="bottom" secondItem="VAF-j3-DWg" secondAttribute="bottom" id="PNp-1X-Lvq"/>
                         <constraint firstItem="VAF-j3-DWg" firstAttribute="leading" secondItem="8kr-5S-DeP" secondAttribute="leading" id="QhE-Ma-fiZ"/>
-                        <constraint firstItem="6kb-g0-vNj" firstAttribute="centerY" secondItem="Ewa-aA-r7P" secondAttribute="centerY" id="SWL-po-hsM"/>
-                        <constraint firstAttribute="height" constant="72" id="Upq-IX-582"/>
+                        <constraint firstAttribute="height" constant="69" id="Upq-IX-582"/>
                         <constraint firstItem="pT0-rO-04P" firstAttribute="leading" secondItem="8kr-5S-DeP" secondAttribute="leading" id="UzJ-IH-swc"/>
                         <constraint firstItem="VAF-j3-DWg" firstAttribute="top" secondItem="8kr-5S-DeP" secondAttribute="top" id="VgU-OA-MnB"/>
                         <constraint firstAttribute="trailing" secondItem="pT0-rO-04P" secondAttribute="trailing" id="btC-8J-4KW"/>
@@ -477,6 +536,7 @@
                 <outlet property="plateWidth" destination="gV3-KZ-iAV" id="Ed8-6M-fxK"/>
                 <outlet property="playButton" destination="p0z-qL-bMm" id="DsB-sp-PJ7"/>
                 <outlet property="preFrequence" destination="5sT-Eb-2rJ" id="YqE-f3-IK2"/>
+                <outlet property="rhythmImage" destination="rg7-hy-7Wr" id="bik-Tc-U9H"/>
                 <outlet property="rightImage" destination="dOO-kx-vvP" id="qI5-na-huC"/>
                 <outlet property="speedValue" destination="Ewa-aA-r7P" id="bz7-mu-K7F"/>
                 <outlet property="topImage" destination="B2r-VK-RGz" id="4iy-Bh-KQf"/>
@@ -486,22 +546,21 @@
                 <outlet property="transferView" destination="ya5-kp-sTW" id="VPm-KO-4q0"/>
                 <outlet property="warningImage" destination="Sbe-L2-liH" id="mzu-oK-f8F"/>
             </connections>
-            <point key="canvasLocation" x="123.84615384615384" y="59.004739336492889"/>
+            <point key="canvasLocation" x="123.84615384615384" y="58.649289099526065"/>
         </view>
     </objects>
     <resources>
-        <image name="beat_speed" width="19" height="20"/>
         <image name="forkButton_bg" width="40.333332061767578" height="84"/>
         <image name="fork_unPlay" width="42" height="28"/>
         <image name="fork_unchoose" width="42" height="28"/>
         <image name="frequence_right" width="25" height="25"/>
-        <image name="metronome_arrow_down" width="11" height="7"/>
-        <image name="metronome_bg_s" width="71.666664123535156" height="72"/>
+        <image name="metronome_bg_s" width="59" height="69"/>
         <image name="pitch_bg" width="89.333335876464844" height="145"/>
         <image name="plate_bg" width="286" height="287"/>
         <image name="plate_mid" width="129" height="129"/>
         <image name="plate_top" width="97" height="97"/>
         <image name="playButton_bg" width="40.333332061767578" height="84"/>
+        <image name="rhythm_quarterNote" width="44" height="46"/>
         <image name="toning_bottom" width="328" height="19"/>
         <image name="tuning_decorate" width="48" height="32"/>
         <image name="tuning_metronome_play" width="110" height="110"/>

+ 3 - 3
KulexiuForStudent/KulexiuForStudent/Module/Widget/View/toneTuning/TuningNavView.xib

@@ -39,7 +39,7 @@
                                 <action selector="settingAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="10h-IE-KXJ"/>
                             </connections>
                         </button>
-                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tuning_title" translatesAutoresizingMaskIntoConstraints="NO" id="WUo-55-1q9">
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tuning_title" translatesAutoresizingMaskIntoConstraints="NO" id="6JB-L0-XFt">
                             <rect key="frame" x="168" y="13.666666666666664" width="54" height="16.999999999999993"/>
                         </imageView>
                     </subviews>
@@ -47,15 +47,15 @@
                     <constraints>
                         <constraint firstAttribute="trailing" secondItem="BFU-Xz-2Xu" secondAttribute="trailing" id="0QV-8r-cmb"/>
                         <constraint firstItem="pFx-8o-VCU" firstAttribute="leading" secondItem="XRC-8p-p4e" secondAttribute="leading" id="0la-07-HRD"/>
+                        <constraint firstItem="6JB-L0-XFt" firstAttribute="centerY" secondItem="XRC-8p-p4e" secondAttribute="centerY" id="0t4-f0-x8g"/>
                         <constraint firstItem="BFU-Xz-2Xu" firstAttribute="top" secondItem="XRC-8p-p4e" secondAttribute="top" id="1ZM-4W-pkR"/>
+                        <constraint firstItem="6JB-L0-XFt" firstAttribute="centerX" secondItem="XRC-8p-p4e" secondAttribute="centerX" id="2cD-4V-3qz"/>
                         <constraint firstAttribute="bottom" secondItem="BFU-Xz-2Xu" secondAttribute="bottom" id="MLk-Cq-pRw"/>
                         <constraint firstItem="BFU-Xz-2Xu" firstAttribute="leading" secondItem="YlL-14-R48" secondAttribute="leading" id="S7q-SJ-hjs"/>
-                        <constraint firstItem="WUo-55-1q9" firstAttribute="centerX" secondItem="XRC-8p-p4e" secondAttribute="centerX" id="Z50-LT-87O"/>
                         <constraint firstItem="YlL-14-R48" firstAttribute="centerY" secondItem="XRC-8p-p4e" secondAttribute="centerY" id="Zc8-0c-TcZ"/>
                         <constraint firstItem="EN2-WR-x5g" firstAttribute="centerY" secondItem="XRC-8p-p4e" secondAttribute="centerY" id="Zdd-20-X1y"/>
                         <constraint firstAttribute="height" constant="44" id="cm1-xm-D5Z"/>
                         <constraint firstAttribute="bottom" secondItem="pFx-8o-VCU" secondAttribute="bottom" id="dGQ-eq-OMp"/>
-                        <constraint firstItem="WUo-55-1q9" firstAttribute="centerY" secondItem="XRC-8p-p4e" secondAttribute="centerY" id="j4n-zh-Pde"/>
                         <constraint firstAttribute="trailing" secondItem="YlL-14-R48" secondAttribute="trailing" constant="22" id="jwl-X5-VvP"/>
                         <constraint firstItem="EN2-WR-x5g" firstAttribute="leading" secondItem="XRC-8p-p4e" secondAttribute="leading" constant="14" id="p0O-O5-qtS"/>
                         <constraint firstItem="pFx-8o-VCU" firstAttribute="top" secondItem="XRC-8p-p4e" secondAttribute="top" id="u6y-gg-F2T"/>