├── .travis.yml ├── KFFlyCommentViewDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── YGFlyCommentDemo.xcscmblueprint └── xcshareddata │ └── xcschemes │ └── YGFlyCommentDemo.xcscheme ├── KFFlyCommentViewDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── home_login_qq_color.imageset │ │ ├── Contents.json │ │ ├── home_login_qq_color.png │ │ ├── home_login_qq_color@2x.png │ │ └── home_login_qq_color@3x.png │ ├── home_login_wechat_color.imageset │ │ ├── Contents.json │ │ ├── home_login_wechat_color.png │ │ ├── home_login_wechat_color@2x.png │ │ └── home_login_wechat_color@3x.png │ ├── home_login_weibo_color.imageset │ │ ├── Contents.json │ │ ├── home_login_weibo_color.png │ │ ├── home_login_weibo_color@2x.png │ │ └── home_login_weibo_color@3x.png │ ├── icon_120-1.imageset │ │ ├── Contents.json │ │ └── icon_120-1.png │ └── rank_charm_heart.imageset │ │ ├── Contents.json │ │ ├── rank_charm_heart.png │ │ ├── rank_charm_heart@2x.png │ │ └── rank_charm_heart@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CustomView.h ├── CustomView.m ├── GoViewController.h ├── GoViewController.m ├── Info.plist ├── KFFlyCommentView │ ├── KFFlyCommentTrackView.h │ ├── KFFlyCommentTrackView.m │ ├── KFFlyCommentView.h │ └── KFFlyCommentView.m ├── ViewController.h ├── ViewController.m ├── YGFlyCommentModel.h ├── YGFlyCommentModel.m ├── YGFlyCommentViewAnother.h ├── YGFlyCommentViewAnother.m └── main.m └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.3.2 3 | xcode_project: YGFlyCommentDemo.xcodeproj 4 | xcode_scheme: YGFlyCommentDemo 5 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F9207B571EC2A7790025BD31 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B561EC2A7790025BD31 /* main.m */; }; 11 | F9207B5A1EC2A7790025BD31 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B591EC2A7790025BD31 /* AppDelegate.m */; }; 12 | F9207B5D1EC2A7790025BD31 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B5C1EC2A7790025BD31 /* ViewController.m */; }; 13 | F9207B601EC2A7790025BD31 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F9207B5E1EC2A7790025BD31 /* Main.storyboard */; }; 14 | F9207B621EC2A7790025BD31 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F9207B611EC2A7790025BD31 /* Assets.xcassets */; }; 15 | F9207B651EC2A7790025BD31 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F9207B631EC2A7790025BD31 /* LaunchScreen.storyboard */; }; 16 | F9207B7D1EC2AD170025BD31 /* GoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B7C1EC2AD170025BD31 /* GoViewController.m */; }; 17 | F9207B821EC2B1D00025BD31 /* YGFlyCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B7F1EC2B1CF0025BD31 /* YGFlyCommentModel.m */; }; 18 | F9207B831EC2B1D00025BD31 /* CustomView.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B811EC2B1D00025BD31 /* CustomView.m */; }; 19 | F9207B861EC2B1F70025BD31 /* YGFlyCommentViewAnother.m in Sources */ = {isa = PBXBuildFile; fileRef = F9207B851EC2B1F70025BD31 /* YGFlyCommentViewAnother.m */; }; 20 | F975F1C728F9233F00090ADE /* KFFlyCommentTrackView.m in Sources */ = {isa = PBXBuildFile; fileRef = F975F1C528F9233F00090ADE /* KFFlyCommentTrackView.m */; }; 21 | F975F1C828F9233F00090ADE /* KFFlyCommentView.m in Sources */ = {isa = PBXBuildFile; fileRef = F975F1C628F9233F00090ADE /* KFFlyCommentView.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | F9207B521EC2A7790025BD31 /* KFFlyCommentViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KFFlyCommentViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | F9207B561EC2A7790025BD31 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 27 | F9207B581EC2A7790025BD31 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 28 | F9207B591EC2A7790025BD31 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 29 | F9207B5B1EC2A7790025BD31 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 30 | F9207B5C1EC2A7790025BD31 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 31 | F9207B5F1EC2A7790025BD31 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 32 | F9207B611EC2A7790025BD31 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | F9207B641EC2A7790025BD31 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 34 | F9207B661EC2A7790025BD31 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | F9207B7B1EC2AD170025BD31 /* GoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GoViewController.h; sourceTree = ""; }; 36 | F9207B7C1EC2AD170025BD31 /* GoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoViewController.m; sourceTree = ""; }; 37 | F9207B7E1EC2B1CF0025BD31 /* YGFlyCommentModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGFlyCommentModel.h; sourceTree = ""; }; 38 | F9207B7F1EC2B1CF0025BD31 /* YGFlyCommentModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YGFlyCommentModel.m; sourceTree = ""; }; 39 | F9207B801EC2B1D00025BD31 /* CustomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomView.h; sourceTree = ""; }; 40 | F9207B811EC2B1D00025BD31 /* CustomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomView.m; sourceTree = ""; }; 41 | F9207B841EC2B1F70025BD31 /* YGFlyCommentViewAnother.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YGFlyCommentViewAnother.h; sourceTree = ""; }; 42 | F9207B851EC2B1F70025BD31 /* YGFlyCommentViewAnother.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YGFlyCommentViewAnother.m; sourceTree = ""; }; 43 | F975F1C328F9233F00090ADE /* KFFlyCommentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KFFlyCommentView.h; sourceTree = ""; }; 44 | F975F1C428F9233F00090ADE /* KFFlyCommentTrackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KFFlyCommentTrackView.h; sourceTree = ""; }; 45 | F975F1C528F9233F00090ADE /* KFFlyCommentTrackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KFFlyCommentTrackView.m; sourceTree = ""; }; 46 | F975F1C628F9233F00090ADE /* KFFlyCommentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KFFlyCommentView.m; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | F9207B4F1EC2A7790025BD31 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | F9207B491EC2A7790025BD31 = { 61 | isa = PBXGroup; 62 | children = ( 63 | F9207B541EC2A7790025BD31 /* KFFlyCommentViewDemo */, 64 | F9207B531EC2A7790025BD31 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | F9207B531EC2A7790025BD31 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | F9207B521EC2A7790025BD31 /* KFFlyCommentViewDemo.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | F9207B541EC2A7790025BD31 /* KFFlyCommentViewDemo */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | F975F1C228F9233F00090ADE /* KFFlyCommentView */, 80 | F9207B581EC2A7790025BD31 /* AppDelegate.h */, 81 | F9207B591EC2A7790025BD31 /* AppDelegate.m */, 82 | F9207B7E1EC2B1CF0025BD31 /* YGFlyCommentModel.h */, 83 | F9207B7F1EC2B1CF0025BD31 /* YGFlyCommentModel.m */, 84 | F9207B801EC2B1D00025BD31 /* CustomView.h */, 85 | F9207B811EC2B1D00025BD31 /* CustomView.m */, 86 | F9207B841EC2B1F70025BD31 /* YGFlyCommentViewAnother.h */, 87 | F9207B851EC2B1F70025BD31 /* YGFlyCommentViewAnother.m */, 88 | F9207B5B1EC2A7790025BD31 /* ViewController.h */, 89 | F9207B5C1EC2A7790025BD31 /* ViewController.m */, 90 | F9207B7B1EC2AD170025BD31 /* GoViewController.h */, 91 | F9207B7C1EC2AD170025BD31 /* GoViewController.m */, 92 | F9207B5E1EC2A7790025BD31 /* Main.storyboard */, 93 | F9207B611EC2A7790025BD31 /* Assets.xcassets */, 94 | F9207B631EC2A7790025BD31 /* LaunchScreen.storyboard */, 95 | F9207B661EC2A7790025BD31 /* Info.plist */, 96 | F9207B551EC2A7790025BD31 /* Supporting Files */, 97 | ); 98 | path = KFFlyCommentViewDemo; 99 | sourceTree = ""; 100 | }; 101 | F9207B551EC2A7790025BD31 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | F9207B561EC2A7790025BD31 /* main.m */, 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | F975F1C228F9233F00090ADE /* KFFlyCommentView */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | F975F1C328F9233F00090ADE /* KFFlyCommentView.h */, 113 | F975F1C428F9233F00090ADE /* KFFlyCommentTrackView.h */, 114 | F975F1C528F9233F00090ADE /* KFFlyCommentTrackView.m */, 115 | F975F1C628F9233F00090ADE /* KFFlyCommentView.m */, 116 | ); 117 | path = KFFlyCommentView; 118 | sourceTree = ""; 119 | }; 120 | /* End PBXGroup section */ 121 | 122 | /* Begin PBXNativeTarget section */ 123 | F9207B511EC2A7790025BD31 /* KFFlyCommentViewDemo */ = { 124 | isa = PBXNativeTarget; 125 | buildConfigurationList = F9207B691EC2A7790025BD31 /* Build configuration list for PBXNativeTarget "KFFlyCommentViewDemo" */; 126 | buildPhases = ( 127 | F9207B4E1EC2A7790025BD31 /* Sources */, 128 | F9207B4F1EC2A7790025BD31 /* Frameworks */, 129 | F9207B501EC2A7790025BD31 /* Resources */, 130 | ); 131 | buildRules = ( 132 | ); 133 | dependencies = ( 134 | ); 135 | name = KFFlyCommentViewDemo; 136 | productName = KFFlyCommentViewDemo; 137 | productReference = F9207B521EC2A7790025BD31 /* KFFlyCommentViewDemo.app */; 138 | productType = "com.apple.product-type.application"; 139 | }; 140 | /* End PBXNativeTarget section */ 141 | 142 | /* Begin PBXProject section */ 143 | F9207B4A1EC2A7790025BD31 /* Project object */ = { 144 | isa = PBXProject; 145 | attributes = { 146 | LastUpgradeCheck = 1340; 147 | ORGANIZATIONNAME = "张楷枫"; 148 | TargetAttributes = { 149 | F9207B511EC2A7790025BD31 = { 150 | CreatedOnToolsVersion = 8.3.2; 151 | DevelopmentTeam = 7XA9B9NTWF; 152 | ProvisioningStyle = Automatic; 153 | }; 154 | }; 155 | }; 156 | buildConfigurationList = F9207B4D1EC2A7790025BD31 /* Build configuration list for PBXProject "KFFlyCommentViewDemo" */; 157 | compatibilityVersion = "Xcode 3.2"; 158 | developmentRegion = en; 159 | hasScannedForEncodings = 0; 160 | knownRegions = ( 161 | en, 162 | Base, 163 | ); 164 | mainGroup = F9207B491EC2A7790025BD31; 165 | productRefGroup = F9207B531EC2A7790025BD31 /* Products */; 166 | projectDirPath = ""; 167 | projectRoot = ""; 168 | targets = ( 169 | F9207B511EC2A7790025BD31 /* KFFlyCommentViewDemo */, 170 | ); 171 | }; 172 | /* End PBXProject section */ 173 | 174 | /* Begin PBXResourcesBuildPhase section */ 175 | F9207B501EC2A7790025BD31 /* Resources */ = { 176 | isa = PBXResourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | F9207B651EC2A7790025BD31 /* LaunchScreen.storyboard in Resources */, 180 | F9207B621EC2A7790025BD31 /* Assets.xcassets in Resources */, 181 | F9207B601EC2A7790025BD31 /* Main.storyboard in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXSourcesBuildPhase section */ 188 | F9207B4E1EC2A7790025BD31 /* Sources */ = { 189 | isa = PBXSourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | F9207B7D1EC2AD170025BD31 /* GoViewController.m in Sources */, 193 | F975F1C728F9233F00090ADE /* KFFlyCommentTrackView.m in Sources */, 194 | F9207B5D1EC2A7790025BD31 /* ViewController.m in Sources */, 195 | F9207B5A1EC2A7790025BD31 /* AppDelegate.m in Sources */, 196 | F9207B821EC2B1D00025BD31 /* YGFlyCommentModel.m in Sources */, 197 | F9207B861EC2B1F70025BD31 /* YGFlyCommentViewAnother.m in Sources */, 198 | F9207B831EC2B1D00025BD31 /* CustomView.m in Sources */, 199 | F9207B571EC2A7790025BD31 /* main.m in Sources */, 200 | F975F1C828F9233F00090ADE /* KFFlyCommentView.m in Sources */, 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | }; 204 | /* End PBXSourcesBuildPhase section */ 205 | 206 | /* Begin PBXVariantGroup section */ 207 | F9207B5E1EC2A7790025BD31 /* Main.storyboard */ = { 208 | isa = PBXVariantGroup; 209 | children = ( 210 | F9207B5F1EC2A7790025BD31 /* Base */, 211 | ); 212 | name = Main.storyboard; 213 | sourceTree = ""; 214 | }; 215 | F9207B631EC2A7790025BD31 /* LaunchScreen.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | F9207B641EC2A7790025BD31 /* Base */, 219 | ); 220 | name = LaunchScreen.storyboard; 221 | sourceTree = ""; 222 | }; 223 | /* End PBXVariantGroup section */ 224 | 225 | /* Begin XCBuildConfiguration section */ 226 | F9207B671EC2A7790025BD31 /* Debug */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | ALWAYS_SEARCH_USER_PATHS = NO; 230 | CLANG_ANALYZER_NONNULL = YES; 231 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 232 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 233 | CLANG_CXX_LIBRARY = "libc++"; 234 | CLANG_ENABLE_MODULES = YES; 235 | CLANG_ENABLE_OBJC_ARC = YES; 236 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 237 | CLANG_WARN_BOOL_CONVERSION = YES; 238 | CLANG_WARN_COMMA = YES; 239 | CLANG_WARN_CONSTANT_CONVERSION = YES; 240 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 241 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 242 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 243 | CLANG_WARN_EMPTY_BODY = YES; 244 | CLANG_WARN_ENUM_CONVERSION = YES; 245 | CLANG_WARN_INFINITE_RECURSION = YES; 246 | CLANG_WARN_INT_CONVERSION = YES; 247 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 248 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 249 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 251 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 252 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 253 | CLANG_WARN_STRICT_PROTOTYPES = YES; 254 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 255 | CLANG_WARN_UNREACHABLE_CODE = YES; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 258 | COPY_PHASE_STRIP = NO; 259 | DEBUG_INFORMATION_FORMAT = dwarf; 260 | ENABLE_STRICT_OBJC_MSGSEND = YES; 261 | ENABLE_TESTABILITY = YES; 262 | GCC_C_LANGUAGE_STANDARD = gnu99; 263 | GCC_DYNAMIC_NO_PIC = NO; 264 | GCC_NO_COMMON_BLOCKS = YES; 265 | GCC_OPTIMIZATION_LEVEL = 0; 266 | GCC_PREPROCESSOR_DEFINITIONS = ( 267 | "DEBUG=1", 268 | "$(inherited)", 269 | ); 270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 272 | GCC_WARN_UNDECLARED_SELECTOR = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 274 | GCC_WARN_UNUSED_FUNCTION = YES; 275 | GCC_WARN_UNUSED_VARIABLE = YES; 276 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 277 | MTL_ENABLE_DEBUG_INFO = YES; 278 | ONLY_ACTIVE_ARCH = YES; 279 | SDKROOT = iphoneos; 280 | }; 281 | name = Debug; 282 | }; 283 | F9207B681EC2A7790025BD31 /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ALWAYS_SEARCH_USER_PATHS = NO; 287 | CLANG_ANALYZER_NONNULL = YES; 288 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 289 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 290 | CLANG_CXX_LIBRARY = "libc++"; 291 | CLANG_ENABLE_MODULES = YES; 292 | CLANG_ENABLE_OBJC_ARC = YES; 293 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_COMMA = YES; 296 | CLANG_WARN_CONSTANT_CONVERSION = YES; 297 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 298 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 299 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 300 | CLANG_WARN_EMPTY_BODY = YES; 301 | CLANG_WARN_ENUM_CONVERSION = YES; 302 | CLANG_WARN_INFINITE_RECURSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 305 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 306 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 307 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 308 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 309 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 310 | CLANG_WARN_STRICT_PROTOTYPES = YES; 311 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 312 | CLANG_WARN_UNREACHABLE_CODE = YES; 313 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 314 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 315 | COPY_PHASE_STRIP = NO; 316 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 317 | ENABLE_NS_ASSERTIONS = NO; 318 | ENABLE_STRICT_OBJC_MSGSEND = YES; 319 | GCC_C_LANGUAGE_STANDARD = gnu99; 320 | GCC_NO_COMMON_BLOCKS = YES; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 328 | MTL_ENABLE_DEBUG_INFO = NO; 329 | SDKROOT = iphoneos; 330 | VALIDATE_PRODUCT = YES; 331 | }; 332 | name = Release; 333 | }; 334 | F9207B6A1EC2A7790025BD31 /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 338 | DEVELOPMENT_TEAM = 7XA9B9NTWF; 339 | INFOPLIST_FILE = KFFlyCommentViewDemo/Info.plist; 340 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 341 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 342 | PRODUCT_BUNDLE_IDENTIFIER = com.ccyouge.KFFlyCommentViewDemo; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | }; 345 | name = Debug; 346 | }; 347 | F9207B6B1EC2A7790025BD31 /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 351 | DEVELOPMENT_TEAM = 7XA9B9NTWF; 352 | INFOPLIST_FILE = KFFlyCommentViewDemo/Info.plist; 353 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 355 | PRODUCT_BUNDLE_IDENTIFIER = com.ccyouge.KFFlyCommentViewDemo; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | }; 358 | name = Release; 359 | }; 360 | /* End XCBuildConfiguration section */ 361 | 362 | /* Begin XCConfigurationList section */ 363 | F9207B4D1EC2A7790025BD31 /* Build configuration list for PBXProject "KFFlyCommentViewDemo" */ = { 364 | isa = XCConfigurationList; 365 | buildConfigurations = ( 366 | F9207B671EC2A7790025BD31 /* Debug */, 367 | F9207B681EC2A7790025BD31 /* Release */, 368 | ); 369 | defaultConfigurationIsVisible = 0; 370 | defaultConfigurationName = Release; 371 | }; 372 | F9207B691EC2A7790025BD31 /* Build configuration list for PBXNativeTarget "KFFlyCommentViewDemo" */ = { 373 | isa = XCConfigurationList; 374 | buildConfigurations = ( 375 | F9207B6A1EC2A7790025BD31 /* Debug */, 376 | F9207B6B1EC2A7790025BD31 /* Release */, 377 | ); 378 | defaultConfigurationIsVisible = 0; 379 | defaultConfigurationName = Release; 380 | }; 381 | /* End XCConfigurationList section */ 382 | }; 383 | rootObject = F9207B4A1EC2A7790025BD31 /* Project object */; 384 | } 385 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo.xcodeproj/project.xcworkspace/xcshareddata/YGFlyCommentDemo.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "BE3DD776CCB7E538498EFA8307539145B3FEF020", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "A4C24BAE6424A7D6B20FEE7FFCBF1B6DB22BEA16" : 9223372036854775807, 8 | "BE3DD776CCB7E538498EFA8307539145B3FEF020" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "DC4940B7-18F9-4726-BA75-BB72312C3B5A", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "A4C24BAE6424A7D6B20FEE7FFCBF1B6DB22BEA16" : "", 13 | "BE3DD776CCB7E538498EFA8307539145B3FEF020" : "YGFlyCommentDemo\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "YGFlyCommentDemo", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "YGFlyCommentDemo.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zkfpk6\/YGFlyCommnet.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "A4C24BAE6424A7D6B20FEE7FFCBF1B6DB22BEA16" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/zkfpk6\/YGFlyCommentManager-Danmaku.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "BE3DD776CCB7E538498EFA8307539145B3FEF020" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo.xcodeproj/xcshareddata/xcschemes/YGFlyCommentDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "home_login_qq_color.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "home_login_qq_color@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "home_login_qq_color@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color@2x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_qq_color.imageset/home_login_qq_color@3x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "home_login_wechat_color.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "home_login_wechat_color@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "home_login_wechat_color@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color@2x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_wechat_color.imageset/home_login_wechat_color@3x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "home_login_weibo_color.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "home_login_weibo_color@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "home_login_weibo_color@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color@2x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/home_login_weibo_color.imageset/home_login_weibo_color@3x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/icon_120-1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_120-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/icon_120-1.imageset/icon_120-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/icon_120-1.imageset/icon_120-1.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "rank_charm_heart.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "rank_charm_heart@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "rank_charm_heart@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart@2x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkfpk6/KFDanmaku/52bb272ba48db0967298b62eae24fb6c5871827f/KFFlyCommentViewDemo/Assets.xcassets/rank_charm_heart.imageset/rank_charm_heart@3x.png -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 91 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/CustomView.h: -------------------------------------------------------------------------------- 1 | // 2 | // YGFlyCommentView.h 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "YGFlyCommentModel.h" 11 | 12 | /** 13 | 这个类是自定义某一条弹幕的view 14 | */ 15 | @interface CustomView : UIView 16 | 17 | /** 18 | 弹幕的model 19 | */ 20 | @property (nonatomic,strong) YGFlyCommentModel *messageModel; 21 | 22 | /** 23 | 初始化方法 24 | 25 | @param messageModel 消息的model 26 | @return 自己 27 | */ 28 | - (instancetype)initWithMessageModel:(YGFlyCommentModel *)messageModel height:(float)height; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/CustomView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomView.m 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年 . All rights reserved. 7 | // 8 | 9 | #import "CustomView.h" 10 | 11 | @implementation CustomView 12 | 13 | - (instancetype)initWithMessageModel:(YGFlyCommentModel *)messageModel height:(float)height 14 | { 15 | self = [super init]; 16 | if (self) 17 | { 18 | self.frame = CGRectMake(0, 0, 0, height); 19 | _messageModel = messageModel; 20 | [self configUI]; 21 | } 22 | return self; 23 | } 24 | 25 | - (void)configUI 26 | { 27 | self.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5]; 28 | self.layer.cornerRadius = self.frame.size.height/2; 29 | 30 | 31 | //头像 32 | UIImageView *avatarImageView = [[UIImageView alloc]initWithFrame:CGRectMake(3, 3, self.frame.size.height - 6, self.frame.size.height - 6)]; 33 | avatarImageView.layer.cornerRadius = self.frame.size.height - 6/2; 34 | avatarImageView.clipsToBounds = YES; 35 | avatarImageView.image = [UIImage imageNamed:_messageModel.userAvatar]; 36 | [self addSubview:avatarImageView]; 37 | 38 | //名 39 | UILabel *nameLabel = [[UILabel alloc]init]; 40 | nameLabel.font = [UIFont systemFontOfSize:14]; 41 | nameLabel.textColor = [UIColor whiteColor]; 42 | nameLabel.text = _messageModel.userName; 43 | [nameLabel sizeToFit]; 44 | nameLabel.frame = CGRectMake(CGRectGetMaxX(avatarImageView.frame) + 5, 4, nameLabel.frame.size.width, nameLabel.frame.size.height); 45 | [self addSubview:nameLabel]; 46 | 47 | //文字 48 | UILabel *messageLabel = [[UILabel alloc]init]; 49 | messageLabel.font = [UIFont systemFontOfSize:13]; 50 | messageLabel.textColor = [UIColor whiteColor]; 51 | messageLabel.text = _messageModel.msg; 52 | [messageLabel sizeToFit]; 53 | messageLabel.frame = CGRectMake(nameLabel.frame.origin.x, CGRectGetMaxY(avatarImageView.frame) - messageLabel.frame.size.height - nameLabel.frame.origin.y, messageLabel.frame.size.width, messageLabel.frame.size.height); 54 | [self addSubview:messageLabel]; 55 | 56 | float width = messageLabel.frame.size.width > nameLabel.frame.size.width ? messageLabel.frame.size.width:nameLabel.frame.size.width; 57 | 58 | self.frame = CGRectMake(0, 0, nameLabel.frame.origin.x + 10 + width, self.frame.size.height); 59 | 60 | UIButton *testButton = [[UIButton alloc] initWithFrame:self.frame]; 61 | [testButton addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside]; 62 | [self addSubview:testButton]; 63 | } 64 | 65 | - (void)test { 66 | NSLog(@"test"); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/GoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GoViewController.h 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GoViewController : UIViewController 12 | 13 | @property (nonatomic,strong) NSArray *speedArray; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/GoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GoViewController.m 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "GoViewController.h" 10 | #import "KFFlyCommentView.h" 11 | #import "CustomView.h" 12 | #import "YGFlyCommentModel.h" 13 | #import "KFFlyCommentView.h" 14 | #import "YGFlyCommentViewAnother.h" 15 | 16 | @interface GoViewController () 17 | 18 | @property (nonatomic, strong) KFFlyCommentView *commentView; 19 | 20 | @end 21 | 22 | @implementation GoViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view. 27 | 28 | self.commentView = [[KFFlyCommentView alloc] initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 0) trackVerticalMargin:10 trackHeight:100 trackSpeedArray:self.speedArray]; 29 | [self.view addSubview:self.commentView]; 30 | // self.commentView.infinityLoop = YES; 31 | // self.commentView.joinWithLeftEdge = YES; 32 | // self.commentView.dragEnable = YES; 33 | [self.commentView start]; 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | - (IBAction)startButtonClick:(UIButton *)sender 42 | { 43 | sender.selected = !sender.isSelected; 44 | if (sender.isSelected) 45 | { 46 | [self.commentView start]; 47 | } 48 | else 49 | { 50 | [self.commentView pause]; 51 | } 52 | } 53 | 54 | - (IBAction)insertFlyComment:(id)sender 55 | { 56 | NSArray *classArray = @[@"CustomView",@"YGFlyCommentViewAnother"]; 57 | NSArray *nameArray = @[@"mc子龙",@"小明",@"赵四",@"狂小狗",@"葬爱"]; 58 | NSArray *msgArray = @[@"老铁666",@"主播,多少礼物给卡黄啊?",@"文明观球,大家有秩序排队观看,不要着急",@"色青主播,我报警啦",@"就是个萨比,还扮滴酷酷滴"]; 59 | NSArray *avatarArray = @[@"home_login_qq_color",@"home_login_wechat_color",@"home_login_weibo_color",@"icon_120-1",@"rank_charm_heart"]; 60 | int classRandomIndex = arc4random() % 2; 61 | int nameRandomIndex = arc4random() % 5; 62 | int msgRandomIndex = arc4random() % 5; 63 | int avatarRandomIndex = arc4random() % 5; 64 | 65 | YGFlyCommentModel *model = [[YGFlyCommentModel alloc]init]; 66 | model.userName = nameArray[nameRandomIndex]; 67 | model.msg = msgArray[msgRandomIndex]; 68 | model.userAvatar = avatarArray[avatarRandomIndex]; 69 | 70 | 71 | CustomView *customView = [[NSClassFromString(classArray[classRandomIndex]) alloc]initWithMessageModel: model height:40]; 72 | [self.commentView appendFlyCommentWithCustomView:customView toTrackIndex:-1]; 73 | } 74 | 75 | - (void)dealloc 76 | { 77 | [self.commentView destory]; 78 | } 79 | 80 | /* 81 | #pragma mark - Navigation 82 | 83 | // In a storyboard-based application, you will often want to do a little preparation before navigation 84 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 85 | // Get the new view controller using [segue destinationViewController]. 86 | // Pass the selected object to the new view controller. 87 | } 88 | */ 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/KFFlyCommentView/KFFlyCommentTrackView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KFFlyCommentTrackView.h 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | 这个类是弹幕轨道的类 13 | */ 14 | @interface KFFlyCommentTrackView : UIView 15 | 16 | /** 17 | 等待出现到屏幕中的弹幕view数组 18 | */ 19 | @property (nonatomic,strong) NSMutableArray *waitShowArray; 20 | 21 | /** 22 | 正在展示的弹幕view数组 23 | */ 24 | @property (nonatomic,strong) NSMutableArray *showingArray; 25 | 26 | /** 27 | 轨道内容间距 28 | */ 29 | @property (nonatomic, assign) CGFloat trackHorizontalPadding; 30 | 31 | /** 32 | 轨道高 33 | */ 34 | @property (nonatomic, assign) CGFloat trackHeight; 35 | 36 | /** 37 | 无限循环滚 38 | */ 39 | @property (nonatomic, assign) BOOL infinityLoop; 40 | 41 | /** 42 | 从屏幕左侧插入 43 | */ 44 | @property (nonatomic, assign) BOOL joinWithLeftEdge; 45 | 46 | /** 47 | 是否可拖动 48 | */ 49 | @property (nonatomic, assign) BOOL dragEnable; 50 | 51 | /** 52 | 向轨道中插入一条自定义的view 53 | 54 | @param view 自定义的view,高度不可超过轨道的高,否则出问题 55 | */ 56 | - (void)appendFlyCommentWithCustomView:(UIView *)view; 57 | 58 | /** 59 | 当前轨道右侧出屏幕的距离+等待出现到屏幕中的弹幕view的总长度和 60 | @return 等待弹幕+右侧出屏幕弹幕的和 61 | */ 62 | - (float)rightOutScreenWidth; 63 | 64 | /** 65 | 清理轨道,移除所有弹幕 66 | */ 67 | - (void)cleanTrack; 68 | 69 | /** 70 | 根据速度移动轨道中所有弹幕的位置 71 | 72 | @param speed 每0.01秒弹幕向左移动的距离 73 | */ 74 | - (void)moveFlyCommentViewWithSpeed:(float)speed; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/KFFlyCommentView/KFFlyCommentTrackView.m: -------------------------------------------------------------------------------- 1 | // 2 | // KFFlyCommentTrackView.m 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "KFFlyCommentTrackView.h" 10 | 11 | @interface KFFlyCommentTrackView () 12 | 13 | @property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer; 14 | 15 | @end 16 | 17 | @implementation KFFlyCommentTrackView 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame 20 | { 21 | self = [super initWithFrame:frame]; 22 | if (self) { 23 | [self configUI]; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)configUI 29 | { 30 | _showingArray = [[NSMutableArray alloc]init]; 31 | _waitShowArray = [[NSMutableArray alloc]init]; 32 | 33 | 34 | _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)]; 35 | _panGestureRecognizer.enabled = NO; 36 | _panGestureRecognizer.delegate = self; 37 | [self addGestureRecognizer:_panGestureRecognizer]; 38 | } 39 | 40 | - (void)setDragEnable:(BOOL)dragEnable { 41 | _dragEnable = dragEnable; 42 | _panGestureRecognizer.enabled = dragEnable; 43 | } 44 | 45 | - (void)panAction:(UIPanGestureRecognizer *)panGestureRecognizer { 46 | CGPoint translation = [panGestureRecognizer translationInView:self]; 47 | [panGestureRecognizer setTranslation:CGPointZero inView:self]; 48 | [self moveFlyCommentViewWithSpeed:-translation.x]; 49 | } 50 | 51 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 52 | // 是否为平移手势 53 | if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) { 54 | // 获取平移方向 55 | CGPoint translation = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:gestureRecognizer.view]; 56 | // 竖向滑动 不响应,防止冲突 57 | if (translation.y != 0) { 58 | return NO; 59 | } 60 | } 61 | return YES; 62 | } 63 | 64 | - (void)appendFlyCommentWithCustomView:(UIView *)view 65 | { 66 | //先让插入的弹幕的x等于屏幕宽 67 | view.frame = CGRectMake(self.frame.size.width, view.frame.origin.y, view.frame.size.width, view.frame.size.height); 68 | //纵向居中 69 | view.center = CGPointMake(view.center.x, self.trackHeight/2); 70 | if (_showingArray.count) 71 | { 72 | //取出最后一条正在显示的弹幕,也就是最右边的弹幕 73 | UIView *lastView = [_showingArray lastObject]; 74 | 75 | //判断如果最右侧的那条弹幕还没有完全出现在屏幕中 76 | if (CGRectGetMaxX(lastView.frame) + self.trackHorizontalPadding > self.frame.size.width || _waitShowArray.count) 77 | { 78 | //那就只能先把这条弹幕加到等待数组中 79 | [_waitShowArray addObject:view]; 80 | } 81 | //如果最右侧的那条弹幕完全出现在屏幕中 82 | else 83 | { 84 | //从屏幕左边插 紧跟上一条 85 | if (self.joinWithLeftEdge) { 86 | view.frame = CGRectMake(CGRectGetMaxX(lastView.frame) + self.trackHorizontalPadding, view.frame.origin.y, view.frame.size.width, view.frame.size.height); 87 | } 88 | //加到轨道上 89 | [self addSubview:view]; 90 | //加到展示数组中 91 | [_showingArray addObject:view]; 92 | } 93 | } 94 | //如果连正在展示的都没有 95 | else 96 | { 97 | //从屏幕左边插,直接最左侧 98 | //加到轨道上 99 | [self addSubview:view]; 100 | if (self.joinWithLeftEdge) { 101 | view.frame = CGRectMake(0, view.frame.origin.y, view.frame.size.width, view.frame.size.height); 102 | } 103 | //加到展示数组中 104 | [_showingArray addObject:view]; 105 | } 106 | } 107 | 108 | - (void)moveFlyCommentViewWithSpeed:(float)speed 109 | { 110 | if (speed == 0) { 111 | return; 112 | } 113 | BOOL moveToLeft = speed > 0; 114 | //遍历所有正在展示的弹幕,自减一下 115 | for (UIView *view in _showingArray) 116 | { 117 | view.frame = CGRectMake(view.frame.origin.x - speed, view.frame.origin.y, view.frame.size.width, view.frame.size.height); 118 | } 119 | 120 | //如果有正在展示的弹幕 121 | if (_showingArray.count) 122 | { 123 | UIView *firstView = [_showingArray firstObject]; 124 | UIView *lastView = [_showingArray lastObject]; 125 | 126 | //最左侧的弹幕如果完全运行到了屏幕外 127 | if ((CGRectGetMaxX(firstView.frame) < 0) && moveToLeft) 128 | { 129 | //remove掉节省内存 130 | [firstView removeFromSuperview]; 131 | [_showingArray removeObjectAtIndex:0]; 132 | //无限循环滚的话 再次加入到等待数组 133 | if (self.infinityLoop) { 134 | [self.waitShowArray addObject:firstView]; 135 | } 136 | } 137 | // 往右拖,最右侧view消失,x比屏幕宽大 138 | if (lastView.frame.origin.x > UIScreen.mainScreen.bounds.size.width && !moveToLeft) { 139 | //remove掉节省内存 140 | [lastView removeFromSuperview]; 141 | [_showingArray removeLastObject]; 142 | //无限循环滚的话 再次加入到等待数组 143 | if (self.infinityLoop) { 144 | [self.waitShowArray insertObject:lastView atIndex:0]; 145 | } 146 | } 147 | //如果等待数组中有值 148 | if (_waitShowArray.count) 149 | { 150 | //如果最右侧的view已经完全出现在屏幕中了,或者没有正在显示中的弹幕 151 | if (((CGRectGetMaxX(lastView.frame) + self.trackHorizontalPadding <= self.frame.size.width) || self.showingArray.count == 0) && moveToLeft) 152 | { 153 | //从等待数组中拿出来加入到展示数组 154 | [_showingArray addObject:[_waitShowArray firstObject]]; 155 | [_waitShowArray removeObjectAtIndex:0]; 156 | UIView *currentView = [_showingArray lastObject]; 157 | //加到屏幕中 158 | [self addSubview:currentView]; 159 | //重置x坐标 160 | CGRect frame = currentView.frame; 161 | frame.origin.x = CGRectGetMaxX(lastView.frame) + self.trackHorizontalPadding; 162 | currentView.frame = frame; 163 | } 164 | 165 | //如果最左侧的view已经完全出现在屏幕中了,或者没有正在显示中的弹幕 166 | if (((firstView.frame.origin.x > self.trackHorizontalPadding) || self.showingArray.count == 0) && !moveToLeft) 167 | { 168 | //从等待数组中拿出来加入到展示数组 169 | [_showingArray insertObject:_waitShowArray.lastObject atIndex:0]; 170 | [_waitShowArray removeLastObject]; 171 | UIView *currentView = [_showingArray firstObject]; 172 | //加到屏幕中 173 | [self addSubview:currentView]; 174 | //重置x坐标 175 | CGRect frame = currentView.frame; 176 | frame.origin.x = firstView.frame.origin.x - currentView.frame.size.width - self.trackHorizontalPadding; 177 | currentView.frame = frame; 178 | } 179 | } 180 | } 181 | } 182 | 183 | /** 184 | 这个方法可以拿出所有右侧尚未出现的弹幕和出现在最右侧的那一条弹幕的长度和 185 | 186 | @return 长度和 187 | */ 188 | - (float)rightOutScreenWidth 189 | { 190 | float outScreenWidth = 0.0; 191 | //如果等待数组中有值 192 | if (_waitShowArray.count) 193 | { 194 | //先遍历所有等待数组中的view,累加长度和间距 195 | for (UIView *view in _waitShowArray) 196 | { 197 | outScreenWidth += view.frame.size.width + self.trackHorizontalPadding; 198 | } 199 | } 200 | 201 | //如果展示数组中有值 202 | if (_showingArray.count) 203 | { 204 | //拿出最右侧的view 205 | UIView *lastView = [_showingArray lastObject]; 206 | //算出出屏宽 207 | float rightOutWidth = CGRectGetMaxX(lastView.frame) - self.frame.size.width; 208 | if (rightOutWidth < 0) 209 | { 210 | rightOutWidth = 0; 211 | } 212 | outScreenWidth += rightOutWidth; 213 | } 214 | 215 | return outScreenWidth; 216 | } 217 | 218 | //清理轨道 219 | - (void)cleanTrack 220 | { 221 | for (UIView *view in _showingArray) 222 | { 223 | [view removeFromSuperview]; 224 | } 225 | [_showingArray removeAllObjects]; 226 | [_waitShowArray removeAllObjects]; 227 | 228 | } 229 | 230 | @end 231 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/KFFlyCommentView/KFFlyCommentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KFFlyCommentView.h 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KFFlyCommentTrackView.h" 11 | 12 | #define COMMENT_VIEW_CONFIG_FPS 60 13 | 14 | @interface KFFlyCommentView : UIView 15 | 16 | 17 | /** 18 | 创建轨道 19 | 20 | @param frame frame 21 | @param trackHeight 轨道高度 22 | @param trackSpeedArray 轨道速度数组 23 | */ 24 | - (instancetype)initWithFrame:(CGRect)frame 25 | trackVerticalMargin:(CGFloat)trackVerticalMargin 26 | trackHeight:(CGFloat)trackHeight 27 | trackSpeedArray:(NSArray *)trackSpeedArray; 28 | 29 | /** 30 | 插入一条弹幕,可以插入任意继承UIView的对象 31 | 32 | @param customView 自定义的view(注意,最高不能超过轨道的高,否则会出问题。轨道的高度请在FlyCommentViewConfig.h中配置) 33 | @param trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入) 34 | */ 35 | - (void)appendFlyCommentWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex; 36 | 37 | /** 38 | 开始播放弹幕 39 | */ 40 | - (void)start; 41 | 42 | /** 43 | 暂停播放弹幕 44 | */ 45 | - (void)pause; 46 | 47 | /** 48 | 停止播放弹幕(会清空所有弹幕) 49 | */ 50 | - (void)stop; 51 | 52 | /** 53 | 销毁(不用一定要销毁,防止NSTimer内存泄露) 54 | */ 55 | - (void)destory; 56 | 57 | /** 58 | 是否无限滚动 default:NO 59 | */ 60 | @property (nonatomic, assign) BOOL infinityLoop; 61 | 62 | /** 63 | 是否从左侧开始 default:NO 64 | */ 65 | @property (nonatomic, assign) BOOL joinWithLeftEdge; 66 | 67 | /** 68 | 是否可拖动 default:NO 69 | */ 70 | @property (nonatomic, assign) BOOL dragEnable; 71 | 72 | /** 73 | 轨道中内容最小间距 default:10 74 | */ 75 | @property (nonatomic, assign) CGFloat trackHorizontalPadding; 76 | 77 | /** 78 | 轨道数组 79 | */ 80 | @property (nonatomic, strong, readonly) NSMutableArray *trackArray; 81 | 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/KFFlyCommentView/KFFlyCommentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // KFFlyCommentView.m 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/8. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "KFFlyCommentView.h" 10 | 11 | @interface KFFlyCommentView () 12 | 13 | @property (nonatomic, strong) NSArray *trackSpeedArray; 14 | @property (nonatomic, strong) NSTimer *timer; 15 | @property (nonatomic, assign) CGFloat trackVerticalMargin; 16 | @property (nonatomic, assign) CGFloat trackHeight; 17 | 18 | @end 19 | 20 | @implementation KFFlyCommentView 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame 23 | trackVerticalMargin:(CGFloat)trackVerticalMargin 24 | trackHeight:(CGFloat)trackHeight 25 | trackSpeedArray:(NSArray *)trackSpeedArray { 26 | self = [super initWithFrame:frame]; 27 | if (self) { 28 | _trackSpeedArray = trackSpeedArray; 29 | _trackVerticalMargin = trackVerticalMargin; 30 | _trackHeight = trackHeight; 31 | _trackArray = [[NSMutableArray alloc] init]; 32 | [self configUI]; 33 | [self initDefaultValue]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void)configUI { 39 | for (int i = 0; i<_trackSpeedArray.count; i++) { 40 | //把轨道按照间距加到baseview上,再加到数组中 41 | KFFlyCommentTrackView *trackView = [[KFFlyCommentTrackView alloc]initWithFrame:CGRectMake(0, (self.trackHeight + self.trackVerticalMargin) * i, self.frame.size.width, self.trackHeight)]; 42 | trackView.trackHeight = self.trackHeight; 43 | trackView.trackHorizontalPadding = self.trackHorizontalPadding; 44 | trackView.infinityLoop = self.infinityLoop; 45 | [self addSubview:trackView]; 46 | [_trackArray addObject:trackView]; 47 | if (_trackSpeedArray.count - 1 == i) { 48 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, CGRectGetMaxY(trackView.frame)); 49 | } 50 | } 51 | } 52 | 53 | - (void)initDefaultValue { 54 | self.trackHorizontalPadding = 10; 55 | self.infinityLoop = NO; 56 | self.dragEnable = NO; 57 | self.joinWithLeftEdge = NO; 58 | } 59 | 60 | - (void)start { 61 | if (_timer) { 62 | return; 63 | } 64 | //开始其实就是开始定时器 65 | _timer = [NSTimer timerWithTimeInterval:1.0 / COMMENT_VIEW_CONFIG_FPS target:self selector:@selector(startAction) userInfo:nil repeats:YES]; 66 | //加到runloop,防止scrollview影响 67 | [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; 68 | } 69 | 70 | - (void)pause 71 | { 72 | //暂停其实就是销毁计时器 73 | [_timer invalidate]; 74 | _timer = nil; 75 | } 76 | 77 | - (void)stop 78 | { 79 | //停止就是销毁计时器 80 | [_timer invalidate]; 81 | _timer = nil; 82 | //然后移除所有轨道的弹幕 83 | for (KFFlyCommentTrackView *trackView in _trackArray) 84 | { 85 | [trackView cleanTrack]; 86 | } 87 | } 88 | 89 | - (void)destory 90 | { 91 | [_timer invalidate]; 92 | _timer = nil; 93 | for (KFFlyCommentTrackView *trackView in _trackArray) 94 | { 95 | [trackView cleanTrack]; 96 | [trackView removeFromSuperview]; 97 | } 98 | [_trackArray removeAllObjects]; 99 | _trackSpeedArray = nil; 100 | _trackArray = nil; 101 | } 102 | 103 | /** 104 | Timer方法 105 | */ 106 | - (void)startAction 107 | { 108 | for (int i = 0; i<_trackArray.count; i++) 109 | { 110 | //其实就是遍历所有轨道执行轨道定时器的方法 111 | KFFlyCommentTrackView *trackView = _trackArray[i]; 112 | [trackView moveFlyCommentViewWithSpeed:[_trackSpeedArray[i] floatValue]]; 113 | } 114 | } 115 | 116 | /** 117 | 插入一条弹幕,可以插入任意继承UIView的对象 118 | 119 | @param customView 自定义的view(注意,最高不能超过轨道的高,否则会出问题。轨道的高度请在FlyCommentViewConfig.h中配置) 120 | @param trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入) 121 | */ 122 | - (void)appendFlyCommentWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex 123 | { 124 | NSInteger realTrackIndex = trackIndex; 125 | if (realTrackIndex == -1) 126 | { 127 | //找到最不拥挤的轨道序号 128 | realTrackIndex = [self findTheMinTotalWidthTrack]; 129 | } 130 | 131 | KFFlyCommentTrackView *trackView = _trackArray[realTrackIndex]; 132 | [trackView appendFlyCommentWithCustomView:customView]; 133 | } 134 | 135 | /** 136 | 找到最短右侧出屏幕和等待数组总长度最短的轨道序号 137 | 138 | @return 轨道的序号 139 | */ 140 | - (int)findTheMinTotalWidthTrack 141 | { 142 | KFFlyCommentTrackView *firstTrackView = _trackArray[0]; 143 | int minWidthIndex = 0; 144 | float minWidth = [firstTrackView rightOutScreenWidth]; 145 | for (int i = 0; i<_trackArray.count; i++) 146 | { 147 | KFFlyCommentTrackView *trackView = _trackArray[i]; 148 | float trackRightOutScreenWidth = [trackView rightOutScreenWidth]; 149 | if (trackRightOutScreenWidth < minWidth) 150 | { 151 | minWidth = trackRightOutScreenWidth; 152 | minWidthIndex = i; 153 | } 154 | 155 | } 156 | return minWidthIndex; 157 | } 158 | 159 | - (void)setInfinityLoop:(BOOL)infinityLoop { 160 | _infinityLoop = infinityLoop; 161 | for (KFFlyCommentTrackView *trackView in self.trackArray) { 162 | trackView.infinityLoop = infinityLoop; 163 | } 164 | } 165 | 166 | - (void)setTrackHorizontalPadding:(CGFloat)trackHorizontalPadding { 167 | _trackHorizontalPadding = trackHorizontalPadding; 168 | for (KFFlyCommentTrackView *trackView in self.trackArray) { 169 | trackView.trackHorizontalPadding = trackHorizontalPadding; 170 | } 171 | } 172 | 173 | - (void)setJoinWithLeftEdge:(BOOL)joinWithLeftEdge { 174 | _joinWithLeftEdge = joinWithLeftEdge; 175 | for (KFFlyCommentTrackView *trackView in self.trackArray) { 176 | trackView.joinWithLeftEdge = joinWithLeftEdge; 177 | } 178 | } 179 | 180 | - (void)setDragEnable:(BOOL)dragEnable { 181 | for (KFFlyCommentTrackView *trackView in self.trackArray) { 182 | trackView.dragEnable = dragEnable; 183 | } 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "GoViewController.h" 11 | 12 | @interface ViewController () 13 | @property (weak, nonatomic) IBOutlet UITextView *textView; 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view, typically from a nib. 22 | } 23 | 24 | 25 | - (void)didReceiveMemoryWarning { 26 | [super didReceiveMemoryWarning]; 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | - (IBAction)goButtonClick:(id)sender 31 | { 32 | NSArray *speedArray = [_textView.text componentsSeparatedByString:@","]; 33 | NSMutableArray *trackSpeedArray = [[NSMutableArray alloc]init]; 34 | for (NSString *speedString in speedArray) 35 | { 36 | [trackSpeedArray addObject:[NSNumber numberWithFloat:speedString.floatValue]]; 37 | } 38 | 39 | 40 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 41 | 42 | GoViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"IdReceive"]; 43 | controller.speedArray = trackSpeedArray; 44 | [self presentViewController:controller animated:YES completion:nil]; 45 | 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/YGFlyCommentModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // YGFlyCommentModel.h 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/9. 6 | // Copyright © 2017年 . All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface YGFlyCommentModel : NSObject 12 | 13 | @property (nonatomic,strong) NSString *userName; 14 | @property (nonatomic,strong) NSString *userLevel; 15 | @property (nonatomic,strong) NSString *msg; 16 | @property (nonatomic,strong) NSString *userAvatar; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/YGFlyCommentModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // YGFlyCommentModel.m 3 | // ParadiseWordLive 4 | // 5 | // Created by zhangkaifeng on 2017/5/9. 6 | // Copyright © 2017年 . All rights reserved. 7 | // 8 | 9 | #import "YGFlyCommentModel.h" 10 | 11 | @implementation YGFlyCommentModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/YGFlyCommentViewAnother.h: -------------------------------------------------------------------------------- 1 | // 2 | // YGFlyCommentViewAnother.h 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "YGFlyCommentModel.h" 11 | 12 | /** 13 | 这个类是自定义某一条弹幕的view 14 | */ 15 | @interface YGFlyCommentViewAnother : UIView 16 | 17 | /** 18 | 弹幕的model 19 | */ 20 | @property (nonatomic,strong) YGFlyCommentModel *messageModel; 21 | 22 | /** 23 | 初始化方法 24 | 25 | @param messageModel 消息的model 26 | @return 自己 27 | */ 28 | - (instancetype)initWithMessageModel:(YGFlyCommentModel *)messageModel height:(float)height; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/YGFlyCommentViewAnother.m: -------------------------------------------------------------------------------- 1 | // 2 | // YGFlyCommentViewAnother.m 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import "YGFlyCommentViewAnother.h" 10 | 11 | @implementation YGFlyCommentViewAnother 12 | 13 | - (instancetype)initWithMessageModel:(YGFlyCommentModel *)messageModel height:(float)height 14 | { 15 | self = [super init]; 16 | if (self) 17 | { 18 | self.frame = CGRectMake(0, 0, 0, 25); 19 | _messageModel = messageModel; 20 | [self configUI]; 21 | } 22 | return self; 23 | } 24 | 25 | - (void)configUI 26 | { 27 | self.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5]; 28 | self.layer.cornerRadius = 5; 29 | 30 | 31 | //头像 32 | UIImageView *avatarImageView = [[UIImageView alloc]initWithFrame:CGRectMake(3, 3, self.frame.size.height - 6, self.frame.size.height - 6)]; 33 | avatarImageView.layer.cornerRadius = self.frame.size.height - 6/2; 34 | avatarImageView.clipsToBounds = YES; 35 | avatarImageView.image = [UIImage imageNamed:_messageModel.userAvatar]; 36 | [self addSubview:avatarImageView]; 37 | 38 | //名 39 | UILabel *nameLabel = [[UILabel alloc]init]; 40 | nameLabel.font = [UIFont systemFontOfSize:14]; 41 | nameLabel.textColor = [UIColor whiteColor]; 42 | nameLabel.text = [NSString stringWithFormat:@"%@:%@",_messageModel.userName,_messageModel.msg]; 43 | [nameLabel sizeToFit]; 44 | nameLabel.frame = CGRectMake(CGRectGetMaxX(avatarImageView.frame) + 5, 4, nameLabel.frame.size.width, nameLabel.frame.size.height); 45 | nameLabel.center = CGPointMake(nameLabel.center.x, avatarImageView.center.y); 46 | [self addSubview:nameLabel]; 47 | 48 | 49 | self.frame = CGRectMake(0, 0, CGRectGetMaxX(nameLabel.frame) + 10, self.frame.size.height); 50 | UIButton *testButton = [[UIButton alloc] initWithFrame:self.frame]; 51 | [testButton addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside]; 52 | [self addSubview:testButton]; 53 | 54 | } 55 | 56 | - (void)test { 57 | NSLog(@"test"); 58 | } 59 | 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /KFFlyCommentViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // YGFlyCommentDemo 4 | // 5 | // Created by zhangkaifeng on 2017/5/10. 6 | // Copyright © 2017年 张楷枫. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YGFlyCommentManager-Danmaku 2 | 3 | 一个可以随意自定义view的弹幕类/A danmaku class that can customize view as your pleases 4 | 5 | ## 效果 6 | 7 | [点击查看效果图](https://s3.ax1x.com/2020/12/07/Dvq8ET.gif) 8 | 9 | ## 特性 10 | - [x] 支持完全自定义弹幕 11 | - [x] 支持弹幕的回收 12 | - [x] 支持弹幕速度调整 13 | - [x] 支持自定义弹幕轨道数量 14 | - [x] 支持自定义弹幕间距 15 | - [x] 支持自定义弹幕轨道间距 16 | - [x] 支持不同弹幕样式使用相同/不同轨道 17 | - [x] 支持自动寻找最不拥挤的弹幕轨道 18 | 19 | ## 用法 20 | 21 | ##### Demo 22 | 23 | `YourClass` 24 | 25 | ```objc 26 | /** 27 | 创建轨道 28 | 29 | @param frame frame 30 | @param trackHeight 轨道高度 31 | @param trackSpeedArray 轨道速度数组 32 | */ 33 | // 弹幕 34 | // 1秒前进ptPerSecond 1fps前进ptPerSecond/COMMENT_VIEW_CONFIG_FPS 35 | CGFloat ptPerSecond = 20.0; 36 | KFFlyCommentView *commentView = [[KFFlyCommentView alloc] initWithFrame:CGRectMake(0, 0, self.width, 0) 37 | trackVerticalMargin:0 38 | trackHeight:30 + 12 39 | trackSpeedArray:@[@(ptPerSecond/COMMENT_VIEW_CONFIG_FPS), @(ptPerSecond/COMMENT_VIEW_CONFIG_FPS)]]; 40 | commentView.infinityLoop = YES; 41 | commentView.joinWithLeftEdge = YES; 42 | commentView.dragEnable = YES; 43 | commentView.trackHorizontalPadding = 12; 44 | commentView.y = self.backgroundImageView.maxY - commentView.height - 10; 45 | [self addSubview:commentView]; 46 | 47 | /** 48 | 插入一条弹幕,可以插入任意继承UIView的对象 49 | 50 | @param customView 自定义的继承于view(注意,最高不能超过轨道的高,否则会出问题) 51 | @param trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入) 52 | */ 53 | [commentView appendFlyCommentWithCustomView:customView toTrackIndex:-1]; 54 | ``` 55 | ##### 创建弹幕 56 | ```objc 57 | - (instancetype)initWithFrame:(CGRect)frame 58 | trackVerticalMargin:(CGFloat)trackVerticalMargin 59 | trackHeight:(CGFloat)trackHeight 60 | trackSpeedArray:(NSArray *)trackSpeedArray; 61 | ``` 62 | 63 | ##### 插入一条弹幕 64 | ```objc 65 | - (void)appendFlyCommentWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex; 66 | ``` 67 | 68 | ##### 停止播放弹幕(会清空所有弹幕) 69 | ```objc 70 | - (void)stop; 71 | ``` 72 | 73 | ## 联系我 74 | - 邮箱: 651146554@qq.com 75 | - QQ:651146554 76 | --------------------------------------------------------------------------------