├── HXTagsView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── Love.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── huangxuan518.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── lzg.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── Love.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── HXTagsView.xcscheme │ │ └── xcschememanagement.plist │ ├── huangxuan518.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── HXTagsView.xcscheme │ │ └── xcschememanagement.plist │ └── lzg.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── HXTagsView.xcscheme │ └── xcschememanagement.plist ├── HXTagsView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── LaunchImage.launchimage │ │ ├── Contents.json │ │ ├── Default-667h@2x.png │ │ └── default-568h@2x.png ├── HXTagTableViewController.h ├── HXTagTableViewController.m ├── HXViewController.h ├── HXViewController.m ├── Info.plist ├── canshu.png ├── danhangbugundongxiaoguo.gif ├── danhanggundongxiaoguo.gif ├── duohanggundongxiaoguo.gif ├── duohangpingpudan1xiaoguo.gif ├── duohangpingpudanxiaoguo.gif ├── duohangpingpuxiaoguo.gif ├── main.m ├── xiaoguo.gif └── 标签 │ ├── HXTagAttribute.h │ ├── HXTagAttribute.m │ ├── HXTagCollectionViewCell.h │ ├── HXTagCollectionViewCell.m │ ├── HXTagCollectionViewFlowLayout.h │ ├── HXTagCollectionViewFlowLayout.m │ ├── HXTagsCell.h │ ├── HXTagsCell.m │ ├── HXTagsView.h │ └── HXTagsView.m └── README.md /HXTagsView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 30093C831C48DFF900B7EEED /* xiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30093C821C48DFF900B7EEED /* xiaoguo.gif */; }; 11 | 301FDD531C52262F00E5578B /* canshu.png in Resources */ = {isa = PBXBuildFile; fileRef = 301FDD521C52262F00E5578B /* canshu.png */; }; 12 | 30D2F7231CC76D7D007D766B /* danhanggundongxiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F71D1CC76D7D007D766B /* danhanggundongxiaoguo.gif */; }; 13 | 30D2F7241CC76D7D007D766B /* danhangbugundongxiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F71E1CC76D7D007D766B /* danhangbugundongxiaoguo.gif */; }; 14 | 30D2F7251CC76D7D007D766B /* duohangpingpudan1xiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F71F1CC76D7D007D766B /* duohangpingpudan1xiaoguo.gif */; }; 15 | 30D2F7261CC76D7D007D766B /* duohangpingpudanxiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F7201CC76D7D007D766B /* duohangpingpudanxiaoguo.gif */; }; 16 | 30D2F7271CC76D7D007D766B /* duohanggundongxiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F7211CC76D7D007D766B /* duohanggundongxiaoguo.gif */; }; 17 | 30D2F7281CC76D7D007D766B /* duohangpingpuxiaoguo.gif in Resources */ = {isa = PBXBuildFile; fileRef = 30D2F7221CC76D7D007D766B /* duohangpingpuxiaoguo.gif */; }; 18 | 30E706201C476F5200F12FD1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E7061F1C476F5200F12FD1 /* main.m */; }; 19 | 30E706231C476F5200F12FD1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E706221C476F5200F12FD1 /* AppDelegate.m */; }; 20 | 30E706261C476F5200F12FD1 /* HXViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E706251C476F5200F12FD1 /* HXViewController.m */; }; 21 | 30E7062B1C476F5200F12FD1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 30E7062A1C476F5200F12FD1 /* Assets.xcassets */; }; 22 | 9CA9CF901D24AB30007F3E91 /* HXTagsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CA9CF8F1D24AB30007F3E91 /* HXTagsCell.m */; }; 23 | 9CA9CF931D24AB64007F3E91 /* HXTagAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CA9CF921D24AB64007F3E91 /* HXTagAttribute.m */; }; 24 | 9CB522301D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CB5222B1D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.m */; }; 25 | 9CB522311D211D9D0047DD2B /* HXTagCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CB5222D1D211D9D0047DD2B /* HXTagCollectionViewCell.m */; }; 26 | 9CB522321D211D9D0047DD2B /* HXTagsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CB5222F1D211D9D0047DD2B /* HXTagsView.m */; }; 27 | E4968DCD1D3CDDA400102A3E /* HXTagTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E4968DCC1D3CDDA400102A3E /* HXTagTableViewController.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 30093C821C48DFF900B7EEED /* xiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = xiaoguo.gif; sourceTree = ""; }; 32 | 301FDD521C52262F00E5578B /* canshu.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = canshu.png; sourceTree = ""; }; 33 | 30D2F71D1CC76D7D007D766B /* danhanggundongxiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = danhanggundongxiaoguo.gif; sourceTree = ""; }; 34 | 30D2F71E1CC76D7D007D766B /* danhangbugundongxiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = danhangbugundongxiaoguo.gif; sourceTree = ""; }; 35 | 30D2F71F1CC76D7D007D766B /* duohangpingpudan1xiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = duohangpingpudan1xiaoguo.gif; sourceTree = ""; }; 36 | 30D2F7201CC76D7D007D766B /* duohangpingpudanxiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = duohangpingpudanxiaoguo.gif; sourceTree = ""; }; 37 | 30D2F7211CC76D7D007D766B /* duohanggundongxiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = duohanggundongxiaoguo.gif; sourceTree = ""; }; 38 | 30D2F7221CC76D7D007D766B /* duohangpingpuxiaoguo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = duohangpingpuxiaoguo.gif; sourceTree = ""; }; 39 | 30E7061B1C476F5100F12FD1 /* HXTagsView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HXTagsView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 30E7061F1C476F5200F12FD1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | 30E706211C476F5200F12FD1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 42 | 30E706221C476F5200F12FD1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 43 | 30E706241C476F5200F12FD1 /* HXViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HXViewController.h; sourceTree = ""; }; 44 | 30E706251C476F5200F12FD1 /* HXViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HXViewController.m; sourceTree = ""; }; 45 | 30E7062A1C476F5200F12FD1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 30E7062F1C476F5200F12FD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 9CA8EDBD1D23DDD700A711A2 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 48 | 9CA9CF8E1D24AB30007F3E91 /* HXTagsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagsCell.h; sourceTree = ""; }; 49 | 9CA9CF8F1D24AB30007F3E91 /* HXTagsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagsCell.m; sourceTree = ""; }; 50 | 9CA9CF911D24AB64007F3E91 /* HXTagAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagAttribute.h; sourceTree = ""; }; 51 | 9CA9CF921D24AB64007F3E91 /* HXTagAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagAttribute.m; sourceTree = ""; }; 52 | 9CB5222A1D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagCollectionViewFlowLayout.h; sourceTree = ""; }; 53 | 9CB5222B1D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagCollectionViewFlowLayout.m; sourceTree = ""; }; 54 | 9CB5222C1D211D9D0047DD2B /* HXTagCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagCollectionViewCell.h; sourceTree = ""; }; 55 | 9CB5222D1D211D9D0047DD2B /* HXTagCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagCollectionViewCell.m; sourceTree = ""; }; 56 | 9CB5222E1D211D9D0047DD2B /* HXTagsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagsView.h; sourceTree = ""; }; 57 | 9CB5222F1D211D9D0047DD2B /* HXTagsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagsView.m; sourceTree = ""; }; 58 | E4968DCB1D3CDDA400102A3E /* HXTagTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HXTagTableViewController.h; sourceTree = ""; }; 59 | E4968DCC1D3CDDA400102A3E /* HXTagTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HXTagTableViewController.m; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 30E706181C476F5100F12FD1 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 30D2F71C1CC76D6C007D766B /* 效果图 */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 30D2F71D1CC76D7D007D766B /* danhanggundongxiaoguo.gif */, 77 | 30D2F71E1CC76D7D007D766B /* danhangbugundongxiaoguo.gif */, 78 | 30D2F71F1CC76D7D007D766B /* duohangpingpudan1xiaoguo.gif */, 79 | 30D2F7201CC76D7D007D766B /* duohangpingpudanxiaoguo.gif */, 80 | 30D2F7211CC76D7D007D766B /* duohanggundongxiaoguo.gif */, 81 | 30D2F7221CC76D7D007D766B /* duohangpingpuxiaoguo.gif */, 82 | 301FDD521C52262F00E5578B /* canshu.png */, 83 | 30093C821C48DFF900B7EEED /* xiaoguo.gif */, 84 | ); 85 | name = "效果图"; 86 | sourceTree = ""; 87 | }; 88 | 30E706121C476F5100F12FD1 = { 89 | isa = PBXGroup; 90 | children = ( 91 | 30E7061D1C476F5200F12FD1 /* HXTagsView */, 92 | 30E7061C1C476F5100F12FD1 /* Products */, 93 | ); 94 | sourceTree = ""; 95 | }; 96 | 30E7061C1C476F5100F12FD1 /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 30E7061B1C476F5100F12FD1 /* HXTagsView.app */, 100 | ); 101 | name = Products; 102 | sourceTree = ""; 103 | }; 104 | 30E7061D1C476F5200F12FD1 /* HXTagsView */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 9CA8EDBD1D23DDD700A711A2 /* README.md */, 108 | 30D2F71C1CC76D6C007D766B /* 效果图 */, 109 | 30E706351C47750F00F12FD1 /* 标签 */, 110 | 30E706211C476F5200F12FD1 /* AppDelegate.h */, 111 | 30E706221C476F5200F12FD1 /* AppDelegate.m */, 112 | 30E706241C476F5200F12FD1 /* HXViewController.h */, 113 | 30E706251C476F5200F12FD1 /* HXViewController.m */, 114 | E4968DCB1D3CDDA400102A3E /* HXTagTableViewController.h */, 115 | E4968DCC1D3CDDA400102A3E /* HXTagTableViewController.m */, 116 | 30E7062A1C476F5200F12FD1 /* Assets.xcassets */, 117 | 30E7062F1C476F5200F12FD1 /* Info.plist */, 118 | 30E7061E1C476F5200F12FD1 /* Supporting Files */, 119 | ); 120 | path = HXTagsView; 121 | sourceTree = ""; 122 | }; 123 | 30E7061E1C476F5200F12FD1 /* Supporting Files */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 30E7061F1C476F5200F12FD1 /* main.m */, 127 | ); 128 | name = "Supporting Files"; 129 | sourceTree = ""; 130 | }; 131 | 30E706351C47750F00F12FD1 /* 标签 */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 9CB5222A1D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.h */, 135 | 9CB5222B1D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.m */, 136 | 9CB5222C1D211D9D0047DD2B /* HXTagCollectionViewCell.h */, 137 | 9CB5222D1D211D9D0047DD2B /* HXTagCollectionViewCell.m */, 138 | 9CA9CF911D24AB64007F3E91 /* HXTagAttribute.h */, 139 | 9CA9CF921D24AB64007F3E91 /* HXTagAttribute.m */, 140 | 9CB5222E1D211D9D0047DD2B /* HXTagsView.h */, 141 | 9CB5222F1D211D9D0047DD2B /* HXTagsView.m */, 142 | 9CA9CF8E1D24AB30007F3E91 /* HXTagsCell.h */, 143 | 9CA9CF8F1D24AB30007F3E91 /* HXTagsCell.m */, 144 | ); 145 | path = "标签"; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | 30E7061A1C476F5100F12FD1 /* HXTagsView */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = 30E706321C476F5200F12FD1 /* Build configuration list for PBXNativeTarget "HXTagsView" */; 154 | buildPhases = ( 155 | 30E706171C476F5100F12FD1 /* Sources */, 156 | 30E706181C476F5100F12FD1 /* Frameworks */, 157 | 30E706191C476F5100F12FD1 /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = HXTagsView; 164 | productName = HXTagsView; 165 | productReference = 30E7061B1C476F5100F12FD1 /* HXTagsView.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | /* End PBXNativeTarget section */ 169 | 170 | /* Begin PBXProject section */ 171 | 30E706131C476F5100F12FD1 /* Project object */ = { 172 | isa = PBXProject; 173 | attributes = { 174 | LastUpgradeCheck = 0720; 175 | ORGANIZATIONNAME = "IT小子"; 176 | TargetAttributes = { 177 | 30E7061A1C476F5100F12FD1 = { 178 | CreatedOnToolsVersion = 7.2; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 30E706161C476F5100F12FD1 /* Build configuration list for PBXProject "HXTagsView" */; 183 | compatibilityVersion = "Xcode 3.2"; 184 | developmentRegion = English; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | Base, 189 | ); 190 | mainGroup = 30E706121C476F5100F12FD1; 191 | productRefGroup = 30E7061C1C476F5100F12FD1 /* Products */; 192 | projectDirPath = ""; 193 | projectRoot = ""; 194 | targets = ( 195 | 30E7061A1C476F5100F12FD1 /* HXTagsView */, 196 | ); 197 | }; 198 | /* End PBXProject section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | 30E706191C476F5100F12FD1 /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 30D2F7261CC76D7D007D766B /* duohangpingpudanxiaoguo.gif in Resources */, 206 | 30D2F7271CC76D7D007D766B /* duohanggundongxiaoguo.gif in Resources */, 207 | 30D2F7281CC76D7D007D766B /* duohangpingpuxiaoguo.gif in Resources */, 208 | 30D2F7231CC76D7D007D766B /* danhanggundongxiaoguo.gif in Resources */, 209 | 301FDD531C52262F00E5578B /* canshu.png in Resources */, 210 | 30E7062B1C476F5200F12FD1 /* Assets.xcassets in Resources */, 211 | 30093C831C48DFF900B7EEED /* xiaoguo.gif in Resources */, 212 | 30D2F7241CC76D7D007D766B /* danhangbugundongxiaoguo.gif in Resources */, 213 | 30D2F7251CC76D7D007D766B /* duohangpingpudan1xiaoguo.gif in Resources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXResourcesBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 30E706171C476F5100F12FD1 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 9CB522301D211D9D0047DD2B /* HXTagCollectionViewFlowLayout.m in Sources */, 225 | 30E706261C476F5200F12FD1 /* HXViewController.m in Sources */, 226 | 9CB522321D211D9D0047DD2B /* HXTagsView.m in Sources */, 227 | 9CA9CF931D24AB64007F3E91 /* HXTagAttribute.m in Sources */, 228 | 30E706231C476F5200F12FD1 /* AppDelegate.m in Sources */, 229 | E4968DCD1D3CDDA400102A3E /* HXTagTableViewController.m in Sources */, 230 | 30E706201C476F5200F12FD1 /* main.m in Sources */, 231 | 9CA9CF901D24AB30007F3E91 /* HXTagsCell.m in Sources */, 232 | 9CB522311D211D9D0047DD2B /* HXTagCollectionViewCell.m in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | /* End PBXSourcesBuildPhase section */ 237 | 238 | /* Begin XCBuildConfiguration section */ 239 | 30E706301C476F5200F12FD1 /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 244 | CLANG_CXX_LIBRARY = "libc++"; 245 | CLANG_ENABLE_MODULES = YES; 246 | CLANG_ENABLE_OBJC_ARC = YES; 247 | CLANG_WARN_BOOL_CONVERSION = YES; 248 | CLANG_WARN_CONSTANT_CONVERSION = YES; 249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 254 | CLANG_WARN_UNREACHABLE_CODE = YES; 255 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 256 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 257 | COPY_PHASE_STRIP = NO; 258 | DEBUG_INFORMATION_FORMAT = dwarf; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | ENABLE_TESTABILITY = YES; 261 | GCC_C_LANGUAGE_STANDARD = gnu99; 262 | GCC_DYNAMIC_NO_PIC = NO; 263 | GCC_NO_COMMON_BLOCKS = YES; 264 | GCC_OPTIMIZATION_LEVEL = 0; 265 | GCC_PREPROCESSOR_DEFINITIONS = ( 266 | "DEBUG=1", 267 | "$(inherited)", 268 | ); 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 276 | MTL_ENABLE_DEBUG_INFO = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = iphoneos; 279 | }; 280 | name = Debug; 281 | }; 282 | 30E706311C476F5200F12FD1 /* Release */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ALWAYS_SEARCH_USER_PATHS = NO; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_MODULES = YES; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_WARN_BOOL_CONVERSION = YES; 291 | CLANG_WARN_CONSTANT_CONVERSION = YES; 292 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 293 | CLANG_WARN_EMPTY_BODY = YES; 294 | CLANG_WARN_ENUM_CONVERSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 297 | CLANG_WARN_UNREACHABLE_CODE = YES; 298 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 299 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 300 | COPY_PHASE_STRIP = NO; 301 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 302 | ENABLE_NS_ASSERTIONS = NO; 303 | ENABLE_STRICT_OBJC_MSGSEND = YES; 304 | GCC_C_LANGUAGE_STANDARD = gnu99; 305 | GCC_NO_COMMON_BLOCKS = YES; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 308 | GCC_WARN_UNDECLARED_SELECTOR = YES; 309 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 310 | GCC_WARN_UNUSED_FUNCTION = YES; 311 | GCC_WARN_UNUSED_VARIABLE = YES; 312 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 313 | MTL_ENABLE_DEBUG_INFO = NO; 314 | SDKROOT = iphoneos; 315 | VALIDATE_PRODUCT = YES; 316 | }; 317 | name = Release; 318 | }; 319 | 30E706331C476F5200F12FD1 /* Debug */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 323 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 324 | INFOPLIST_FILE = HXTagsView/Info.plist; 325 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 326 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 327 | PRODUCT_BUNDLE_IDENTIFIER = blog.libuqing.com.HXTagsView; 328 | PRODUCT_NAME = "$(TARGET_NAME)"; 329 | }; 330 | name = Debug; 331 | }; 332 | 30E706341C476F5200F12FD1 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 336 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 337 | INFOPLIST_FILE = HXTagsView/Info.plist; 338 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 339 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 340 | PRODUCT_BUNDLE_IDENTIFIER = blog.libuqing.com.HXTagsView; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | }; 343 | name = Release; 344 | }; 345 | /* End XCBuildConfiguration section */ 346 | 347 | /* Begin XCConfigurationList section */ 348 | 30E706161C476F5100F12FD1 /* Build configuration list for PBXProject "HXTagsView" */ = { 349 | isa = XCConfigurationList; 350 | buildConfigurations = ( 351 | 30E706301C476F5200F12FD1 /* Debug */, 352 | 30E706311C476F5200F12FD1 /* Release */, 353 | ); 354 | defaultConfigurationIsVisible = 0; 355 | defaultConfigurationName = Release; 356 | }; 357 | 30E706321C476F5200F12FD1 /* Build configuration list for PBXNativeTarget "HXTagsView" */ = { 358 | isa = XCConfigurationList; 359 | buildConfigurations = ( 360 | 30E706331C476F5200F12FD1 /* Debug */, 361 | 30E706341C476F5200F12FD1 /* Release */, 362 | ); 363 | defaultConfigurationIsVisible = 0; 364 | defaultConfigurationName = Release; 365 | }; 366 | /* End XCConfigurationList section */ 367 | }; 368 | rootObject = 30E706131C476F5100F12FD1 /* Project object */; 369 | } 370 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/Love.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/Love.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/huangxuan518.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/huangxuan518.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/lzg.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView.xcodeproj/project.xcworkspace/xcuserdata/lzg.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/Love.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/Love.xcuserdatad/xcschemes/HXTagsView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/Love.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HXTagsView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 30E7061A1C476F5100F12FD1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/huangxuan518.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/huangxuan518.xcuserdatad/xcschemes/HXTagsView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/huangxuan518.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HXTagsView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 30E7061A1C476F5100F12FD1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/lzg.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/lzg.xcuserdatad/xcschemes/HXTagsView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /HXTagsView.xcodeproj/xcuserdata/lzg.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HXTagsView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 30E7061A1C476F5100F12FD1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HXTagsView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/1/14. 6 | // Copyright © 2016年 IT小子. 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 | -------------------------------------------------------------------------------- /HXTagsView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/1/14. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "HXViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 22 | self.window.backgroundColor = [UIColor whiteColor]; 23 | 24 | HXViewController *vc = [HXViewController new]; 25 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; 26 | self.window.rootViewController = nav; 27 | 28 | [self.window makeKeyAndVisible]; 29 | 30 | return YES; 31 | } 32 | 33 | - (void)applicationWillResignActive:(UIApplication *)application { 34 | // 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. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application { 39 | // 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. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | - (void)applicationWillEnterForeground:(UIApplication *)application { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application { 48 | // 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. 49 | } 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /HXTagsView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /HXTagsView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /HXTagsView/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "8.0", 8 | "subtype" : "736h", 9 | "scale" : "3x" 10 | }, 11 | { 12 | "orientation" : "landscape", 13 | "idiom" : "iphone", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "8.0", 16 | "subtype" : "736h", 17 | "scale" : "3x" 18 | }, 19 | { 20 | "extent" : "full-screen", 21 | "idiom" : "iphone", 22 | "subtype" : "667h", 23 | "filename" : "Default-667h@2x.png", 24 | "minimum-system-version" : "8.0", 25 | "orientation" : "portrait", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "orientation" : "portrait", 30 | "idiom" : "iphone", 31 | "extent" : "full-screen", 32 | "minimum-system-version" : "7.0", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "extent" : "full-screen", 37 | "idiom" : "iphone", 38 | "subtype" : "retina4", 39 | "filename" : "Default-568h@2x.png", 40 | "minimum-system-version" : "7.0", 41 | "orientation" : "portrait", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "orientation" : "portrait", 46 | "idiom" : "iphone", 47 | "extent" : "full-screen", 48 | "scale" : "1x" 49 | }, 50 | { 51 | "orientation" : "portrait", 52 | "idiom" : "iphone", 53 | "extent" : "full-screen", 54 | "scale" : "2x" 55 | }, 56 | { 57 | "orientation" : "portrait", 58 | "idiom" : "iphone", 59 | "extent" : "full-screen", 60 | "subtype" : "retina4", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /HXTagsView/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png -------------------------------------------------------------------------------- /HXTagsView/Assets.xcassets/LaunchImage.launchimage/default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/Assets.xcassets/LaunchImage.launchimage/default-568h@2x.png -------------------------------------------------------------------------------- /HXTagsView/HXTagTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagTableViewController.h 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/7/18. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HXTagTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HXTagsView/HXTagTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagTableViewController.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/7/18. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagTableViewController.h" 10 | #import "HXTagsCell.h" 11 | 12 | @interface HXTagTableViewController () 13 | 14 | @property (nonatomic,strong) HXTagCollectionViewFlowLayout *layout;//布局layout 15 | @property (nonatomic,strong) NSArray *selectTags; 16 | 17 | @end 18 | 19 | @implementation HXTagTableViewController 20 | 21 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 23 | if (self) { 24 | 25 | } 26 | return self; 27 | } 28 | 29 | - (HXTagCollectionViewFlowLayout *)layout { 30 | if (!_layout) { 31 | _layout = [HXTagCollectionViewFlowLayout new]; 32 | _layout.scrollDirection = UICollectionViewScrollDirectionVertical; 33 | } 34 | return _layout; 35 | } 36 | 37 | - (NSArray *)tags { 38 | return @[@"火游戏影ol游戏",@"问游戏道",@"天游戏龙游戏八游戏部",@"枪神纪游戏",@"英魂之游戏刃",@"勇者游戏大冒险",@"nba 游戏2k",@"上古世纪游戏",@"游戏跑跑卡游戏丁车",@"传奇世界游戏",@"劲舞游戏团",@"激游戏战2",@"蜀山ol",@"天下3",@"大话西游2",@"热血江湖",@"游戏人生",@"梦三国",@"流星蝴蝶剑",@"九阴真经",@"斗战神",@"奇迹mu",@"最终幻想14",@"宠物小精灵"]; 39 | } 40 | 41 | - (void)viewDidLoad { 42 | [super viewDidLoad]; 43 | 44 | // Uncomment the following line to preserve selection between presentations. 45 | 46 | [self.tableView registerClass:HXTagsCell.class forCellReuseIdentifier:@"cellId"]; 47 | } 48 | 49 | #pragma mark UITableViewDataSource/UITableViewDelegate 50 | 51 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 52 | return 1; 53 | } 54 | 55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 56 | 57 | HXTagsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellId"]; 58 | if (!cell) { 59 | cell = [[HXTagsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellId"]; 60 | } 61 | 62 | cell.tags = self.tags; 63 | cell.selectedTags = [NSMutableArray arrayWithArray:_selectTags]; 64 | cell.layout = self.layout; 65 | cell.completion = ^(NSArray *selectTags,NSInteger currentIndex) { 66 | NSLog(@"selectTags:%@ currentIndex:%ld",selectTags, (long)currentIndex); 67 | _selectTags = selectTags; 68 | }; 69 | [cell reloadData]; 70 | 71 | return cell; 72 | } 73 | 74 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 75 | float height = [HXTagsCell getCellHeightWithTags:self.tags layout:self.layout tagAttribute:nil width:tableView.frame.size.width]; 76 | return height; 77 | } 78 | 79 | - (void)didReceiveMemoryWarning { 80 | [super didReceiveMemoryWarning]; 81 | // Dispose of any resources that can be recreated. 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /HXTagsView/HXViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXViewController.h 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/1/14. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HXViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /HXTagsView/HXViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXViewController.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/1/14. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXViewController.h" 10 | #import "HXTagTableViewController.h" 11 | #import "HXTagsView.h" 12 | 13 | @interface HXViewController () 14 | 15 | @property (nonatomic,strong) UILabel *titleLabel;//标题 16 | @property (nonatomic, strong) HXTagsView *tagsView;//tagsView 17 | @property (nonatomic,assign) BOOL isScrollDirection;//单行多行开关 18 | @property (nonatomic,assign) BOOL isMultiLineRoll;//多行滚动不滚动开关 19 | @property (nonatomic,assign) BOOL isMultiSelect;//单选多选开关 20 | 21 | @property (nonatomic,strong) UIView *scrollDirectionView; 22 | @property (nonatomic,strong) UIView *multiLineRollView; 23 | @property (nonatomic,strong) UIView *multiSelectView; 24 | 25 | @end 26 | 27 | @implementation HXViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | UIView *view = [[UIView alloc] initWithFrame:self.view.frame]; 32 | view.backgroundColor = [UIColor clearColor]; 33 | [self.view addSubview:view]; 34 | 35 | UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"tableView使用" style:UIBarButtonItemStyleDone target:self action:@selector(gotoTagTableViewController)]; 36 | self.navigationItem.rightBarButtonItem = item; 37 | 38 | self.title = @"标签"; 39 | 40 | [self addView]; 41 | 42 | self.titleLabel.text = @"单行滚动"; 43 | [self showTagsView]; 44 | } 45 | 46 | - (void)switchValueChanged:(UISwitch *)sender { 47 | BOOL on = sender.on; 48 | 49 | if (sender.tag == 1) { 50 | //单行多行开关 51 | if (on) { 52 | self.tagsView.layout.scrollDirection = UICollectionViewScrollDirectionVertical; 53 | } else { 54 | self.tagsView.layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 55 | } 56 | _isScrollDirection = on; 57 | } else if (sender.tag == 2) { 58 | //滚动不滚动开关 59 | _isMultiLineRoll = on; 60 | } else if (sender.tag == 3) { 61 | //单选多选开关 62 | self.tagsView.isMultiSelect = on; 63 | _isMultiSelect = on; 64 | } 65 | 66 | CGFloat height = [HXTagsView getHeightWithTags:self.tagsView.tags layout:self.tagsView.layout tagAttribute:self.tagsView.tagAttribute width:self.view.frame.size.width]; 67 | 68 | NSMutableString *str; 69 | 70 | if (_isScrollDirection) { 71 | str = [NSMutableString stringWithString:@"多行"]; 72 | _multiLineRollView.hidden = NO; 73 | 74 | if (_isMultiLineRoll) { 75 | [str appendString:@"滚动"]; 76 | self.tagsView.frame = CGRectMake(0, 300, self.view.frame.size.width, 100); 77 | } else { 78 | [str appendString:@"不滚动"]; 79 | self.tagsView.frame = CGRectMake(0, 300, self.view.frame.size.width, height); 80 | } 81 | } else { 82 | str = [NSMutableString stringWithString:@"单行"]; 83 | self.tagsView.frame = CGRectMake(0, 300, self.view.frame.size.width, 54); 84 | _multiLineRollView.hidden = YES; 85 | } 86 | 87 | if (_isMultiSelect) { 88 | [str appendString:@"多选"]; 89 | } else { 90 | [str appendString:@"单选"]; 91 | } 92 | 93 | self.titleLabel.text = str; 94 | 95 | [self.tagsView reloadData]; 96 | } 97 | 98 | /** 99 | * 显示 100 | */ 101 | - (void)showTagsView { 102 | self.tagsView.tags = @[@"火游戏影ol游戏",@"问游戏道",@"天游戏龙游戏八游戏部",@"枪神纪游戏",@"英魂之游戏刃",@"勇者游戏大冒险",@"nba 游戏2k",@"上古世纪游戏",@"游戏跑跑卡游戏丁车",@"传奇世界游戏",@"劲舞游戏团",@"激游戏战2",@"蜀山ol",@"天下3",@"大话西游2",@"热血江湖",@"游戏人生",@"梦三国",@"流星蝴蝶剑",@"九阴真经",@"斗战神",@"奇迹mu",@"最终幻想14",@"宠物小精灵"]; 103 | [self.tagsView reloadData]; 104 | } 105 | 106 | #pragma mark - 添加View 107 | 108 | - (void)addView { 109 | //单行多行开关 110 | _scrollDirectionView = [[UIView alloc] initWithFrame:CGRectMake(0, 74, self.view.frame.size.width, 40)]; 111 | _scrollDirectionView.backgroundColor = [UIColor whiteColor]; 112 | 113 | UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 300, 40)]; 114 | titleLabel.text = @"单行(NO)多行(YES)开关"; 115 | titleLabel.font = [UIFont systemFontOfSize:14]; 116 | titleLabel.textColor = [UIColor grayColor]; 117 | [_scrollDirectionView addSubview:titleLabel]; 118 | 119 | UISwitch *mySwitch = [[ UISwitch alloc]initWithFrame:CGRectMake(_scrollDirectionView.frame.size.width - 70,0,0.0,0.0)]; 120 | mySwitch.tag = 1; 121 | [mySwitch addTarget: self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged]; 122 | [_scrollDirectionView addSubview:mySwitch]; 123 | 124 | [self.view addSubview:_scrollDirectionView]; 125 | 126 | //滚动不滚动开关 127 | _multiLineRollView = [[UIView alloc] initWithFrame:CGRectMake(0, 74 + 40, self.view.frame.size.width, 40)]; 128 | _multiLineRollView.backgroundColor = [UIColor whiteColor]; 129 | 130 | titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 300, 40)]; 131 | titleLabel.text = @"多行滚动(YES)不滚动(NO)开关(多行起作用)"; 132 | titleLabel.font = [UIFont systemFontOfSize:14]; 133 | titleLabel.textColor = [UIColor grayColor]; 134 | _multiLineRollView.hidden = YES; 135 | [_multiLineRollView addSubview:titleLabel]; 136 | 137 | mySwitch = [[ UISwitch alloc]initWithFrame:CGRectMake(_multiLineRollView.frame.size.width - 70,0,0.0,0.0)]; 138 | mySwitch.tag = 2; 139 | [mySwitch addTarget: self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged]; 140 | [_multiLineRollView addSubview:mySwitch]; 141 | 142 | [self.view addSubview:_multiLineRollView]; 143 | 144 | //单选多选开关 145 | _multiSelectView = [[UIView alloc] initWithFrame:CGRectMake(0, 74 + 80, self.view.frame.size.width, 40)]; 146 | _multiSelectView.backgroundColor = [UIColor whiteColor]; 147 | 148 | titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 300, 40)]; 149 | titleLabel.text = @"单选(NO)多选(YES)开关"; 150 | titleLabel.font = [UIFont systemFontOfSize:14]; 151 | titleLabel.textColor = [UIColor grayColor]; 152 | [_multiSelectView addSubview:titleLabel]; 153 | 154 | mySwitch = [[ UISwitch alloc]initWithFrame:CGRectMake(_multiSelectView.frame.size.width - 70,0,0.0,0.0)]; 155 | mySwitch.tag = 3; 156 | [mySwitch addTarget: self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged]; 157 | [_multiSelectView addSubview:mySwitch]; 158 | 159 | [self.view addSubview:_multiSelectView]; 160 | 161 | UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0f, 200.0f, self.view.frame.size.width - 20, 40.0f)]; 162 | [textField setBorderStyle:UITextBorderStyleRoundedRect]; //外框类型 163 | textField.placeholder = @"请输入搜索词";//默认显示的字 164 | textField.clearButtonMode = UITextFieldViewModeWhileEditing; //编辑时会出现个修改X 165 | [textField addTarget:self action:@selector(textFieldChange:) forControlEvents:UIControlEventEditingChanged]; 166 | UIView *inputAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)]; 167 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 168 | button.frame = CGRectMake(inputAccessoryView.frame.size.width - 42, 0, 32, 43.5); 169 | button.titleLabel.font = [UIFont systemFontOfSize:16]; 170 | [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 171 | [button setTitle:@"收起" forState:UIControlStateNormal]; 172 | [button addTarget:self action:@selector(hideButtonAction:) forControlEvents:UIControlEventTouchUpInside]; 173 | [inputAccessoryView addSubview:button]; 174 | textField.inputAccessoryView = inputAccessoryView; 175 | [self.view addSubview:textField]; 176 | } 177 | 178 | - (void)hideButtonAction:(UIButton *)sender { 179 | [self.view endEditing:YES]; 180 | } 181 | 182 | - (void)textFieldChange:(UITextField *)sender { 183 | self.tagsView.key = sender.text; 184 | [self.tagsView reloadData]; 185 | } 186 | 187 | #pragma mark - 懒加载 188 | 189 | - (UILabel *)titleLabel { 190 | if (!_titleLabel) { 191 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 270, 200, 20)]; 192 | [self.view addSubview:_titleLabel]; 193 | } 194 | return _titleLabel; 195 | } 196 | 197 | - (HXTagsView *)tagsView { 198 | if (!_tagsView) { 199 | _tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 54)]; 200 | _tagsView.completion = ^(NSArray *selectTags,NSInteger currentIndex) { 201 | NSLog(@"selectTags:%@ currentIndex:%ld",selectTags, (long)currentIndex); 202 | }; 203 | [self.view addSubview:_tagsView]; 204 | } 205 | return _tagsView; 206 | } 207 | 208 | #pragma mark - goto 209 | 210 | - (void)gotoTagTableViewController { 211 | HXTagTableViewController *vc = [HXTagTableViewController new]; 212 | [self.navigationController pushViewController:vc animated:YES]; 213 | } 214 | 215 | - (void)didReceiveMemoryWarning { 216 | [super didReceiveMemoryWarning]; 217 | // Dispose of any resources that can be recreated. 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /HXTagsView/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | NSAppTransportSecurity 36 | 37 | NSAllowsArbitraryLoads 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /HXTagsView/canshu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/canshu.png -------------------------------------------------------------------------------- /HXTagsView/danhangbugundongxiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/danhangbugundongxiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/danhanggundongxiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/danhanggundongxiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/duohanggundongxiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/duohanggundongxiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/duohangpingpudan1xiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/duohangpingpudan1xiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/duohangpingpudanxiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/duohangpingpudanxiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/duohangpingpuxiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/duohangpingpuxiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by 黄轩 on 16/1/14. 6 | // Copyright © 2016年 IT小子. 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 | -------------------------------------------------------------------------------- /HXTagsView/xiaoguo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangxuan518/HXTagsView/6c8725296aceee4910c6624246626afa99f17448/HXTagsView/xiaoguo.gif -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagAttribute.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagAttribute.h 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by Love on 16/6/30. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface HXTagAttribute : NSObject 13 | 14 | @property (nonatomic,assign) CGFloat borderWidth;//标签边框宽度 15 | @property (nonatomic,strong) UIColor *borderColor;//标签边框颜色 16 | @property (nonatomic,assign) CGFloat cornerRadius;//标签圆角大小 17 | @property (nonatomic,strong) UIColor *normalBackgroundColor;//标签默认背景颜色 18 | @property (nonatomic,strong) UIColor *selectedBackgroundColor;//标签选中背景颜色 19 | @property (nonatomic,assign) CGFloat titleSize;//标签字体大小 20 | @property (nonatomic,strong) UIColor *textColor;//标签字体颜色 21 | @property (nonatomic,strong) UIColor *keyColor;//搜索关键词颜色 22 | @property (nonatomic,assign) CGFloat tagSpace;//标签内部左右间距(标题距离边框2边的距离和) 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagAttribute.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagAttribute.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by Love on 16/6/30. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagAttribute.h" 10 | 11 | @implementation HXTagAttribute 12 | 13 | - (instancetype)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | int r = arc4random() % 255; 18 | int g = arc4random() % 255; 19 | int b = arc4random() % 255; 20 | 21 | UIColor *normalColor = [UIColor colorWithRed:b/255.0 green:r/255.0 blue:g/255.0 alpha:1.0]; 22 | UIColor *normalBackgroundColor = [UIColor whiteColor]; 23 | UIColor *selectedBackgroundColor = [UIColor colorWithRed:220/255.0 green:220/255.0 blue:220/255.0 alpha:1.0]; 24 | 25 | _borderWidth = 0.5f; 26 | _borderColor = normalColor; 27 | _cornerRadius = 2.0; 28 | _normalBackgroundColor = normalBackgroundColor; 29 | _selectedBackgroundColor = selectedBackgroundColor; 30 | _titleSize = 14; 31 | _textColor = normalColor; 32 | _keyColor = [UIColor redColor]; 33 | _tagSpace = 20; 34 | } 35 | return self; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagCollectionViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagCollectionViewCell.h 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HXTagCollectionViewCell : UICollectionViewCell 12 | 13 | @property (nonatomic,strong) UILabel *titleLabel; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagCollectionViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagCollectionViewCell.m 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagCollectionViewCell.h" 10 | 11 | @implementation HXTagCollectionViewCell 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame 14 | { 15 | if (self = [super initWithFrame:frame]) { 16 | _titleLabel = [[UILabel alloc] initWithFrame:self.bounds]; 17 | _titleLabel.textAlignment = NSTextAlignmentCenter; 18 | [self.contentView addSubview:_titleLabel]; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | - (void)layoutSubviews 25 | { 26 | [super layoutSubviews]; 27 | 28 | self.titleLabel.frame = self.bounds; 29 | } 30 | 31 | - (void)prepareForReuse 32 | { 33 | [super prepareForReuse]; 34 | 35 | self.titleLabel.text = @""; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagCollectionViewFlowLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagCollectionViewFlowLayout.h 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HXTagCollectionViewFlowLayout : UICollectionViewFlowLayout 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagCollectionViewFlowLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagCollectionViewFlowLayout.m 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagCollectionViewFlowLayout.h" 10 | 11 | @interface HXTagCollectionViewFlowLayout() 12 | 13 | @property (nonatomic, weak) id delegate; 14 | @property (nonatomic, strong) NSMutableArray *itemAttributes; 15 | @property (nonatomic, assign) CGFloat contentWidth;//滑动宽度 水平 16 | @property (nonatomic, assign) CGFloat contentHeight;//滑动高度 垂直 17 | 18 | @end 19 | 20 | @implementation HXTagCollectionViewFlowLayout 21 | 22 | - (instancetype)init 23 | { 24 | self = [super init]; 25 | if (self) { 26 | self.scrollDirection = UICollectionViewScrollDirectionHorizontal; 27 | self.itemSize = CGSizeMake(100.0f, 34.0f); 28 | self.minimumInteritemSpacing = 10.0f; 29 | self.minimumLineSpacing = 10.0f; 30 | self.sectionInset = UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f); 31 | } 32 | return self; 33 | } 34 | 35 | #pragma mark - 36 | 37 | - (void)prepareLayout 38 | { 39 | [super prepareLayout]; 40 | 41 | [self.itemAttributes removeAllObjects]; 42 | 43 | //滑动的宽度 = 左边 44 | self.contentWidth = self.sectionInset.left; 45 | 46 | //cell的高度 = 顶部 + 高度 47 | self.contentHeight = self.sectionInset.top + self.itemSize.height; 48 | 49 | CGFloat originX = self.sectionInset.left; 50 | CGFloat originY = self.sectionInset.top; 51 | 52 | NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; 53 | 54 | for (NSInteger i = 0; i < itemCount; i++) { 55 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 56 | CGSize itemSize = [self itemSizeForIndexPath:indexPath]; 57 | 58 | if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 59 | //垂直滚动 60 | //当前CollectionViewCell的起点 + 当前CollectionViewCell的宽度 + 当前CollectionView距离右侧的间隔 > collectionView的宽度 61 | if ((originX + itemSize.width + self.sectionInset.right) > self.collectionView.frame.size.width) { 62 | originX = self.sectionInset.left; 63 | originY += itemSize.height + self.minimumLineSpacing; 64 | 65 | self.contentHeight += itemSize.height + self.minimumLineSpacing; 66 | } 67 | } else { 68 | self.contentWidth += itemSize.width + self.minimumInteritemSpacing; 69 | } 70 | 71 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 72 | attributes.frame = CGRectMake(originX, originY, itemSize.width, itemSize.height); 73 | [self.itemAttributes addObject:attributes]; 74 | 75 | originX += itemSize.width + self.minimumInteritemSpacing; 76 | } 77 | 78 | self.contentHeight += self.sectionInset.bottom; 79 | } 80 | 81 | - (CGSize)collectionViewContentSize 82 | { 83 | if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { 84 | return CGSizeMake(self.collectionView.frame.size.width, self.contentHeight); 85 | } else { 86 | return CGSizeMake(self.contentWidth,self.collectionView.frame.size.height); 87 | } 88 | } 89 | 90 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 91 | { 92 | return self.itemAttributes; 93 | } 94 | 95 | - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 96 | { 97 | CGRect oldBounds = self.collectionView.bounds; 98 | 99 | if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds)) { 100 | return YES; 101 | } 102 | 103 | return NO; 104 | } 105 | 106 | #pragma mark - 107 | 108 | - (id)delegate 109 | { 110 | if (_delegate == nil) { 111 | _delegate = (id)self.collectionView.delegate; 112 | } 113 | 114 | return _delegate; 115 | } 116 | 117 | - (CGSize)itemSizeForIndexPath:(NSIndexPath *)indexPath 118 | { 119 | if ([self.delegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]) { 120 | self.itemSize = [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath]; 121 | } 122 | 123 | return self.itemSize; 124 | } 125 | 126 | #pragma mark - 懒加载 127 | 128 | //UICollectionViewLayoutAttributes数组 129 | - (NSMutableArray *)itemAttributes { 130 | if (!_itemAttributes) { 131 | _itemAttributes = [NSMutableArray array]; 132 | } 133 | return _itemAttributes; 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagsCell.h 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by Love on 16/6/30. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HXTagCollectionViewFlowLayout.h" 11 | 12 | @class HXTagAttribute; 13 | 14 | @interface HXTagsCell : UITableViewCell 15 | 16 | @property (nonatomic,strong) NSArray *tags;//传入的标签数组 字符串数组 17 | @property (nonatomic,strong) NSMutableArray *selectedTags; //选择的标签数组 18 | @property (nonatomic,strong) HXTagCollectionViewFlowLayout *layout;//布局layout 19 | @property (nonatomic,strong) HXTagAttribute *tagAttribute;//按钮样式对象 20 | @property (nonatomic,assign) BOOL isMultiSelect;//是否可以多选 默认:NO 单选 21 | @property (nonatomic,copy) NSString *key;//搜索关键词 22 | 23 | @property (nonatomic,copy) void (^completion)(NSArray *selectTags,NSInteger currentIndex);//选中的标签数组,当前点击的index 24 | 25 | //刷新界面 26 | - (void)reloadData; 27 | 28 | /** 29 | * 计算Cell的高度 30 | * 31 | * @param tags 标签数组 32 | * @param layout 布局样式 默认则传nil 33 | * @param tagAttribute 标签样式 默认传nil 涉及到计算的主要是titleSize 34 | * @param width 计算的最大范围 35 | */ 36 | + (CGFloat)getCellHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagsCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagsCell.m 3 | // HXTagsView https://github.com/huangxuan518/HXTagsView 4 | // 博客地址 http://blog.libuqing.com/ 5 | // Created by Love on 16/6/30. 6 | // Copyright © 2016年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagsCell.h" 10 | #import "HXTagCollectionViewCell.h" 11 | #import "HXTagAttribute.h" 12 | 13 | @interface HXTagsCell () 14 | 15 | @property (nonatomic,strong) UICollectionView *collectionView; 16 | 17 | @end 18 | 19 | @implementation HXTagsCell 20 | 21 | static NSString * const reuseIdentifier = @"HXTagCollectionViewCellId"; 22 | 23 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 24 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 25 | if (self) { 26 | [self setup]; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | - (id)initWithCoder:(NSCoder *)aDecoder 33 | { 34 | if (self = [super initWithCoder:aDecoder]) { 35 | [self setup]; 36 | } 37 | 38 | return self; 39 | } 40 | 41 | - (void)setup 42 | { 43 | //初始化样式 44 | _tagAttribute = [HXTagAttribute new]; 45 | 46 | _layout = [[HXTagCollectionViewFlowLayout alloc] init]; 47 | [self addSubview:self.collectionView]; 48 | } 49 | 50 | #pragma mark - UICollectionViewDelegate | UICollectionViewDataSource 51 | 52 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 53 | { 54 | return _tags.count; 55 | } 56 | 57 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 58 | { 59 | HXTagCollectionViewFlowLayout *layout = (HXTagCollectionViewFlowLayout *)collectionView.collectionViewLayout; 60 | CGSize maxSize = CGSizeMake(collectionView.frame.size.width - layout.sectionInset.left - layout.sectionInset.right, layout.itemSize.height); 61 | 62 | CGRect frame = [_tags[indexPath.item] boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:_tagAttribute.titleSize]} context:nil]; 63 | 64 | return CGSizeMake(frame.size.width + _tagAttribute.tagSpace, layout.itemSize.height); 65 | } 66 | 67 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 68 | { 69 | HXTagCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 70 | cell.backgroundColor = _tagAttribute.normalBackgroundColor; 71 | cell.layer.borderColor = _tagAttribute.borderColor.CGColor; 72 | cell.layer.cornerRadius = _tagAttribute.cornerRadius; 73 | cell.layer.borderWidth = _tagAttribute.borderWidth; 74 | cell.titleLabel.textColor = _tagAttribute.textColor; 75 | cell.titleLabel.font = [UIFont systemFontOfSize:_tagAttribute.titleSize]; 76 | 77 | NSString *title = self.tags[indexPath.item]; 78 | if (_key.length > 0) { 79 | cell.titleLabel.attributedText = [self searchTitle:title key:_key keyColor:_tagAttribute.keyColor]; 80 | } else { 81 | cell.titleLabel.text = title; 82 | } 83 | 84 | if ([self.selectedTags containsObject:self.tags[indexPath.item]]) { 85 | cell.backgroundColor = _tagAttribute.selectedBackgroundColor; 86 | } 87 | 88 | return cell; 89 | } 90 | 91 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 92 | { 93 | HXTagCollectionViewCell *cell = (HXTagCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; 94 | 95 | if ([self.selectedTags containsObject:self.tags[indexPath.item]]) { 96 | cell.backgroundColor = _tagAttribute.normalBackgroundColor; 97 | [self.selectedTags removeObject:self.tags[indexPath.item]]; 98 | } 99 | else { 100 | if (_isMultiSelect) { 101 | cell.backgroundColor = _tagAttribute.selectedBackgroundColor; 102 | [self.selectedTags addObject:self.tags[indexPath.item]]; 103 | } else { 104 | [self.selectedTags removeAllObjects]; 105 | [self.selectedTags addObject:self.tags[indexPath.item]]; 106 | 107 | [self reloadData]; 108 | } 109 | } 110 | 111 | if (_completion) { 112 | _completion(self.selectedTags,indexPath.item); 113 | } 114 | } 115 | 116 | // 设置文字中关键字高亮 117 | - (NSMutableAttributedString *)searchTitle:(NSString *)title key:(NSString *)key keyColor:(UIColor *)keyColor { 118 | 119 | NSMutableAttributedString *titleStr = [[NSMutableAttributedString alloc] initWithString:title]; 120 | NSString *copyStr = title; 121 | 122 | NSMutableString *xxstr = [NSMutableString new]; 123 | for (int i = 0; i < key.length; i++) { 124 | [xxstr appendString:@"*"]; 125 | } 126 | 127 | while ([copyStr rangeOfString:key options:NSCaseInsensitiveSearch].location != NSNotFound) { 128 | 129 | NSRange range = [copyStr rangeOfString:key options:NSCaseInsensitiveSearch]; 130 | 131 | [titleStr addAttribute:NSForegroundColorAttributeName value:keyColor range:range]; 132 | copyStr = [copyStr stringByReplacingCharactersInRange:NSMakeRange(range.location, range.length) withString:xxstr]; 133 | } 134 | return titleStr; 135 | } 136 | 137 | - (void)reloadData { 138 | [self.collectionView reloadData]; 139 | } 140 | 141 | - (void)layoutSubviews { 142 | [super layoutSubviews]; 143 | _collectionView.frame = self.bounds; 144 | } 145 | 146 | #pragma mark - 懒加载 147 | 148 | - (NSMutableArray *)selectedTags 149 | { 150 | if (!_selectedTags) { 151 | _selectedTags = [NSMutableArray array]; 152 | } 153 | return _selectedTags; 154 | } 155 | 156 | - (UICollectionView *)collectionView { 157 | if (!_collectionView) { 158 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 362) collectionViewLayout:_layout]; 159 | _collectionView.delegate = self; 160 | _collectionView.dataSource = self; 161 | _collectionView.backgroundColor = [UIColor colorWithRed:241/255.0 green:241/255.0 blue:241/255.0 alpha:1.0]; 162 | [_collectionView registerClass:[HXTagCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier]; 163 | } 164 | 165 | _collectionView.collectionViewLayout = _layout; 166 | 167 | if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { 168 | //垂直 169 | _collectionView.showsVerticalScrollIndicator = YES; 170 | _collectionView.showsHorizontalScrollIndicator = NO; 171 | } else { 172 | _collectionView.showsHorizontalScrollIndicator = YES; 173 | _collectionView.showsVerticalScrollIndicator = NO; 174 | } 175 | 176 | _collectionView.frame = self.bounds; 177 | 178 | return _collectionView; 179 | } 180 | 181 | + (CGFloat)getCellHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width 182 | { 183 | CGFloat contentHeight = 0; 184 | 185 | if (!layout) { 186 | layout = [[HXTagCollectionViewFlowLayout alloc] init]; 187 | } 188 | 189 | if (tagAttribute.titleSize <= 0) { 190 | tagAttribute = [[HXTagAttribute alloc] init]; 191 | } 192 | 193 | //cell的高度 = 顶部 + 高度 194 | contentHeight = layout.sectionInset.top + layout.itemSize.height; 195 | 196 | CGFloat originX = layout.sectionInset.left; 197 | CGFloat originY = layout.sectionInset.top; 198 | 199 | NSInteger itemCount = tags.count; 200 | 201 | for (NSInteger i = 0; i < itemCount; i++) { 202 | CGSize maxSize = CGSizeMake(width - layout.sectionInset.left - layout.sectionInset.right, layout.itemSize.height); 203 | 204 | CGRect frame = [tags[i] boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:tagAttribute.titleSize]} context:nil]; 205 | 206 | CGSize itemSize = CGSizeMake(frame.size.width + tagAttribute.tagSpace, layout.itemSize.height); 207 | 208 | if (layout.scrollDirection == UICollectionViewScrollDirectionVertical) { 209 | //垂直滚动 210 | //当前CollectionViewCell的起点 + 当前CollectionViewCell的宽度 + 当前CollectionView距离右侧的间隔 > collectionView的宽度 211 | if ((originX + itemSize.width + layout.sectionInset.right) > width) { 212 | originX = layout.sectionInset.left; 213 | originY += itemSize.height + layout.minimumLineSpacing; 214 | 215 | contentHeight += itemSize.height + layout.minimumLineSpacing; 216 | } 217 | } 218 | 219 | originX += itemSize.width + layout.minimumInteritemSpacing; 220 | } 221 | 222 | contentHeight += layout.sectionInset.bottom; 223 | return contentHeight; 224 | } 225 | 226 | @end 227 | -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagsView.h 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HXTagCollectionViewFlowLayout.h" 11 | 12 | @class HXTagAttribute; 13 | 14 | @interface HXTagsView : UIView 15 | 16 | @property (nonatomic,strong) NSArray *tags;//传入的标签数组 字符串数组 17 | @property (nonatomic,strong) HXTagCollectionViewFlowLayout *layout;//布局layout 18 | @property (nonatomic,strong) HXTagAttribute *tagAttribute;//按钮样式对象 19 | @property (nonatomic,assign) BOOL isMultiSelect;//是否可以多选 默认:NO 单选 20 | @property (nonatomic,copy) NSString *key;//搜索关键词 21 | 22 | @property (nonatomic,copy) void (^completion)(NSArray *selectTags,NSInteger currentIndex);//选中的标签数组,当前点击的index 23 | 24 | //刷新界面 25 | - (void)reloadData; 26 | 27 | /** 28 | * 计算Cell的高度 29 | * 30 | * @param tags 标签数组 31 | * @param layout 布局样式 默认则传nil 32 | * @param tagAttribute 标签样式 默认传nil 涉及到计算的主要是titleSize 33 | * @param width 计算的最大范围 34 | */ 35 | + (CGFloat)getHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width; 36 | 37 | @end -------------------------------------------------------------------------------- /HXTagsView/标签/HXTagsView.m: -------------------------------------------------------------------------------- 1 | // 2 | // HXTagsView.m 3 | // 黄轩 https://github.com/huangxuan518 4 | // 5 | // Created by 黄轩 on 16/1/13. 6 | // Copyright © 2015年 IT小子. All rights reserved. 7 | // 8 | 9 | #import "HXTagsView.h" 10 | #import "HXTagCollectionViewCell.h" 11 | #import "HXTagAttribute.h" 12 | 13 | @interface HXTagsView () 14 | 15 | @property (nonatomic,strong) NSMutableArray *selectedTags; 16 | @property (nonatomic,strong) UICollectionView *collectionView; 17 | 18 | @end 19 | 20 | @implementation HXTagsView 21 | 22 | static NSString * const reuseIdentifier = @"HXTagCollectionViewCellId"; 23 | 24 | - (id)initWithFrame:(CGRect)frame 25 | { 26 | if (self = [super initWithFrame:frame]) { 27 | [self setup]; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (id)initWithCoder:(NSCoder *)aDecoder 34 | { 35 | if (self = [super initWithCoder:aDecoder]) { 36 | [self setup]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (void)setup 43 | { 44 | //初始化样式 45 | _tagAttribute = [HXTagAttribute new]; 46 | 47 | _layout = [[HXTagCollectionViewFlowLayout alloc] init]; 48 | [self addSubview:self.collectionView]; 49 | } 50 | 51 | #pragma mark - UICollectionViewDelegate | UICollectionViewDataSource 52 | 53 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 54 | { 55 | return _tags.count; 56 | } 57 | 58 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 59 | { 60 | HXTagCollectionViewFlowLayout *layout = (HXTagCollectionViewFlowLayout *)collectionView.collectionViewLayout; 61 | CGSize maxSize = CGSizeMake(collectionView.frame.size.width - layout.sectionInset.left - layout.sectionInset.right, layout.itemSize.height); 62 | 63 | CGRect frame = [_tags[indexPath.item] boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:_tagAttribute.titleSize]} context:nil]; 64 | 65 | return CGSizeMake(frame.size.width + _tagAttribute.tagSpace, layout.itemSize.height); 66 | } 67 | 68 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 69 | { 70 | HXTagCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 71 | cell.backgroundColor = _tagAttribute.normalBackgroundColor; 72 | cell.layer.borderColor = _tagAttribute.borderColor.CGColor; 73 | cell.layer.cornerRadius = _tagAttribute.cornerRadius; 74 | cell.layer.borderWidth = _tagAttribute.borderWidth; 75 | cell.titleLabel.textColor = _tagAttribute.textColor; 76 | cell.titleLabel.font = [UIFont systemFontOfSize:_tagAttribute.titleSize]; 77 | 78 | NSString *title = self.tags[indexPath.item]; 79 | if (_key.length > 0) { 80 | cell.titleLabel.attributedText = [self searchTitle:title key:_key keyColor:_tagAttribute.keyColor]; 81 | } else { 82 | cell.titleLabel.text = title; 83 | } 84 | 85 | if ([self.selectedTags containsObject:self.tags[indexPath.item]]) { 86 | cell.backgroundColor = _tagAttribute.selectedBackgroundColor; 87 | } 88 | 89 | return cell; 90 | } 91 | 92 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 93 | { 94 | HXTagCollectionViewCell *cell = (HXTagCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; 95 | 96 | if ([self.selectedTags containsObject:self.tags[indexPath.item]]) { 97 | cell.backgroundColor = _tagAttribute.normalBackgroundColor; 98 | [self.selectedTags removeObject:self.tags[indexPath.item]]; 99 | } 100 | else { 101 | if (_isMultiSelect) { 102 | cell.backgroundColor = _tagAttribute.selectedBackgroundColor; 103 | [self.selectedTags addObject:self.tags[indexPath.item]]; 104 | } else { 105 | [self.selectedTags removeAllObjects]; 106 | [self.selectedTags addObject:self.tags[indexPath.item]]; 107 | 108 | [self reloadData]; 109 | } 110 | } 111 | 112 | if (_completion) { 113 | _completion(self.selectedTags,indexPath.item); 114 | } 115 | } 116 | 117 | // 设置文字中关键字高亮 118 | - (NSMutableAttributedString *)searchTitle:(NSString *)title key:(NSString *)key keyColor:(UIColor *)keyColor { 119 | 120 | NSMutableAttributedString *titleStr = [[NSMutableAttributedString alloc] initWithString:title]; 121 | NSString *copyStr = title; 122 | 123 | NSMutableString *xxstr = [NSMutableString new]; 124 | for (int i = 0; i < key.length; i++) { 125 | [xxstr appendString:@"*"]; 126 | } 127 | 128 | while ([copyStr rangeOfString:key options:NSCaseInsensitiveSearch].location != NSNotFound) { 129 | 130 | NSRange range = [copyStr rangeOfString:key options:NSCaseInsensitiveSearch]; 131 | 132 | [titleStr addAttribute:NSForegroundColorAttributeName value:keyColor range:range]; 133 | copyStr = [copyStr stringByReplacingCharactersInRange:NSMakeRange(range.location, range.length) withString:xxstr]; 134 | } 135 | return titleStr; 136 | } 137 | 138 | - (void)reloadData { 139 | [self.collectionView reloadData]; 140 | } 141 | 142 | - (void)layoutSubviews { 143 | [super layoutSubviews]; 144 | _collectionView.frame = self.bounds; 145 | } 146 | 147 | #pragma mark - 懒加载 148 | 149 | - (NSMutableArray *)selectedTags 150 | { 151 | if (!_selectedTags) { 152 | _selectedTags = [NSMutableArray array]; 153 | } 154 | return _selectedTags; 155 | } 156 | 157 | - (UICollectionView *)collectionView { 158 | if (!_collectionView) { 159 | _collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:_layout]; 160 | _collectionView.delegate = self; 161 | _collectionView.dataSource = self; 162 | _collectionView.backgroundColor = [UIColor colorWithRed:241/255.0 green:241/255.0 blue:241/255.0 alpha:1.0]; 163 | [_collectionView registerClass:[HXTagCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier]; 164 | } 165 | 166 | _collectionView.collectionViewLayout = _layout; 167 | 168 | if (_layout.scrollDirection == UICollectionViewScrollDirectionVertical) { 169 | //垂直 170 | _collectionView.showsVerticalScrollIndicator = YES; 171 | _collectionView.showsHorizontalScrollIndicator = NO; 172 | } else { 173 | _collectionView.showsHorizontalScrollIndicator = YES; 174 | _collectionView.showsVerticalScrollIndicator = NO; 175 | } 176 | 177 | _collectionView.frame = self.bounds; 178 | 179 | return _collectionView; 180 | } 181 | 182 | + (CGFloat)getHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width 183 | { 184 | CGFloat contentHeight; 185 | 186 | if (!layout) { 187 | layout = [[HXTagCollectionViewFlowLayout alloc] init]; 188 | } 189 | 190 | if (tagAttribute.titleSize <= 0) { 191 | tagAttribute = [[HXTagAttribute alloc] init]; 192 | } 193 | 194 | //cell的高度 = 顶部 + 高度 195 | contentHeight = layout.sectionInset.top + layout.itemSize.height; 196 | 197 | CGFloat originX = layout.sectionInset.left; 198 | CGFloat originY = layout.sectionInset.top; 199 | 200 | NSInteger itemCount = tags.count; 201 | 202 | for (NSInteger i = 0; i < itemCount; i++) { 203 | CGSize maxSize = CGSizeMake(width - layout.sectionInset.left - layout.sectionInset.right, layout.itemSize.height); 204 | 205 | CGRect frame = [tags[i] boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:tagAttribute.titleSize]} context:nil]; 206 | 207 | CGSize itemSize = CGSizeMake(frame.size.width + tagAttribute.tagSpace, layout.itemSize.height); 208 | 209 | if (layout.scrollDirection == UICollectionViewScrollDirectionVertical) { 210 | //垂直滚动 211 | //当前CollectionViewCell的起点 + 当前CollectionViewCell的宽度 + 当前CollectionView距离右侧的间隔 > collectionView的宽度 212 | if ((originX + itemSize.width + layout.sectionInset.right) > width) { 213 | originX = layout.sectionInset.left; 214 | originY += itemSize.height + layout.minimumLineSpacing; 215 | 216 | contentHeight += itemSize.height + layout.minimumLineSpacing; 217 | } 218 | } 219 | 220 | originX += itemSize.width + layout.minimumInteritemSpacing; 221 | } 222 | 223 | contentHeight += layout.sectionInset.bottom; 224 | return contentHeight; 225 | } 226 | 227 | @end 228 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HXTagsView 如果对你有一点点帮助,请给一颗★,你的支持是对我的最大鼓励!推荐工具 iOS打包机器人 https://github.com/huangxuan518/HXPackRobot 2 | HXTagsView是一款支持自动布局的标签tag 3 | 4 | 特性: 5 | 6 | -流式展示标签 7 | 8 | -可以配置标签的字体大小、颜色、边框颜色、边框弧度大小、边框的宽度、高度、间隔、外边距、标签内部左右间距等 9 | 10 | -支持单行 多行滚动显示 多行不滚动显示 11 | 12 | -支持多选操作,控制字段isMultiSelect 13 | 14 | -支持cell,高度计算方法+ (CGFloat)getCellHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width; 15 | 16 | -支持搜索关键词标签加亮以及关键词颜色自定义,设置key字段的值即可 17 | 18 | -标签样式更改tagAttribute,tagSpace是标签内部左右间隔和,还有titleSize,这2个参数影响到计算 19 | 20 | -标签布局计算属性更改layout,即更改HXTagCollectionViewFlowLayout的属性,包括.scrollDirection .itemSize .minimumInteritemSpacing .minimumLineSpacing .sectionInset等属性,用法同UICollectionViewFlowLayout; 21 | 22 | # 效果展示 23 | 24 | 25 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/xiaoguo.gif) 26 | # 适用 27 | 本标签类适用于标签长度不确定等动态计算的标签显示需求 28 | 29 | # View上使用HXTagsView示例 30 | 31 | //单行不滚动 === 32 | NSArray *tagAry = @[@"英雄联盟",@"穿越火线",@"地下城与勇士"]; 33 | 34 | 35 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 52)]; 36 | tagsView.tags = tagAry; 37 | [self.view addSubview:tagsView]; 38 | 39 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/danhangbugundongxiaoguo.gif) 40 | 41 | //单行滚动 === 42 | NSArray *tagAry = @[@"魔兽世界",@"梦幻西游",@"qq飞车",@"传奇",@"逆战",@"炉石传说",@"剑灵",@"qq炫舞",@"dota2",@"300英雄",@"笑傲江湖ol",@"剑网3",@"坦克世界",@"神武",@"龙之谷"]; 43 | 44 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 52)]; 45 | tagsView.tags = tagAry; 46 | [self.view addSubview:tagsView]; 47 | 48 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/danhanggundongxiaoguo.gif) 49 | 50 | //多行不滚动单选 === 51 | NSArray *tagAry = @[@"冒险岛",@"反恐精英ol",@"魔域",@"诛仙",@"火影ol",@"问道",@"天龙八部",@"枪神纪",@"英魂之刃",@"勇者大冒险",@"nba 2k",@"上古世纪",@"跑跑卡丁车",@"传奇世界",@"劲舞团",@"激战2"]; 52 | 53 | //高度需要计算出来 54 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 52)]; 55 | tagsView.tags = tagAry; 56 | tagsView.layout.scrollDirection = UICollectionViewScrollDirectionVertical; 57 | [self.view addSubview:tagsView]; 58 | 59 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/duohangpingpudan1xiaoguo.gif) 60 | 61 | //多行滚动单选 === 62 | NSArray *tagAry = @[@"蜀山ol",@"天下3",@"大话西游2",@"热血江湖",@"游戏人生",@"梦三国",@"流星蝴蝶剑",@"九阴真经",@"斗战神",@"奇迹mu",@"最终幻想14",@"宠物小精灵",@"天龙八部3",@"qq三国",@"倩女幽魂ol",@"御龙在天"]; 63 | 64 | float height = [HXTagsCell getCellHeightWithTags:self.tags layout:self.layout tagAttribute:nil width:tableView.frame.size.width]; 65 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, height)]; 66 | tagsView.tags = tagAry; 67 | tagsView.layout.scrollDirection = UICollectionViewScrollDirectionVertical; 68 | tagsView.layout.isMultiLineRoll = YES; 69 | [self.view addSubview:tagsView]; 70 | 71 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/duohanggundongxiaoguo.gif) 72 | 73 | //多行不滚动多选 74 | NSArray *tagAry = @[@"冒险岛游戏",@"反恐精英ol游戏",@"游戏魔域",@"诛游戏仙",@"火游戏影ol游戏",@"问游戏道",@"天游戏龙游戏八游戏部",@"枪神纪游戏",@"英魂之游戏刃",@"勇者游戏大冒险",@"nba 游戏2k",@"上古世纪游戏",@"游戏跑跑卡游戏丁车",@"传奇世界游戏",@"劲舞游戏团",@"激游戏战2"]; 75 | 76 | //高度需要计算出来 77 | float height = [HXTagsCell getCellHeightWithTags:self.tags layout:self.layout tagAttribute:nil width:tableView.frame.size.width]; 78 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, height)]; 79 | tagsView.tags = tagAry; 80 | tagsView.layout.scrollDirection = UICollectionViewScrollDirectionVertical; 81 | tagsView.isMultiSelect = YES; 82 | [self.view addSubview:tagsView]; 83 | 84 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/duohangpingpudanxiaoguo.gif) 85 | 86 | //多行不滚动有关键字多选 87 | NSArray *tagAry = @[@"冒险岛游戏",@"反恐精英ol游戏",@"游戏魔域",@"诛游戏仙",@"火游戏影ol游戏",@"问游戏道",@"天游戏龙游戏八游戏部",@"枪神纪游戏",@"英魂之游戏刃",@"勇者游戏大冒险",@"nba 游戏2k",@"上古世纪游戏",@"游戏跑跑卡游戏丁车",@"传奇世界游戏",@"劲舞游戏团",@"激游戏战2"]; 88 | 89 | //高度需要计算出来 90 | float height = [HXTagsCell getCellHeightWithTags:self.tags layout:self.layout tagAttribute:nil width:tableView.frame.size.width]; 91 | HXTagsView *tagsView = [[HXTagsView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, height)]; 92 | tagsView.tags = tagAry; 93 | tagsView.layout.scrollDirection = UICollectionViewScrollDirectionVertical; 94 | tagsView.isMultiSelect = YES; 95 | tagsView.key = @"游戏"; 96 | [self.view addSubview:tagsView]; 97 | 98 | ![image](https://github.com/huangxuan518/HXTagsView/blob/master/HXTagsView/duohangpingpuxiaoguo.gif) 99 | 100 | # UITableView上使用HXTagsCell示例 101 | 102 | #import "HXTagTableViewController.h" 103 | #import "HXTagsCell.h" 104 | 105 | @interface HXTagTableViewController () 106 | 107 | @property (nonatomic,strong) HXTagCollectionViewFlowLayout *layout;//布局layout 108 | @property (nonatomic,strong) NSArray *selectTags; 109 | 110 | @end 111 | 112 | @implementation HXTagTableViewController 113 | 114 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 115 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 116 | if (self) { 117 | 118 | } 119 | return self; 120 | } 121 | 122 | - (HXTagCollectionViewFlowLayout *)layout { 123 | if (!_layout) { 124 | _layout = [HXTagCollectionViewFlowLayout new]; 125 | _layout.scrollDirection = UICollectionViewScrollDirectionVertical; 126 | } 127 | return _layout; 128 | } 129 | 130 | - (NSArray *)tags { 131 | return @[@"火游戏影ol游戏",@"问游戏道",@"天游戏龙游戏八游戏部",@"枪神纪游戏",@"英魂之游戏刃",@"勇者游戏大冒险",@"nba 游戏2k",@"上古世纪游戏",@"游戏跑跑卡游戏丁车",@"传奇世界游戏",@"劲舞游戏团",@"激游戏战2",@"蜀山ol",@"天下3",@"大话西游2",@"热血江湖",@"游戏人生",@"梦三国",@"流星蝴蝶剑",@"九阴真经",@"斗战神",@"奇迹mu",@"最终幻想14",@"宠物小精灵"]; 132 | } 133 | 134 | - (void)viewDidLoad { 135 | [super viewDidLoad]; 136 | 137 | // Uncomment the following line to preserve selection between presentations. 138 | 139 | [self.tableView registerClass:HXTagsCell.class forCellReuseIdentifier:@"cellId"]; 140 | } 141 | 142 | #pragma mark UITableViewDataSource/UITableViewDelegate 143 | 144 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 145 | return 1; 146 | } 147 | 148 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 149 | 150 | HXTagsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellId"]; 151 | if (!cell) { 152 | cell = [[HXTagsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellId"]; 153 | } 154 | 155 | cell.tags = self.tags; 156 | cell.selectedTags = [NSMutableArray arrayWithArray:_selectTags]; 157 | cell.layout = self.layout; 158 | cell.completion = ^(NSArray *selectTags,NSInteger currentIndex) { 159 | _selectTags = selectTags; 160 | }; 161 | [cell reloadData]; 162 | 163 | return cell; 164 | } 165 | 166 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 167 | float height = [HXTagsCell getCellHeightWithTags:self.tags layout:self.layout tagAttribute:nil width:tableView.frame.size.width]; 168 | return height; 169 | } 170 | 171 | - (void)didReceiveMemoryWarning { 172 | [super didReceiveMemoryWarning]; 173 | // Dispose of any resources that can be recreated. 174 | } 175 | 176 | @end 177 | 178 | 179 | #高度计算方法 180 | 181 | //View高度 182 | + (CGFloat)getHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width; 183 | //cell高度 184 | + (CGFloat)getCellHeightWithTags:(NSArray *)tags layout:(HXTagCollectionViewFlowLayout *)layout tagAttribute:(HXTagAttribute *)tagAttribute width:(CGFloat)width; 185 | 186 | # 选择回调方法 187 | 188 | self.tagsView.completion = ^(NSArray *selectTags,NSInteger currentIndex) { 189 | 190 | }; 191 | 192 | # 刷新方法 193 | 194 | - (void)reloadData; 195 | 196 | # 说明 197 | 1.当多行模式下,自定义高度小于计算出的高度时则滚动,大于或者等于计算出的高度时则不滚动 198 | 2.用高度计算方法,因为涉及到很多参数,所以如果需要计算,请设置layout,默认可以不设置,则是默认参数 199 | 200 | 更改参数后,请执行reloadData 201 | --------------------------------------------------------------------------------