├── README.md ├── Sceenshots └── screenshot1.gif ├── TagDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── TagDemo.xccheckout │ └── xcuserdata │ │ └── alienjunx.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── alienjunx.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── TagDemo.xcscheme │ └── xcschememanagement.plist ├── TagDemo ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── BoCollectionSectionBgLayout │ ├── AJSectionBackgroundLayout.h │ ├── AJSectionBackgroundLayout.m │ ├── AJSectionBackgroundView.h │ ├── AJSectionBackgroundView.m │ ├── AJTagModel.h │ ├── AJTagModel.m │ ├── AJTagsCell.h │ ├── AJTagsCell.m │ ├── AJTagsView.h │ └── AJTagsView.m ├── ExampleViewController.h ├── ExampleViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── TagCell.h ├── TagCell.m ├── TagModel.h ├── TagModel.m ├── ViewController.h ├── ViewController.m └── main.m └── TagDemoTests ├── Info.plist └── TagDemoTests.m /README.md: -------------------------------------------------------------------------------- 1 | # MyTags 2 | 用于表现修改个人标签,使用UICollectionView实现,动态背景框使用UICollectionViewFlowLayout的DecorationView实现。 3 | 4 | 5 | ![Aaron Swartz](https://github.com/alienjun/MyTags/blob/master/Sceenshots/screenshot1.gif) 6 | 7 | 8 | 9 | 1.其中利用UICollectionView的特性,实现了标签插回原位的效果。 10 | 11 | 12 | 2.为了能利用UICollectionView动画特性,未选中和选中的标签在同一个UICollectionView中表现;这里会导致背景框跟随标签高度变化成了难点,好在UICollectionViewFlowLayout 提供了一个DecorationView 解决了此问题。 13 | 14 | 欢迎一起交流技术学习。 15 | 16 | 微博:[AlienJunX](http://weibo.com/alienjunx) 17 | 18 | 特别感谢: 19 | 20 | 21 | 22 | 23 | 还有一个可以给任何View添加类似nice 应用中的那种标签。
24 | ![Aaron Swartz](https://github.com/alienjun/AJTagView/blob/master/Screenshots/screenshot1.gif) 25 | 26 | 戳链接——> [https://github.com/alienjun/AJTagView](https://github.com/alienjun/AJTagView) 27 | -------------------------------------------------------------------------------- /Sceenshots/screenshot1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alienjun/AJMyTags/13fe8a4b0fefab091ff026b9689752c7cad28aba/Sceenshots/screenshot1.gif -------------------------------------------------------------------------------- /TagDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FB0713061C919AC200B86FC2 /* AJTagsView.m in Sources */ = {isa = PBXBuildFile; fileRef = FB0713051C919AC200B86FC2 /* AJTagsView.m */; }; 11 | FB0713091C919AD400B86FC2 /* AJTagsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FB0713081C919AD400B86FC2 /* AJTagsCell.m */; }; 12 | FB07130C1C919D0800B86FC2 /* AJTagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FB07130B1C919D0800B86FC2 /* AJTagModel.m */; }; 13 | FB07130F1C91A2AA00B86FC2 /* ExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB07130E1C91A2AA00B86FC2 /* ExampleViewController.m */; }; 14 | FB47166B1BA0028B0021DE7B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FB47166A1BA0028B0021DE7B /* main.m */; }; 15 | FB47166E1BA0028B0021DE7B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FB47166D1BA0028B0021DE7B /* AppDelegate.m */; }; 16 | FB4716711BA0028B0021DE7B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4716701BA0028B0021DE7B /* ViewController.m */; }; 17 | FB4716741BA0028B0021DE7B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB4716721BA0028B0021DE7B /* Main.storyboard */; }; 18 | FB4716761BA0028B0021DE7B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FB4716751BA0028B0021DE7B /* Images.xcassets */; }; 19 | FB4716791BA0028B0021DE7B /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = FB4716771BA0028B0021DE7B /* LaunchScreen.xib */; }; 20 | FB4716851BA0028B0021DE7B /* TagDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4716841BA0028B0021DE7B /* TagDemoTests.m */; }; 21 | FB471B201BA015190021DE7B /* AJSectionBackgroundLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = FB471B1D1BA015190021DE7B /* AJSectionBackgroundLayout.m */; }; 22 | FB471B211BA015190021DE7B /* AJSectionBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = FB471B1F1BA015190021DE7B /* AJSectionBackgroundView.m */; }; 23 | FB471B241BA01D6C0021DE7B /* TagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = FB471B231BA01D6C0021DE7B /* TagModel.m */; }; 24 | FB471B271BA01DA10021DE7B /* TagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FB471B261BA01DA10021DE7B /* TagCell.m */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | FB47167F1BA0028B0021DE7B /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = FB47165D1BA0028B0021DE7B /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = FB4716641BA0028B0021DE7B; 33 | remoteInfo = TagDemo; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | FB0713041C919AC200B86FC2 /* AJTagsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AJTagsView.h; sourceTree = ""; }; 39 | FB0713051C919AC200B86FC2 /* AJTagsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AJTagsView.m; sourceTree = ""; }; 40 | FB0713071C919AD400B86FC2 /* AJTagsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AJTagsCell.h; sourceTree = ""; }; 41 | FB0713081C919AD400B86FC2 /* AJTagsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AJTagsCell.m; sourceTree = ""; }; 42 | FB07130A1C919D0800B86FC2 /* AJTagModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AJTagModel.h; sourceTree = ""; }; 43 | FB07130B1C919D0800B86FC2 /* AJTagModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AJTagModel.m; sourceTree = ""; }; 44 | FB07130D1C91A2AA00B86FC2 /* ExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleViewController.h; sourceTree = ""; }; 45 | FB07130E1C91A2AA00B86FC2 /* ExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleViewController.m; sourceTree = ""; }; 46 | FB4716651BA0028B0021DE7B /* TagDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TagDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | FB4716691BA0028B0021DE7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | FB47166A1BA0028B0021DE7B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | FB47166C1BA0028B0021DE7B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | FB47166D1BA0028B0021DE7B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | FB47166F1BA0028B0021DE7B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 52 | FB4716701BA0028B0021DE7B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 53 | FB4716731BA0028B0021DE7B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | FB4716751BA0028B0021DE7B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 55 | FB4716781BA0028B0021DE7B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 56 | FB47167E1BA0028B0021DE7B /* TagDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TagDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | FB4716831BA0028B0021DE7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | FB4716841BA0028B0021DE7B /* TagDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TagDemoTests.m; sourceTree = ""; }; 59 | FB471B1C1BA015190021DE7B /* AJSectionBackgroundLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AJSectionBackgroundLayout.h; sourceTree = ""; }; 60 | FB471B1D1BA015190021DE7B /* AJSectionBackgroundLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AJSectionBackgroundLayout.m; sourceTree = ""; }; 61 | FB471B1E1BA015190021DE7B /* AJSectionBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AJSectionBackgroundView.h; sourceTree = ""; }; 62 | FB471B1F1BA015190021DE7B /* AJSectionBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AJSectionBackgroundView.m; sourceTree = ""; }; 63 | FB471B221BA01D6C0021DE7B /* TagModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagModel.h; sourceTree = ""; }; 64 | FB471B231BA01D6C0021DE7B /* TagModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TagModel.m; sourceTree = ""; }; 65 | FB471B251BA01DA10021DE7B /* TagCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagCell.h; sourceTree = ""; }; 66 | FB471B261BA01DA10021DE7B /* TagCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TagCell.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | FB4716621BA0028B0021DE7B /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | FB47167B1BA0028B0021DE7B /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | FB47165C1BA0028B0021DE7B = { 88 | isa = PBXGroup; 89 | children = ( 90 | FB4716671BA0028B0021DE7B /* TagDemo */, 91 | FB4716811BA0028B0021DE7B /* TagDemoTests */, 92 | FB4716661BA0028B0021DE7B /* Products */, 93 | ); 94 | sourceTree = ""; 95 | }; 96 | FB4716661BA0028B0021DE7B /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | FB4716651BA0028B0021DE7B /* TagDemo.app */, 100 | FB47167E1BA0028B0021DE7B /* TagDemoTests.xctest */, 101 | ); 102 | name = Products; 103 | sourceTree = ""; 104 | }; 105 | FB4716671BA0028B0021DE7B /* TagDemo */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | FB471B1B1BA015190021DE7B /* AJTags */, 109 | FB471B251BA01DA10021DE7B /* TagCell.h */, 110 | FB471B261BA01DA10021DE7B /* TagCell.m */, 111 | FB471B221BA01D6C0021DE7B /* TagModel.h */, 112 | FB471B231BA01D6C0021DE7B /* TagModel.m */, 113 | FB47166F1BA0028B0021DE7B /* ViewController.h */, 114 | FB4716701BA0028B0021DE7B /* ViewController.m */, 115 | FB4716721BA0028B0021DE7B /* Main.storyboard */, 116 | FB4716751BA0028B0021DE7B /* Images.xcassets */, 117 | FB4716771BA0028B0021DE7B /* LaunchScreen.xib */, 118 | FB4716681BA0028B0021DE7B /* Supporting Files */, 119 | FB47166C1BA0028B0021DE7B /* AppDelegate.h */, 120 | FB47166D1BA0028B0021DE7B /* AppDelegate.m */, 121 | FB07130D1C91A2AA00B86FC2 /* ExampleViewController.h */, 122 | FB07130E1C91A2AA00B86FC2 /* ExampleViewController.m */, 123 | ); 124 | path = TagDemo; 125 | sourceTree = ""; 126 | }; 127 | FB4716681BA0028B0021DE7B /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | FB4716691BA0028B0021DE7B /* Info.plist */, 131 | FB47166A1BA0028B0021DE7B /* main.m */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | FB4716811BA0028B0021DE7B /* TagDemoTests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | FB4716841BA0028B0021DE7B /* TagDemoTests.m */, 140 | FB4716821BA0028B0021DE7B /* Supporting Files */, 141 | ); 142 | path = TagDemoTests; 143 | sourceTree = ""; 144 | }; 145 | FB4716821BA0028B0021DE7B /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | FB4716831BA0028B0021DE7B /* Info.plist */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | FB471B1B1BA015190021DE7B /* AJTags */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | FB471B1C1BA015190021DE7B /* AJSectionBackgroundLayout.h */, 157 | FB471B1D1BA015190021DE7B /* AJSectionBackgroundLayout.m */, 158 | FB471B1E1BA015190021DE7B /* AJSectionBackgroundView.h */, 159 | FB471B1F1BA015190021DE7B /* AJSectionBackgroundView.m */, 160 | FB0713041C919AC200B86FC2 /* AJTagsView.h */, 161 | FB0713051C919AC200B86FC2 /* AJTagsView.m */, 162 | FB0713071C919AD400B86FC2 /* AJTagsCell.h */, 163 | FB0713081C919AD400B86FC2 /* AJTagsCell.m */, 164 | FB07130A1C919D0800B86FC2 /* AJTagModel.h */, 165 | FB07130B1C919D0800B86FC2 /* AJTagModel.m */, 166 | ); 167 | name = AJTags; 168 | path = BoCollectionSectionBgLayout; 169 | sourceTree = ""; 170 | }; 171 | /* End PBXGroup section */ 172 | 173 | /* Begin PBXNativeTarget section */ 174 | FB4716641BA0028B0021DE7B /* TagDemo */ = { 175 | isa = PBXNativeTarget; 176 | buildConfigurationList = FB4716881BA0028B0021DE7B /* Build configuration list for PBXNativeTarget "TagDemo" */; 177 | buildPhases = ( 178 | FB4716611BA0028B0021DE7B /* Sources */, 179 | FB4716621BA0028B0021DE7B /* Frameworks */, 180 | FB4716631BA0028B0021DE7B /* Resources */, 181 | ); 182 | buildRules = ( 183 | ); 184 | dependencies = ( 185 | ); 186 | name = TagDemo; 187 | productName = TagDemo; 188 | productReference = FB4716651BA0028B0021DE7B /* TagDemo.app */; 189 | productType = "com.apple.product-type.application"; 190 | }; 191 | FB47167D1BA0028B0021DE7B /* TagDemoTests */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = FB47168B1BA0028B0021DE7B /* Build configuration list for PBXNativeTarget "TagDemoTests" */; 194 | buildPhases = ( 195 | FB47167A1BA0028B0021DE7B /* Sources */, 196 | FB47167B1BA0028B0021DE7B /* Frameworks */, 197 | FB47167C1BA0028B0021DE7B /* Resources */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | FB4716801BA0028B0021DE7B /* PBXTargetDependency */, 203 | ); 204 | name = TagDemoTests; 205 | productName = TagDemoTests; 206 | productReference = FB47167E1BA0028B0021DE7B /* TagDemoTests.xctest */; 207 | productType = "com.apple.product-type.bundle.unit-test"; 208 | }; 209 | /* End PBXNativeTarget section */ 210 | 211 | /* Begin PBXProject section */ 212 | FB47165D1BA0028B0021DE7B /* Project object */ = { 213 | isa = PBXProject; 214 | attributes = { 215 | LastUpgradeCheck = 0640; 216 | ORGANIZATIONNAME = com.alienjun.demo; 217 | TargetAttributes = { 218 | FB4716641BA0028B0021DE7B = { 219 | CreatedOnToolsVersion = 6.4; 220 | }; 221 | FB47167D1BA0028B0021DE7B = { 222 | CreatedOnToolsVersion = 6.4; 223 | TestTargetID = FB4716641BA0028B0021DE7B; 224 | }; 225 | }; 226 | }; 227 | buildConfigurationList = FB4716601BA0028B0021DE7B /* Build configuration list for PBXProject "TagDemo" */; 228 | compatibilityVersion = "Xcode 3.2"; 229 | developmentRegion = English; 230 | hasScannedForEncodings = 0; 231 | knownRegions = ( 232 | en, 233 | Base, 234 | ); 235 | mainGroup = FB47165C1BA0028B0021DE7B; 236 | productRefGroup = FB4716661BA0028B0021DE7B /* Products */; 237 | projectDirPath = ""; 238 | projectRoot = ""; 239 | targets = ( 240 | FB4716641BA0028B0021DE7B /* TagDemo */, 241 | FB47167D1BA0028B0021DE7B /* TagDemoTests */, 242 | ); 243 | }; 244 | /* End PBXProject section */ 245 | 246 | /* Begin PBXResourcesBuildPhase section */ 247 | FB4716631BA0028B0021DE7B /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | FB4716741BA0028B0021DE7B /* Main.storyboard in Resources */, 252 | FB4716791BA0028B0021DE7B /* LaunchScreen.xib in Resources */, 253 | FB4716761BA0028B0021DE7B /* Images.xcassets in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | FB47167C1BA0028B0021DE7B /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXResourcesBuildPhase section */ 265 | 266 | /* Begin PBXSourcesBuildPhase section */ 267 | FB4716611BA0028B0021DE7B /* Sources */ = { 268 | isa = PBXSourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | FB471B241BA01D6C0021DE7B /* TagModel.m in Sources */, 272 | FB07130F1C91A2AA00B86FC2 /* ExampleViewController.m in Sources */, 273 | FB0713091C919AD400B86FC2 /* AJTagsCell.m in Sources */, 274 | FB4716711BA0028B0021DE7B /* ViewController.m in Sources */, 275 | FB47166E1BA0028B0021DE7B /* AppDelegate.m in Sources */, 276 | FB471B201BA015190021DE7B /* AJSectionBackgroundLayout.m in Sources */, 277 | FB07130C1C919D0800B86FC2 /* AJTagModel.m in Sources */, 278 | FB0713061C919AC200B86FC2 /* AJTagsView.m in Sources */, 279 | FB471B271BA01DA10021DE7B /* TagCell.m in Sources */, 280 | FB47166B1BA0028B0021DE7B /* main.m in Sources */, 281 | FB471B211BA015190021DE7B /* AJSectionBackgroundView.m in Sources */, 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | FB47167A1BA0028B0021DE7B /* Sources */ = { 286 | isa = PBXSourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | FB4716851BA0028B0021DE7B /* TagDemoTests.m in Sources */, 290 | ); 291 | runOnlyForDeploymentPostprocessing = 0; 292 | }; 293 | /* End PBXSourcesBuildPhase section */ 294 | 295 | /* Begin PBXTargetDependency section */ 296 | FB4716801BA0028B0021DE7B /* PBXTargetDependency */ = { 297 | isa = PBXTargetDependency; 298 | target = FB4716641BA0028B0021DE7B /* TagDemo */; 299 | targetProxy = FB47167F1BA0028B0021DE7B /* PBXContainerItemProxy */; 300 | }; 301 | /* End PBXTargetDependency section */ 302 | 303 | /* Begin PBXVariantGroup section */ 304 | FB4716721BA0028B0021DE7B /* Main.storyboard */ = { 305 | isa = PBXVariantGroup; 306 | children = ( 307 | FB4716731BA0028B0021DE7B /* Base */, 308 | ); 309 | name = Main.storyboard; 310 | sourceTree = ""; 311 | }; 312 | FB4716771BA0028B0021DE7B /* LaunchScreen.xib */ = { 313 | isa = PBXVariantGroup; 314 | children = ( 315 | FB4716781BA0028B0021DE7B /* Base */, 316 | ); 317 | name = LaunchScreen.xib; 318 | sourceTree = ""; 319 | }; 320 | /* End PBXVariantGroup section */ 321 | 322 | /* Begin XCBuildConfiguration section */ 323 | FB4716861BA0028B0021DE7B /* Debug */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 328 | CLANG_CXX_LIBRARY = "libc++"; 329 | CLANG_ENABLE_MODULES = YES; 330 | CLANG_ENABLE_OBJC_ARC = YES; 331 | CLANG_WARN_BOOL_CONVERSION = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 334 | CLANG_WARN_EMPTY_BODY = YES; 335 | CLANG_WARN_ENUM_CONVERSION = YES; 336 | CLANG_WARN_INT_CONVERSION = YES; 337 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 338 | CLANG_WARN_UNREACHABLE_CODE = YES; 339 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 340 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 341 | COPY_PHASE_STRIP = NO; 342 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 343 | ENABLE_STRICT_OBJC_MSGSEND = YES; 344 | GCC_C_LANGUAGE_STANDARD = gnu99; 345 | GCC_DYNAMIC_NO_PIC = NO; 346 | GCC_NO_COMMON_BLOCKS = YES; 347 | GCC_OPTIMIZATION_LEVEL = 0; 348 | GCC_PREPROCESSOR_DEFINITIONS = ( 349 | "DEBUG=1", 350 | "$(inherited)", 351 | ); 352 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 353 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 354 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 355 | GCC_WARN_UNDECLARED_SELECTOR = YES; 356 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 357 | GCC_WARN_UNUSED_FUNCTION = YES; 358 | GCC_WARN_UNUSED_VARIABLE = YES; 359 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 360 | MTL_ENABLE_DEBUG_INFO = YES; 361 | ONLY_ACTIVE_ARCH = YES; 362 | SDKROOT = iphoneos; 363 | }; 364 | name = Debug; 365 | }; 366 | FB4716871BA0028B0021DE7B /* Release */ = { 367 | isa = XCBuildConfiguration; 368 | buildSettings = { 369 | ALWAYS_SEARCH_USER_PATHS = NO; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BOOL_CONVERSION = YES; 375 | CLANG_WARN_CONSTANT_CONVERSION = YES; 376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 377 | CLANG_WARN_EMPTY_BODY = YES; 378 | CLANG_WARN_ENUM_CONVERSION = YES; 379 | CLANG_WARN_INT_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_UNREACHABLE_CODE = YES; 382 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 383 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 384 | COPY_PHASE_STRIP = NO; 385 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 386 | ENABLE_NS_ASSERTIONS = NO; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | GCC_C_LANGUAGE_STANDARD = gnu99; 389 | GCC_NO_COMMON_BLOCKS = YES; 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNUSED_FUNCTION = YES; 395 | GCC_WARN_UNUSED_VARIABLE = YES; 396 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 397 | MTL_ENABLE_DEBUG_INFO = NO; 398 | SDKROOT = iphoneos; 399 | VALIDATE_PRODUCT = YES; 400 | }; 401 | name = Release; 402 | }; 403 | FB4716891BA0028B0021DE7B /* Debug */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 407 | INFOPLIST_FILE = TagDemo/Info.plist; 408 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 410 | PRODUCT_NAME = "$(TARGET_NAME)"; 411 | }; 412 | name = Debug; 413 | }; 414 | FB47168A1BA0028B0021DE7B /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 418 | INFOPLIST_FILE = TagDemo/Info.plist; 419 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 421 | PRODUCT_NAME = "$(TARGET_NAME)"; 422 | }; 423 | name = Release; 424 | }; 425 | FB47168C1BA0028B0021DE7B /* Debug */ = { 426 | isa = XCBuildConfiguration; 427 | buildSettings = { 428 | BUNDLE_LOADER = "$(TEST_HOST)"; 429 | FRAMEWORK_SEARCH_PATHS = ( 430 | "$(SDKROOT)/Developer/Library/Frameworks", 431 | "$(inherited)", 432 | ); 433 | GCC_PREPROCESSOR_DEFINITIONS = ( 434 | "DEBUG=1", 435 | "$(inherited)", 436 | ); 437 | INFOPLIST_FILE = TagDemoTests/Info.plist; 438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 439 | PRODUCT_NAME = "$(TARGET_NAME)"; 440 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TagDemo.app/TagDemo"; 441 | }; 442 | name = Debug; 443 | }; 444 | FB47168D1BA0028B0021DE7B /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | BUNDLE_LOADER = "$(TEST_HOST)"; 448 | FRAMEWORK_SEARCH_PATHS = ( 449 | "$(SDKROOT)/Developer/Library/Frameworks", 450 | "$(inherited)", 451 | ); 452 | INFOPLIST_FILE = TagDemoTests/Info.plist; 453 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 454 | PRODUCT_NAME = "$(TARGET_NAME)"; 455 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TagDemo.app/TagDemo"; 456 | }; 457 | name = Release; 458 | }; 459 | /* End XCBuildConfiguration section */ 460 | 461 | /* Begin XCConfigurationList section */ 462 | FB4716601BA0028B0021DE7B /* Build configuration list for PBXProject "TagDemo" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | FB4716861BA0028B0021DE7B /* Debug */, 466 | FB4716871BA0028B0021DE7B /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | FB4716881BA0028B0021DE7B /* Build configuration list for PBXNativeTarget "TagDemo" */ = { 472 | isa = XCConfigurationList; 473 | buildConfigurations = ( 474 | FB4716891BA0028B0021DE7B /* Debug */, 475 | FB47168A1BA0028B0021DE7B /* Release */, 476 | ); 477 | defaultConfigurationIsVisible = 0; 478 | defaultConfigurationName = Release; 479 | }; 480 | FB47168B1BA0028B0021DE7B /* Build configuration list for PBXNativeTarget "TagDemoTests" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | FB47168C1BA0028B0021DE7B /* Debug */, 484 | FB47168D1BA0028B0021DE7B /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | /* End XCConfigurationList section */ 490 | }; 491 | rootObject = FB47165D1BA0028B0021DE7B /* Project object */; 492 | } 493 | -------------------------------------------------------------------------------- /TagDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TagDemo.xcodeproj/project.xcworkspace/xcshareddata/TagDemo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4394A108-4C46-4012-8341-E8EF85CCA151 9 | IDESourceControlProjectName 10 | TagDemo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 14E73774343E00F7D2B90D6CA6F5E7950826E723 14 | github.com:alienjun/MyTags.git 15 | 16 | IDESourceControlProjectPath 17 | TagDemo.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 14E73774343E00F7D2B90D6CA6F5E7950826E723 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:alienjun/MyTags.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 14E73774343E00F7D2B90D6CA6F5E7950826E723 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 14E73774343E00F7D2B90D6CA6F5E7950826E723 36 | IDESourceControlWCCName 37 | MyTags 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TagDemo.xcodeproj/project.xcworkspace/xcuserdata/alienjunx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alienjun/AJMyTags/13fe8a4b0fefab091ff026b9689752c7cad28aba/TagDemo.xcodeproj/project.xcworkspace/xcuserdata/alienjunx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TagDemo.xcodeproj/xcuserdata/alienjunx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /TagDemo.xcodeproj/xcuserdata/alienjunx.xcuserdatad/xcschemes/TagDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /TagDemo.xcodeproj/xcuserdata/alienjunx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TagDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FB4716641BA0028B0021DE7B 16 | 17 | primary 18 | 19 | 20 | FB47167D1BA0028B0021DE7B 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TagDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. 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 | -------------------------------------------------------------------------------- /TagDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /TagDemo/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TagDemo/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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJSectionBackgroundLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJSectionBackgroundLayout.h 3 | // AJTags 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015 AlienJunX 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | @interface AJSectionBackgroundLayout : UICollectionViewFlowLayout 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJSectionBackgroundLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJSectionBackgroundLayout.m 3 | // AJTags 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015 AlienJunX 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "AJSectionBackgroundLayout.h" 13 | #import "AJSectionBackgroundView.h" 14 | 15 | //没有内容时默认高度 16 | CGFloat defaultHeight = 98.0f; 17 | //elementKind 18 | NSString *decorationViewOfKind = @"decorationBgView"; 19 | 20 | @interface AJSectionBackgroundLayout() 21 | @property (strong, nonatomic) NSMutableArray *itemAttributes; 22 | @end 23 | 24 | @implementation AJSectionBackgroundLayout 25 | 26 | - (void)prepareLayout { 27 | [super prepareLayout]; 28 | 29 | self.itemAttributes = [NSMutableArray new]; 30 | NSInteger numberOfSection = self.collectionView.numberOfSections; 31 | for (int section = 0; section < numberOfSection; section++) { 32 | NSInteger lastIndex = [self.collectionView numberOfItemsInSection:section] - 1; 33 | CGRect frame = CGRectZero; 34 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewOfKind withIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]]; 35 | attributes.zIndex = -1; 36 | if (lastIndex < 0) { 37 | frame = CGRectMake(0, 0, self.collectionView.frame.size.width, 36); 38 | if (section == 1) { 39 | UICollectionViewLayoutAttributes *headerView = [self.collectionView.collectionViewLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]]; 40 | frame = CGRectMake(0, CGRectGetMaxY(headerView.frame), self.collectionView.frame.size.width, defaultHeight); 41 | } 42 | } else { 43 | UICollectionViewLayoutAttributes *firstItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]]; 44 | UICollectionViewLayoutAttributes *lastItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:lastIndex inSection:section]]; 45 | 46 | frame = CGRectUnion(firstItem.frame, lastItem.frame); 47 | frame.origin.x -= self.sectionInset.left; 48 | frame.origin.y -= self.sectionInset.top; 49 | frame.size.width = self.collectionView.frame.size.width; 50 | frame.size.height += self.sectionInset.top + self.sectionInset.bottom; 51 | if (section == 1) { 52 | //保持默认高度 53 | frame.size.height = frame.size.height < defaultHeight ? defaultHeight:frame.size.height; 54 | } 55 | } 56 | 57 | attributes.frame = frame; 58 | [self.itemAttributes addObject:attributes]; 59 | [self registerClass:[AJSectionBackgroundView class] forDecorationViewOfKind:decorationViewOfKind]; 60 | } 61 | } 62 | 63 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 64 | NSMutableArray *attributes = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]]; 65 | //使cell紧随前一个 66 | for (int i = 1; i < [attributes count]; ++i) { 67 | //当前attributes 68 | UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i]; 69 | //上一个attributes 70 | UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1]; 71 | //间距 72 | NSInteger maximumSpacing = 5; 73 | //前一个cell的最右边 74 | NSInteger prevOrigin = CGRectGetMaxX(prevLayoutAttributes.frame); 75 | //需要做偏移 76 | if ((prevOrigin + maximumSpacing + currentLayoutAttributes.frame.size.width <= self.collectionViewContentSize.width - self.sectionInset.right) && currentLayoutAttributes.indexPath.section == prevLayoutAttributes.indexPath.section) { 77 | CGRect frame = currentLayoutAttributes.frame; 78 | frame.origin.x = prevOrigin + maximumSpacing; 79 | currentLayoutAttributes.frame = frame; 80 | } 81 | } 82 | 83 | for (UICollectionViewLayoutAttributes *attribute in self.itemAttributes){ 84 | if (!CGRectIntersectsRect(rect, attribute.frame)) 85 | continue; 86 | [attributes addObject:attribute]; 87 | } 88 | return attributes; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJSectionBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJSectionBackgroundView.h 3 | // AJTags 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015 AlienJunX 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import 13 | 14 | @interface AJSectionBackgroundView : UICollectionReusableView 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJSectionBackgroundView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJSectionBackgroundView.m 3 | // AJTags 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015 AlienJunX 7 | // 8 | // This source code is licensed under the MIT-style license found in the 9 | // LICENSE file in the root directory of this source tree. 10 | // 11 | 12 | #import "AJSectionBackgroundView.h" 13 | 14 | @interface AJSectionBackgroundView() 15 | @property (weak,nonatomic) UIView *bgview; 16 | @end 17 | 18 | @implementation AJSectionBackgroundView 19 | 20 | - (instancetype)initWithFrame:(CGRect)frame{ 21 | self = [super initWithFrame:frame]; 22 | if (self) { 23 | UIView *bgview = [[UIView alloc] init]; 24 | bgview.layer.borderColor = [UIColor colorWithRed:180.0/255.0 green:180.0/255.0 blue:180.0/255.0 alpha:1.0].CGColor; 25 | bgview.layer.borderWidth = 0.5; 26 | bgview.backgroundColor = [UIColor whiteColor]; 27 | bgview.layer.cornerRadius = 2.0; 28 | [self addSubview:bgview]; 29 | self.bgview = bgview; 30 | _bgview.translatesAutoresizingMaskIntoConstraints = NO; 31 | 32 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_bgview]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_bgview)]]; 33 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_bgview]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_bgview)]]; 34 | } 35 | return self; 36 | } 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagModel.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AJTagModel : NSObject 12 | @property (strong, nonatomic) NSString *text; 13 | @property (strong, nonatomic) NSString *color; 14 | @property (nonatomic) NSInteger index; 15 | 16 | + (NSMutableArray *)initData; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagModel.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | #import 9 | #import "AJTagModel.h" 10 | 11 | @implementation AJTagModel 12 | 13 | + (NSMutableArray *)initData { 14 | NSMutableArray *marray = [[NSMutableArray alloc] init]; 15 | for (int i=0; i<[self arrayText].count; i++) { 16 | AJTagModel *t = [[AJTagModel alloc] init]; 17 | t.index = i; 18 | t.text = [self arrayText][i]; 19 | t.color = [t randomColor]; 20 | [marray addObject:t]; 21 | } 22 | return marray; 23 | } 24 | 25 | + (NSArray *)arrayText { 26 | return @[@"帅气",@"完美大人",@"好给力",@"好厉害",@"编程高手",@"设计师",@"有品位",@"色彩玩家",@"颜值高",@"善于沟通",@"牛逼闪闪",@"哈哈",@"潜力股",@"富二代",@"跑车一族",@"牛叉",@"泡妞高手",@"萝莉控",@"爱喝啤酒吃烧烤",@"外星人",@"妹子",@"妞妞",@"瓦窑",@"丽丽",@"土豪",@"冲锋枪啊",]; 27 | } 28 | 29 | - (NSString *)randomColor { 30 | CGFloat r = ( arc4random() % 256 / 256.0 ); 31 | CGFloat g = ( arc4random() % 128 / 256.0 ) + 0.5; 32 | CGFloat b = ( arc4random() % 128 / 256.0 ) + 0.5; 33 | 34 | return [NSString stringWithFormat:@"%02lX%02lX%02lX", 35 | lroundf(r * 255), 36 | lroundf(g * 255), 37 | lroundf(b * 255)]; 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagsCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagsCell.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AJTagsCell : UICollectionViewCell 12 | 13 | - (void)setTitleStr:(NSString *)title color:(NSString *)color; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagsCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagsCell.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import "AJTagsCell.h" 10 | @interface AJTagsCell() 11 | @property (weak, nonatomic) UIView *bgView; 12 | @property (weak, nonatomic) UILabel *label; 13 | @end 14 | 15 | @implementation AJTagsCell 16 | 17 | - (void)setTitleStr:(NSString *)title color:(NSString *)color { 18 | if (self.bgView == nil) { 19 | UIView *bgView = [[UIView alloc] initWithFrame:self.bounds]; 20 | [self.contentView addSubview:bgView]; 21 | self.bgView = bgView; 22 | bgView.layer.cornerRadius = 13; 23 | } 24 | if (self.label == nil) { 25 | UILabel *label = [[UILabel alloc] initWithFrame:self.bounds]; 26 | label.font = [UIFont systemFontOfSize:12.0]; 27 | label.textColor = UIColor.whiteColor; 28 | label.textAlignment = NSTextAlignmentCenter; 29 | [self.contentView addSubview:label]; 30 | self.label = label; 31 | } 32 | 33 | self.label.text = title; 34 | self.bgView.backgroundColor = [self createBGColor:color]; 35 | } 36 | 37 | - (UIColor *)createBGColor:(NSString *)color { 38 | if (color.length < 6) { 39 | return [UIColor whiteColor]; 40 | } 41 | long red = strtoul([[color substringWithRange:NSMakeRange(0, 2)] UTF8String],0,16); 42 | long green = strtoul([[color substringWithRange:NSMakeRange(2, 2)] UTF8String],0,16); 43 | long blue = strtoul([[color substringWithRange:NSMakeRange(4, 2)] UTF8String],0,16); 44 | return [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1.0f]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagsView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagsView.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol AJTagsViewDelegate 12 | 13 | //选中的标签 14 | - (NSMutableArray *)tagsSelectedList; 15 | 16 | //全部标签 17 | - (NSMutableArray *)tagsOriginDataList; 18 | 19 | @end 20 | 21 | @interface AJTagsView : UICollectionView 22 | 23 | @property (strong, nonatomic) NSMutableArray *originDataList; 24 | @property (strong, nonatomic) NSMutableArray *selectedList; 25 | 26 | - (void)reloadDataInfo; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /TagDemo/BoCollectionSectionBgLayout/AJTagsView.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJTagsView.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import "AJTagsView.h" 10 | #import "AJTagsCell.h" 11 | #import "AJTagModel.h" 12 | #import "AJSectionBackgroundLayout.h" 13 | 14 | #define kItemHeight 26 15 | #define kMinimumLineSpacing 5 16 | #define kMinimumInteritemSpacing 5 17 | 18 | #define kSectionEdgeInsetsLeft 15 19 | #define kSectionEdgeInsetsBottom 0 20 | #define kSectionEdgeInsetsTop 5 21 | #define kSectionEdgeInsetsRight 15 22 | 23 | #define kMarginTop 134 24 | 25 | @interface AJTagsView() 26 | @property (strong, nonatomic) NSMutableArray *unSelectedList; 27 | @end 28 | 29 | @implementation AJTagsView 30 | 31 | #pragma mark - init 32 | - (void)initCommon { 33 | [self registerClass:[AJTagsCell class] forCellWithReuseIdentifier:@"cell"]; 34 | self.backgroundColor = [UIColor whiteColor]; 35 | self.userInteractionEnabled = YES; 36 | self.delegate = self; 37 | self.dataSource = self; 38 | } 39 | 40 | - (instancetype)initWithFrame:(CGRect)frame { 41 | AJSectionBackgroundLayout *flowLayout = [[AJSectionBackgroundLayout alloc] init]; 42 | [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical]; 43 | self = [super initWithFrame:frame collectionViewLayout:flowLayout]; 44 | if (self) { 45 | [self initCommon]; 46 | } 47 | return self; 48 | } 49 | 50 | - (instancetype)initWithCoder:(NSCoder *)coder { 51 | self = [super initWithCoder:coder]; 52 | if (self) { 53 | self.collectionViewLayout = [[AJSectionBackgroundLayout alloc] init]; 54 | [self initCommon]; 55 | } 56 | return self; 57 | } 58 | 59 | - (void)reloadDataInfo { 60 | for (int i = 0; i < self.originDataList.count; i++) { 61 | AJTagModel *model = self.originDataList[i]; 62 | model.index = i; 63 | BOOL unSelected = YES; 64 | for (AJTagModel *model1 in self.selectedList) { 65 | if ([model1.text isEqualToString:model.text]) { 66 | unSelected = NO; 67 | break; 68 | } 69 | } 70 | if (unSelected) { 71 | [self.unSelectedList addObject:model]; 72 | } 73 | } 74 | [self reloadData]; 75 | } 76 | 77 | #pragma mark - UICollectionViewDataSource 78 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 79 | return 2; 80 | } 81 | 82 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 83 | NSInteger items = 1; 84 | if (section == 0) { 85 | items = [self.selectedList count]; 86 | } else if (section == 1) { 87 | items = [self.unSelectedList count]; 88 | } 89 | return items; 90 | } 91 | 92 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 93 | AJTagsCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; 94 | AJTagModel *model; 95 | if (indexPath.section==0) { 96 | model =self.selectedList[indexPath.row]; 97 | } else if(indexPath.section == 1) { 98 | model =self.unSelectedList[indexPath.row]; 99 | } 100 | [cell setTitleStr:model.text color:model.color]; 101 | return cell; 102 | } 103 | 104 | //- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 105 | // UICollectionReusableView *view ; 106 | // if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 107 | // view = [UICollectionReusableView new]; 108 | // } 109 | // return view; 110 | //} 111 | 112 | 113 | #pragma mark - UICollectionViewDelegateFlowLayout 114 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 115 | UIEdgeInsets inset = UIEdgeInsetsMake(kSectionEdgeInsetsTop, kSectionEdgeInsetsLeft, 5, kSectionEdgeInsetsRight); 116 | if (section == 0) { 117 | if (self.selectedList.count == 0) { 118 | inset = UIEdgeInsetsMake(5, 15, 31, 15); 119 | } 120 | } else if (section == 1) { 121 | if (self.unSelectedList.count == 0) { 122 | inset = UIEdgeInsetsMake(5, 15, 93, 15); 123 | } 124 | } 125 | return inset; 126 | } 127 | 128 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { 129 | return kMinimumLineSpacing; 130 | } 131 | 132 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { 133 | return kMinimumInteritemSpacing; 134 | } 135 | 136 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 137 | CGSize size = CGSizeZero; 138 | AJTagModel *model; 139 | if (indexPath.section == 0) { 140 | model = self.selectedList[indexPath.row]; 141 | } else if(indexPath.section == 1) { 142 | model = self.unSelectedList[indexPath.row]; 143 | } 144 | size = [self calculateCellSize:model.text]; 145 | return size; 146 | } 147 | 148 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { 149 | if (section == 0) { 150 | return CGSizeMake(0, CGFLOAT_MIN); 151 | } 152 | return CGSizeMake([UIScreen mainScreen].bounds.size.width, 30); 153 | } 154 | 155 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 156 | if (indexPath.section == 0) { 157 | //insert 到原来的位置 158 | AJTagModel *model = self.selectedList[indexPath.row]; 159 | NSInteger index = [self getObjectInListIndex:model]; 160 | 161 | [self.unSelectedList insertObject:model atIndex:index]; 162 | [self.selectedList removeObjectAtIndex:indexPath.row]; 163 | 164 | NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:index inSection:1]; 165 | [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; 166 | } else if (indexPath.section == 1) { 167 | [self.selectedList addObject:self.unSelectedList[indexPath.row]]; 168 | [self.unSelectedList removeObjectAtIndex:indexPath.row]; 169 | 170 | NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:self.selectedList.count - 1 inSection:0]; 171 | [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; 172 | } 173 | } 174 | 175 | 176 | #pragma mark - utils 177 | 178 | //查询对象插入到原来合适的位置 179 | - (NSInteger)getObjectInListIndex:(AJTagModel *)m { 180 | //把m丢到List中,然后排序一下,找到str在List中的位置 181 | if (m) { 182 | [self.unSelectedList addObject:m]; 183 | [self.unSelectedList sortUsingComparator:^NSComparisonResult(AJTagModel *obj1, AJTagModel *obj2) { 184 | NSInteger index1 = obj1.index; 185 | NSInteger index2 = obj2.index; 186 | return index1 > index2; 187 | }]; 188 | NSInteger index = [self.unSelectedList indexOfObject:m]; 189 | [self.unSelectedList removeObject:m]; 190 | return index; 191 | } 192 | 193 | return [self.unSelectedList count] + 1; 194 | } 195 | 196 | 197 | //通过text获取tag 198 | - (AJTagModel *)getObjectInList:(NSString *)str { 199 | for (AJTagModel *model in self.originDataList) { 200 | if ([model.text isEqualToString:str]) { 201 | return model; 202 | } 203 | } 204 | return nil; 205 | } 206 | 207 | //计算cell size 208 | - (CGSize)calculateCellSize:(NSString *)content { 209 | CGSize size = [content sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(MAXFLOAT, kItemHeight) lineBreakMode:NSLineBreakByCharWrapping]; 210 | size.height = kItemHeight; 211 | size.width = floorf(size.width+20); 212 | return size; 213 | } 214 | 215 | #pragma mark - getter/setter 216 | - (NSMutableArray *)selectedList { 217 | if (_selectedList == nil) { 218 | _selectedList = [[NSMutableArray alloc] init]; 219 | } 220 | return _selectedList; 221 | } 222 | 223 | - (NSMutableArray *)unSelectedList { 224 | if (_unSelectedList == nil) { 225 | _unSelectedList = [[NSMutableArray alloc] init]; 226 | } 227 | return _unSelectedList; 228 | } 229 | 230 | - (NSMutableArray *)originDataList { 231 | if (_originDataList == nil) { 232 | _originDataList = [[NSMutableArray alloc] init]; 233 | } 234 | return _originDataList; 235 | } 236 | 237 | @end 238 | -------------------------------------------------------------------------------- /TagDemo/ExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExampleViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TagDemo/ExampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 16/3/10. 6 | // Copyright © 2016年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import "ExampleViewController.h" 10 | #import "AJTagsView.h" 11 | #import "AJTagModel.h" 12 | 13 | 14 | @interface ExampleViewController() 15 | @property (weak, nonatomic) IBOutlet AJTagsView *tagsView; 16 | @property (strong, nonatomic) NSMutableArray *originDataList; 17 | @property (strong, nonatomic) NSMutableArray *selectedList; 18 | @end 19 | 20 | @implementation ExampleViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | self.originDataList = [AJTagModel initData]; 26 | self.selectedList = [NSMutableArray array]; 27 | 28 | for (int i = 0; i < self.originDataList.count; i++) { 29 | if (i < 8) { 30 | [self.selectedList addObject:self.originDataList[i]]; 31 | } 32 | } 33 | 34 | self.tagsView.originDataList = self.originDataList; 35 | self.tagsView.selectedList = self.selectedList; 36 | 37 | [self.tagsView reloadDataInfo]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /TagDemo/Images.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 | } -------------------------------------------------------------------------------- /TagDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.alienjun.demo.$(PRODUCT_NAME:rfc1034identifier) 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 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /TagDemo/TagCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // BoModifyExpertiseCell.h 3 | // bobohair-iphone 4 | // 5 | // Created by AlienJunX on 15/7/15. 6 | // Copyright (c) 2015年 Shanghai Metis IT Co.,Ltd. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TagCell : UICollectionViewCell 12 | @property (weak, nonatomic) IBOutlet UILabel *label; 13 | -(void)setTitleStr:(NSString *)title color:(NSString *)color; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /TagDemo/TagCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // BoModifyExpertiseCell.m 3 | // bobohair-iphone 4 | // 5 | // Created by AlienJunX on 15/7/15. 6 | // Copyright (c) 2015年 Shanghai Metis IT Co.,Ltd. All rights reserved. 7 | // 8 | 9 | #import "TagCell.h" 10 | 11 | @interface TagCell() 12 | 13 | @property (weak, nonatomic) IBOutlet UIView *bgView; 14 | 15 | @end 16 | 17 | @implementation TagCell 18 | 19 | -(void)awakeFromNib{ 20 | [super awakeFromNib]; 21 | _bgView.layer.cornerRadius = 13; 22 | 23 | } 24 | 25 | 26 | -(void)setTitleStr:(NSString *)title color:(NSString *)color{ 27 | [self.label setText:title]; 28 | _bgView.backgroundColor = [self randomColor]; 29 | } 30 | 31 | 32 | -(UIColor *)randomColor{ 33 | CGFloat hue = ( arc4random() % 256 / 256.0 ); 34 | CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; 35 | CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; 36 | return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /TagDemo/TagModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TagModel.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TagModel : NSObject 12 | @property (strong, nonatomic) NSString *text; 13 | @property (strong, nonatomic) NSString *color; 14 | @property (nonatomic) NSInteger index; 15 | 16 | +(NSMutableArray *)initData; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /TagDemo/TagModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TagModel.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import "TagModel.h" 10 | 11 | 12 | @implementation TagModel 13 | 14 | 15 | +(NSMutableArray *)initData{ 16 | NSMutableArray *marray = [[NSMutableArray alloc] init]; 17 | for (int i=0; i<[self arrayText].count; i++) { 18 | TagModel *t = [[TagModel alloc] init]; 19 | t.index = i; 20 | t.text = [self arrayText][i]; 21 | // t.color = @"708c3b"; 22 | [marray addObject:t]; 23 | } 24 | 25 | return marray; 26 | } 27 | 28 | +(NSArray *)arrayText{ 29 | return @[@"帅气",@"完美大人",@"好给力",@"好厉害",@"编程高手",@"设计师",@"有品位",@"色彩玩家",@"颜值高",@"善于沟通",@"牛逼闪闪",@"哈哈",@"潜力股",@"富二代",@"跑车一族",@"牛叉",@"泡妞高手",@"萝莉控",@"爱喝啤酒吃烧烤",@"外星人",@"妹子",@"妞妞",@"瓦窑",@"丽丽",@"土豪",@"冲锋枪啊",]; 30 | } 31 | @end 32 | -------------------------------------------------------------------------------- /TagDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TagDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #define kItemHeight 26 10 | #define kMinimumLineSpacing 5 11 | #define kMinimumInteritemSpacing 5 12 | 13 | #define kSectionEdgeInsetsLeft 15 14 | #define kSectionEdgeInsetsBottom 0 15 | #define kSectionEdgeInsetsTop 5 16 | #define kSectionEdgeInsetsRight 15 17 | 18 | #define kMarginTop 134 19 | 20 | 21 | #import "ViewController.h" 22 | #import "TagCell.h" 23 | #import "TagModel.h" 24 | 25 | @interface ViewController () 26 | @property (strong, nonatomic) NSMutableArray *originDataList; 27 | @property (strong, nonatomic) NSMutableArray *selectedList; 28 | @property (strong, nonatomic) NSMutableArray *unSelectedList; 29 | @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; 30 | @end 31 | 32 | @implementation ViewController 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | //初始化数据 37 | self.originDataList = [TagModel initData]; 38 | 39 | for (int i=0 ; i index2; 159 | }]; 160 | NSInteger index = [self.unSelectedList indexOfObject:m]; 161 | [self.unSelectedList removeObject:m]; 162 | return index; 163 | } 164 | 165 | return [self.unSelectedList count]+1; 166 | } 167 | 168 | 169 | //通过text获取tag 170 | -(TagModel *) getObjectInList:(NSString *)str{ 171 | for (TagModel *model in self.originDataList) { 172 | if ([model.text isEqualToString:str]) { 173 | return model; 174 | } 175 | } 176 | return nil; 177 | } 178 | 179 | //计算cell size 180 | -(CGSize)calculateCellSize:(NSString *)content{ 181 | CGSize size = [content sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:CGSizeMake(MAXFLOAT, kItemHeight) lineBreakMode:NSLineBreakByCharWrapping]; 182 | size.height = kItemHeight; 183 | size.width = floorf(size.width+20); 184 | return size; 185 | } 186 | 187 | 188 | #pragma mark - getter/setter 189 | -(NSMutableArray *)selectedList{ 190 | if (_selectedList == nil) { 191 | _selectedList = [[NSMutableArray alloc] init]; 192 | } 193 | return _selectedList; 194 | } 195 | 196 | -(NSMutableArray *)unSelectedList{ 197 | if (_unSelectedList == nil) { 198 | _unSelectedList = [[NSMutableArray alloc] init]; 199 | } 200 | return _unSelectedList; 201 | } 202 | 203 | -(NSMutableArray *)originDataList{ 204 | if (_originDataList == nil) { 205 | _originDataList = [[NSMutableArray alloc] init]; 206 | } 207 | return _originDataList; 208 | } 209 | @end 210 | -------------------------------------------------------------------------------- /TagDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TagDemo 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. 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 | -------------------------------------------------------------------------------- /TagDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.alienjun.demo.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /TagDemoTests/TagDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TagDemoTests.m 3 | // TagDemoTests 4 | // 5 | // Created by AlienJunX on 15/9/9. 6 | // Copyright (c) 2015年 com.alienjun.demo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface TagDemoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation TagDemoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------