diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..f1ae691 --- /dev/null +++ b/Podfile @@ -0,0 +1,17 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '8.0' +# Uncomment this line if you're using Swift +# use_frameworks! + +source 'git@gitlab.91chengguo.com:component-iOS/specs.git' +source 'https://github.com/CocoaPods/Specs.git' + +target 'ZBWUIKit' do + pod 'SDWebImage' + pod 'libwebp', '0.6.1' + pod 'MJRefresh', '~> 3.1.12' + pod 'ZBWCategories', '~> 0.1.7' + pod 'ZBWUISignal' + pod 'Common-iOS', :path => "../Common-iOS" +end + diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..1ef4e84 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,90 @@ +PODS: + - Common-iOS (0.0.1): + - libwebp (= 0.6.1) + - ZBWCategories + - ZBWMacroDefine/biz (~> 0.1.2) + - libwebp (0.6.1): + - libwebp/core (= 0.6.1) + - libwebp/dec (= 0.6.1) + - libwebp/demux (= 0.6.1) + - libwebp/dsp (= 0.6.1) + - libwebp/enc (= 0.6.1) + - libwebp/mux (= 0.6.1) + - libwebp/utils (= 0.6.1) + - libwebp/webp (= 0.6.1) + - libwebp/core (0.6.1): + - libwebp/webp + - libwebp/dec (0.6.1): + - libwebp/core + - libwebp/demux (0.6.1): + - libwebp/core + - libwebp/dsp (0.6.1): + - libwebp/core + - libwebp/enc (0.6.1): + - libwebp/core + - libwebp/mux (0.6.1): + - libwebp/core + - libwebp/utils (0.6.1): + - libwebp/core + - libwebp/webp (0.6.1) + - MJRefresh (3.1.17) + - SDWebImage (5.10.2): + - SDWebImage/Core (= 5.10.2) + - SDWebImage/Core (5.10.2) + - ZBWCategories (0.1.7): + - SDWebImage + - "ZBWCategories/NSFoundation+ZBWCategory (= 0.1.7)" + - "ZBWCategories/UIKit+ZBWCategory (= 0.1.7)" + - ZBWJson + - "ZBWCategories/NSFoundation+ZBWCategory (0.1.7)": + - SDWebImage + - "ZBWCategories/NSFoundation+ZBWCategory/NSObject+ZBWCategory (= 0.1.7)" + - ZBWJson + - "ZBWCategories/NSFoundation+ZBWCategory/NSObject+ZBWCategory (0.1.7)": + - SDWebImage + - ZBWJson + - "ZBWCategories/UIKit+ZBWCategory (0.1.7)": + - SDWebImage + - ZBWJson + - ZBWJson (0.0.7) + - ZBWMacroDefine/biz (0.1.4): + - ZBWMacroDefine/common + - ZBWMacroDefine/common (0.1.4) + - ZBWUISignal (0.0.1) + +DEPENDENCIES: + - Common-iOS (from `../Common-iOS`) + - libwebp (= 0.6.1) + - MJRefresh (~> 3.1.12) + - SDWebImage + - ZBWCategories (~> 0.1.7) + - ZBWUISignal + +SPEC REPOS: + "git@gitlab.91chengguo.com:component-iOS/specs.git": + - ZBWMacroDefine + https://github.com/CocoaPods/Specs.git: + - libwebp + - MJRefresh + - SDWebImage + - ZBWCategories + - ZBWJson + - ZBWUISignal + +EXTERNAL SOURCES: + Common-iOS: + :path: "../Common-iOS" + +SPEC CHECKSUMS: + Common-iOS: 53107f5b82cf18d5f7a2a998b11ce66890053392 + libwebp: 0f01098c6c17175391af621b2f14150f3ca16e16 + MJRefresh: ee5b68f639775462faba4db0fd243baf4d42c2cf + SDWebImage: b969dcfc02c40a5da71eac0b03b8f1a0c794a86f + ZBWCategories: 1b6c811d37cf02a4d83d36a4cc1913f87faf74fb + ZBWJson: ae7f2d44877ea347c48d6714bfc4704129adedd4 + ZBWMacroDefine: 07e0c7200686f875e6ba2a98b8b94ca792536a7c + ZBWUISignal: 88ca740af822efc938d1d6f00e8c0970bea0f2bc + +PODFILE CHECKSUM: ee9716c2ff5b0f75412fbdcdd4e477130b5bda03 + +COCOAPODS: 1.8.3 diff --git a/ZBWUIKit.podspec b/ZBWUIKit.podspec new file mode 100644 index 0000000..937c0e3 --- /dev/null +++ b/ZBWUIKit.podspec @@ -0,0 +1,89 @@ + +Pod::Spec.new do |s| + + # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # These will help people to find your library, and whilst it + # can feel like a chore to fill in it's definitely to your advantage. The + # summary should be tweet-length, and the description more in depth. + # + + s.name = "ZBWUIKit" + s.version = "0.1.0" + s.summary = "A short description of ZBWUIKit." + + # This description is used to generate tags and improve search results. + # * Think: What does it do? Why did you write it? What is the focus? + # * Try to keep it short, snappy and to the point. + # * Write the description between the DESC delimiters below. + # * Finally, don't worry about the indent, CocoaPods strips it! + s.description = <<-DESC + zbwuikit + DESC + + s.homepage = "http://EXAMPLE/ZBWUIKit" + # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" + + + # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Licensing your code is important. See http://choosealicense.com for more info. + # CocoaPods will detect a license file if there is a named LICENSE* + # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. + # + + s.license = "BSD" + # s.license = { :type => "MIT", :file => "FILE_LICENSE" } + + s.author = { "bwzhu" => "zhubw@taofen8.com" } + + s.source = { :git => "git@gitlab.91chengguo.com:component-iOS/ZBWUIKit.git", :tag => "#{s.version}" } + + s.platform = :ios, "7.0" + + s.source_files = "ZBWUIKit", "ZBWUIKit/*.{h,m,mm}" + + s.prefix_header_file = "ZBWUIKit/ZBWUIKit-prefix.pch" + + # s.exclude_files = "Classes/Exclude" + + # s.public_header_files = "Classes/**/*.h" + + s.subspec 'CustomViews' do |coustomviewsSpec| + coustomviewsSpec.source_files = "ZBWUIKit/CustomViews/**/*.{h,m,mm}" + end + + s.subspec 'ViewControllers' do |viewControllersSpec| + viewControllersSpec.source_files = "ZBWUIKit/ViewControllers/**/*.{h,m,mm}" + end + + s.subspec 'Signal' do |signalSpec| + signalSpec.source_files = "ZBWUIKit/Signal/*.*","ZBWUIKit/Signal/**/*.{h,m,mm}" + end + + s.subspec 'Category' do |categoryS| + categoryS.source_files = "ZBWUIKit/Category/*.*","ZBWUIKit/Category/**/*.{h,m,mm}" + end + + + # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Link your library with frameworks, or libraries. Libraries do not include + # the lib prefix of their name. + # + + # s.framework = "SomeFramework" + # s.frameworks = "SomeFramework", "AnotherFramework" + + # s.library = "iconv" + # s.libraries = "iconv", "xml2" + + # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } + s.dependency "ZBWCategories" + s.dependency "Common-iOS" + s.dependency 'SDWebImage' + s.dependency 'libwebp', '0.6.1' + s.dependency 'MJRefresh', '~> 3.1.12' + s.dependency 'ZBWUISignal' + +end diff --git a/ZBWUIKit.xcodeproj/project.pbxproj b/ZBWUIKit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..9f993a0 --- /dev/null +++ b/ZBWUIKit.xcodeproj/project.pbxproj @@ -0,0 +1,503 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 8C113E822249DCFD00E26866 /* ZBWUIKit.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8C113E7F2249DCFD00E26866 /* ZBWUIKit.h */; }; + 8C113EBB2249DDED00E26866 /* UIResponder+ZBWStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113E8A2249DDED00E26866 /* UIResponder+ZBWStack.m */; }; + 8C113EC02249DDED00E26866 /* UIView+ZBWLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113E982249DDED00E26866 /* UIView+ZBWLoadingView.m */; }; + 8C113EC12249DDED00E26866 /* ZBWLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113E9A2249DDED00E26866 /* ZBWLoadingView.m */; }; + 8C113EC22249DDED00E26866 /* ZBWBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113E9B2249DDED00E26866 /* ZBWBannerView.m */; }; + 8C113EC32249DDED00E26866 /* ZBWPhoneNumTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113E9C2249DDED00E26866 /* ZBWPhoneNumTextField.m */; }; + 8C113EC42249DDED00E26866 /* ZBWSegmentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EA02249DDED00E26866 /* ZBWSegmentView.m */; }; + 8C113EC62249DDED00E26866 /* ZBWGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EA32249DDED00E26866 /* ZBWGridView.m */; }; + 8C113EC72249DDED00E26866 /* ZBWGridCellButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EA42249DDED00E26866 /* ZBWGridCellButton.m */; }; + 8C113EC82249DDED00E26866 /* ZBWGridCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EA62249DDED00E26866 /* ZBWGridCell.m */; }; + 8C113EC92249DDED00E26866 /* ZBWPageableGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EAA2249DDED00E26866 /* ZBWPageableGridView.m */; }; + 8C113ECA2249DDED00E26866 /* TagView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EAF2249DDED00E26866 /* TagView.m */; }; + 8C113ECB2249DDED00E26866 /* TagItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EB02249DDED00E26866 /* TagItemView.m */; }; + 8C113ECC2249DDED00E26866 /* UITableView+ZBWAddition.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EB32249DDED00E26866 /* UITableView+ZBWAddition.m */; }; + 8C113ECD2249DDED00E26866 /* ZBWPageControlView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EB42249DDED00E26866 /* ZBWPageControlView.m */; }; + 8C113ECE2249DDED00E26866 /* ZBWSegmentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C113EB92249DDED00E26866 /* ZBWSegmentViewController.m */; }; + FE67D7737D186214B56F81DA /* libPods-ZBWUIKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7036C14F00FAC0F54F3B0A2C /* libPods-ZBWUIKit.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8C113E7A2249DCFD00E26866 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 8C113E822249DCFD00E26866 /* ZBWUIKit.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0EB0BCBF3D5FA5EC511F886D /* Pods-ZBWUIKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZBWUIKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-ZBWUIKit/Pods-ZBWUIKit.release.xcconfig"; sourceTree = ""; }; + 7036C14F00FAC0F54F3B0A2C /* libPods-ZBWUIKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ZBWUIKit.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C113E7C2249DCFD00E26866 /* libZBWUIKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZBWUIKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C113E7F2249DCFD00E26866 /* ZBWUIKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZBWUIKit.h; sourceTree = ""; }; + 8C113E8A2249DDED00E26866 /* UIResponder+ZBWStack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIResponder+ZBWStack.m"; sourceTree = ""; }; + 8C113E8B2249DDED00E26866 /* ZBWUIKit+Category.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ZBWUIKit+Category.h"; sourceTree = ""; }; + 8C113E8C2249DDED00E26866 /* UIResponder+ZBWStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+ZBWStack.h"; sourceTree = ""; }; + 8C113E982249DDED00E26866 /* UIView+ZBWLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+ZBWLoadingView.m"; sourceTree = ""; }; + 8C113E9A2249DDED00E26866 /* ZBWLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWLoadingView.m; sourceTree = ""; }; + 8C113E9B2249DDED00E26866 /* ZBWBannerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWBannerView.m; sourceTree = ""; }; + 8C113E9C2249DDED00E26866 /* ZBWPhoneNumTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWPhoneNumTextField.m; sourceTree = ""; }; + 8C113E9D2249DDED00E26866 /* ZBWPageControlView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWPageControlView.h; sourceTree = ""; }; + 8C113E9E2249DDED00E26866 /* ZBWCustomViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWCustomViews.h; sourceTree = ""; }; + 8C113E9F2249DDED00E26866 /* UITableView+ZBWAddition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+ZBWAddition.h"; sourceTree = ""; }; + 8C113EA02249DDED00E26866 /* ZBWSegmentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWSegmentView.m; sourceTree = ""; }; + 8C113EA32249DDED00E26866 /* ZBWGridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWGridView.m; sourceTree = ""; }; + 8C113EA42249DDED00E26866 /* ZBWGridCellButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWGridCellButton.m; sourceTree = ""; }; + 8C113EA52249DDED00E26866 /* ZBWPageableGridView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWPageableGridView.h; sourceTree = ""; }; + 8C113EA62249DDED00E26866 /* ZBWGridCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWGridCell.m; sourceTree = ""; }; + 8C113EA72249DDED00E26866 /* ZBWGridCellButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWGridCellButton.h; sourceTree = ""; }; + 8C113EA82249DDED00E26866 /* ZBWGridView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWGridView.h; sourceTree = ""; }; + 8C113EA92249DDED00E26866 /* ZBWGridCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWGridCell.h; sourceTree = ""; }; + 8C113EAA2249DDED00E26866 /* ZBWPageableGridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWPageableGridView.m; sourceTree = ""; }; + 8C113EAB2249DDED00E26866 /* UIView+ZBWLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+ZBWLoadingView.h"; sourceTree = ""; }; + 8C113EAC2249DDED00E26866 /* ZBWLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWLoadingView.h; sourceTree = ""; }; + 8C113EAD2249DDED00E26866 /* ZBWBannerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWBannerView.h; sourceTree = ""; }; + 8C113EAF2249DDED00E26866 /* TagView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TagView.m; sourceTree = ""; }; + 8C113EB02249DDED00E26866 /* TagItemView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TagItemView.m; sourceTree = ""; }; + 8C113EB12249DDED00E26866 /* TagView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagView.h; sourceTree = ""; }; + 8C113EB22249DDED00E26866 /* TagItemView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagItemView.h; sourceTree = ""; }; + 8C113EB32249DDED00E26866 /* UITableView+ZBWAddition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+ZBWAddition.m"; sourceTree = ""; }; + 8C113EB42249DDED00E26866 /* ZBWPageControlView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWPageControlView.m; sourceTree = ""; }; + 8C113EB52249DDED00E26866 /* ZBWPhoneNumTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWPhoneNumTextField.h; sourceTree = ""; }; + 8C113EB62249DDED00E26866 /* ZBWSegmentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWSegmentView.h; sourceTree = ""; }; + 8C113EB72249DDED00E26866 /* ZBWUIKit-prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ZBWUIKit-prefix.pch"; sourceTree = ""; }; + 8C113EB92249DDED00E26866 /* ZBWSegmentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZBWSegmentViewController.m; sourceTree = ""; }; + 8C113EBA2249DDED00E26866 /* ZBWSegmentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZBWSegmentViewController.h; sourceTree = ""; }; + F83E43037E3570B89FC96C59 /* Pods-ZBWUIKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZBWUIKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ZBWUIKit/Pods-ZBWUIKit.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8C113E792249DCFD00E26866 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FE67D7737D186214B56F81DA /* libPods-ZBWUIKit.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8C113E732249DCFD00E26866 = { + isa = PBXGroup; + children = ( + 8C113E7E2249DCFD00E26866 /* ZBWUIKit */, + 8C113E7D2249DCFD00E26866 /* Products */, + BB30E84F97D625E35939E570 /* Pods */, + 9823D0728633EB030D2D127D /* Frameworks */, + ); + sourceTree = ""; + }; + 8C113E7D2249DCFD00E26866 /* Products */ = { + isa = PBXGroup; + children = ( + 8C113E7C2249DCFD00E26866 /* libZBWUIKit.a */, + ); + name = Products; + sourceTree = ""; + }; + 8C113E7E2249DCFD00E26866 /* ZBWUIKit */ = { + isa = PBXGroup; + children = ( + 8C113E882249DDED00E26866 /* Category */, + 8C113E972249DDED00E26866 /* CustomViews */, + 8C113EB72249DDED00E26866 /* ZBWUIKit-prefix.pch */, + 8C113EB82249DDED00E26866 /* ViewControllers */, + 8C113E7F2249DCFD00E26866 /* ZBWUIKit.h */, + ); + path = ZBWUIKit; + sourceTree = ""; + }; + 8C113E882249DDED00E26866 /* Category */ = { + isa = PBXGroup; + children = ( + 8C113E892249DDED00E26866 /* UIKit+Category */, + ); + path = Category; + sourceTree = ""; + }; + 8C113E892249DDED00E26866 /* UIKit+Category */ = { + isa = PBXGroup; + children = ( + 8C113E8A2249DDED00E26866 /* UIResponder+ZBWStack.m */, + 8C113E8B2249DDED00E26866 /* ZBWUIKit+Category.h */, + 8C113E8C2249DDED00E26866 /* UIResponder+ZBWStack.h */, + ); + path = "UIKit+Category"; + sourceTree = ""; + }; + 8C113E972249DDED00E26866 /* CustomViews */ = { + isa = PBXGroup; + children = ( + 8C113EA22249DDED00E26866 /* GridView */, + 8C113EAC2249DDED00E26866 /* ZBWLoadingView.h */, + 8C113E9A2249DDED00E26866 /* ZBWLoadingView.m */, + 8C113EAE2249DDED00E26866 /* TagView */, + 8C113E9F2249DDED00E26866 /* UITableView+ZBWAddition.h */, + 8C113EB32249DDED00E26866 /* UITableView+ZBWAddition.m */, + 8C113EAB2249DDED00E26866 /* UIView+ZBWLoadingView.h */, + 8C113E982249DDED00E26866 /* UIView+ZBWLoadingView.m */, + 8C113EAD2249DDED00E26866 /* ZBWBannerView.h */, + 8C113E9B2249DDED00E26866 /* ZBWBannerView.m */, + 8C113E9E2249DDED00E26866 /* ZBWCustomViews.h */, + 8C113E9D2249DDED00E26866 /* ZBWPageControlView.h */, + 8C113EB42249DDED00E26866 /* ZBWPageControlView.m */, + 8C113EB52249DDED00E26866 /* ZBWPhoneNumTextField.h */, + 8C113E9C2249DDED00E26866 /* ZBWPhoneNumTextField.m */, + 8C113EB62249DDED00E26866 /* ZBWSegmentView.h */, + 8C113EA02249DDED00E26866 /* ZBWSegmentView.m */, + ); + path = CustomViews; + sourceTree = ""; + }; + 8C113EA22249DDED00E26866 /* GridView */ = { + isa = PBXGroup; + children = ( + 8C113EA32249DDED00E26866 /* ZBWGridView.m */, + 8C113EA42249DDED00E26866 /* ZBWGridCellButton.m */, + 8C113EA52249DDED00E26866 /* ZBWPageableGridView.h */, + 8C113EA62249DDED00E26866 /* ZBWGridCell.m */, + 8C113EA72249DDED00E26866 /* ZBWGridCellButton.h */, + 8C113EA82249DDED00E26866 /* ZBWGridView.h */, + 8C113EA92249DDED00E26866 /* ZBWGridCell.h */, + 8C113EAA2249DDED00E26866 /* ZBWPageableGridView.m */, + ); + path = GridView; + sourceTree = ""; + }; + 8C113EAE2249DDED00E26866 /* TagView */ = { + isa = PBXGroup; + children = ( + 8C113EAF2249DDED00E26866 /* TagView.m */, + 8C113EB02249DDED00E26866 /* TagItemView.m */, + 8C113EB12249DDED00E26866 /* TagView.h */, + 8C113EB22249DDED00E26866 /* TagItemView.h */, + ); + path = TagView; + sourceTree = ""; + }; + 8C113EB82249DDED00E26866 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + 8C113EB92249DDED00E26866 /* ZBWSegmentViewController.m */, + 8C113EBA2249DDED00E26866 /* ZBWSegmentViewController.h */, + ); + path = ViewControllers; + sourceTree = ""; + }; + 9823D0728633EB030D2D127D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7036C14F00FAC0F54F3B0A2C /* libPods-ZBWUIKit.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + BB30E84F97D625E35939E570 /* Pods */ = { + isa = PBXGroup; + children = ( + F83E43037E3570B89FC96C59 /* Pods-ZBWUIKit.debug.xcconfig */, + 0EB0BCBF3D5FA5EC511F886D /* Pods-ZBWUIKit.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8C113E7B2249DCFD00E26866 /* ZBWUIKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8C113E852249DCFD00E26866 /* Build configuration list for PBXNativeTarget "ZBWUIKit" */; + buildPhases = ( + 7BBC934BE9511CF2BEF733B4 /* [CP] Check Pods Manifest.lock */, + 8C113E782249DCFD00E26866 /* Sources */, + 8C113E792249DCFD00E26866 /* Frameworks */, + 8C113E7A2249DCFD00E26866 /* CopyFiles */, + DC2404A55202CB695BAA63C9 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ZBWUIKit; + productName = ZBWUIKit; + productReference = 8C113E7C2249DCFD00E26866 /* libZBWUIKit.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8C113E742249DCFD00E26866 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = "朱博文"; + TargetAttributes = { + 8C113E7B2249DCFD00E26866 = { + CreatedOnToolsVersion = 10.1; + }; + }; + }; + buildConfigurationList = 8C113E772249DCFD00E26866 /* Build configuration list for PBXProject "ZBWUIKit" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8C113E732249DCFD00E26866; + productRefGroup = 8C113E7D2249DCFD00E26866 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8C113E7B2249DCFD00E26866 /* ZBWUIKit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 7BBC934BE9511CF2BEF733B4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ZBWUIKit-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + DC2404A55202CB695BAA63C9 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ZBWUIKit/Pods-ZBWUIKit-resources.sh", + "${PODS_ROOT}/MJRefresh/MJRefresh/MJRefresh.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MJRefresh.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ZBWUIKit/Pods-ZBWUIKit-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8C113E782249DCFD00E26866 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C113EC42249DDED00E26866 /* ZBWSegmentView.m in Sources */, + 8C113ECE2249DDED00E26866 /* ZBWSegmentViewController.m in Sources */, + 8C113ECB2249DDED00E26866 /* TagItemView.m in Sources */, + 8C113EC12249DDED00E26866 /* ZBWLoadingView.m in Sources */, + 8C113EC62249DDED00E26866 /* ZBWGridView.m in Sources */, + 8C113EC02249DDED00E26866 /* UIView+ZBWLoadingView.m in Sources */, + 8C113ECC2249DDED00E26866 /* UITableView+ZBWAddition.m in Sources */, + 8C113EC72249DDED00E26866 /* ZBWGridCellButton.m in Sources */, + 8C113ECD2249DDED00E26866 /* ZBWPageControlView.m in Sources */, + 8C113EC32249DDED00E26866 /* ZBWPhoneNumTextField.m in Sources */, + 8C113EC92249DDED00E26866 /* ZBWPageableGridView.m in Sources */, + 8C113ECA2249DDED00E26866 /* TagView.m in Sources */, + 8C113EC22249DDED00E26866 /* ZBWBannerView.m in Sources */, + 8C113EC82249DDED00E26866 /* ZBWGridCell.m in Sources */, + 8C113EBB2249DDED00E26866 /* UIResponder+ZBWStack.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 8C113E832249DCFD00E26866 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 8C113E842249DCFD00E26866 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8C113E862249DCFD00E26866 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F83E43037E3570B89FC96C59 /* Pods-ZBWUIKit.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SZRFDMPH3R; + GCC_PREFIX_HEADER = "ZBWUIKit/ZBWUIKit-prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = ""; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8C113E872249DCFD00E26866 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0EB0BCBF3D5FA5EC511F886D /* Pods-ZBWUIKit.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = SZRFDMPH3R; + GCC_PREFIX_HEADER = "ZBWUIKit/ZBWUIKit-prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = ""; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8C113E772249DCFD00E26866 /* Build configuration list for PBXProject "ZBWUIKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C113E832249DCFD00E26866 /* Debug */, + 8C113E842249DCFD00E26866 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8C113E852249DCFD00E26866 /* Build configuration list for PBXNativeTarget "ZBWUIKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C113E862249DCFD00E26866 /* Debug */, + 8C113E872249DCFD00E26866 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8C113E742249DCFD00E26866 /* Project object */; +} diff --git a/ZBWUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ZBWUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..7bc64fc --- /dev/null +++ b/ZBWUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ZBWUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ZBWUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ZBWUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ZBWUIKit.xcodeproj/project.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate b/ZBWUIKit.xcodeproj/project.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..3c7ebaf Binary files /dev/null and b/ZBWUIKit.xcodeproj/project.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ZBWUIKit.xcodeproj/xcuserdata/zhubowen.xcuserdatad/xcschemes/xcschememanagement.plist b/ZBWUIKit.xcodeproj/xcuserdata/zhubowen.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..7952d9b --- /dev/null +++ b/ZBWUIKit.xcodeproj/xcuserdata/zhubowen.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + ZBWUIKit.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/ZBWUIKit.xcworkspace/contents.xcworkspacedata b/ZBWUIKit.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..06edbf7 --- /dev/null +++ b/ZBWUIKit.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ZBWUIKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ZBWUIKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ZBWUIKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/IDEFindNavigatorScopes.plist b/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate b/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..62a4ef0 Binary files /dev/null and b/ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.h b/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.h new file mode 100644 index 0000000..05b155b --- /dev/null +++ b/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.h @@ -0,0 +1,54 @@ +// +// UIResponder+ZBWStack.h +// ZBWUIKit +// +// Created by 朱博文 on 16/12/22. +// Copyright © 2016年 朱博文. All rights reserved. +// + +#import + +@interface UIResponder (ZBWStack) + +/** + * 获取页面栈 + * 从当前Responder开始,往【下】获取页面栈。 + * 比如: + * [rootViewController] [rootViewController] [Push] [Present] + * UIWindow | UINavigationController | UIViewController | UIViewController | UIViewController + * 当前页面栈为: W -> Navi -> A -> B -> C + * 调用 [C zbw_stackResponders], 返回@(W, Navi, A, B, C) + * + * @return 返回页面栈 + */ +- (NSArray *)zbw_stackResponders; + + +/** + * 获取页面栈 + * 从当前Responder开始,往【上】获取页面栈。 + * 比如: + * [rootViewController] [rootViewController] [Push] [Present] + * UIWindow | UINavigationController | UIViewController | UIViewController | UIViewController + * 当前页面栈为: W -> Navi -> A -> B -> C + * 调用 [W zbw_reverseStackResponders], 返回@(W, Navi, A, B, C) + * + * @return 返回页面栈 + */ +- (NSArray *)zbw_reverseStackResponders; + + +- (UINavigationController *)zbw_topNavigationController; + +- (UINavigationController *)zbw_bottomNavigationController; + +- (UITabBarController *)zbw_topTabBarController; + +- (UITabBarController *)zbw_bottomTabBarController; + + +- (id)zbw_topVC:(Class)aClass; +- (id)zbw_bottomVC:(Class)aClass; + + +@end diff --git a/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.m b/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.m new file mode 100644 index 0000000..246a9af --- /dev/null +++ b/ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.m @@ -0,0 +1,231 @@ +// +// UIResponder+ZBWStack.m +// ZBWUIKit +// +// Created by 朱博文 on 16/12/22. +// Copyright © 2016年 朱博文. All rights reserved. +// + +#import "UIResponder+ZBWStack.h" + +@implementation UIResponder (ZBWStack) + +- (NSArray *)zbw_stackResponders +{ + NSMutableArray *stackArray = [NSMutableArray arrayWithCapacity:5]; + if ([self isKindOfClass:[UIWindow class]]) + { + [stackArray insertObject:self atIndex:0]; + NSArray *array = [self.nextResponder zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + } + else if([self isKindOfClass:[UIView class]]) + { + NSArray *array = [self.nextResponder zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + } + else if([self isKindOfClass:[UITabBarController class]]) + { + UITabBarController *tabBarController = (UITabBarController *)self; + UIViewController *selectedVC = tabBarController.selectedViewController; + NSArray *array = [selectedVC zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + [stackArray insertObject:tabBarController atIndex:0]; + } + else if([self isKindOfClass:[UINavigationController class]]) + { + NSArray *vcsOfNav = [(UINavigationController *)self viewControllers]; + [stackArray insertObjects:vcsOfNav atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, vcsOfNav.count)]]; + [stackArray insertObject:self atIndex:0]; + + // + NSArray *array = [self.nextResponder zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + } + else if([self isKindOfClass:[UIViewController class]]) + { + UIViewController *vc = (UIViewController *)self; + if (vc.navigationController) + { + NSArray *array = [vc.navigationController zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + } + else + { + [stackArray insertObject:self atIndex:0]; + NSArray *array = [self.nextResponder zbw_stackResponders]; + if (array.count > 0) + { + [stackArray insertObjects:array atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, array.count)]]; + } + } + + } + + return [stackArray copy]; + +} + +- (NSArray *)zbw_reverseStackResponders +{ + NSMutableArray *stackArray = [NSMutableArray arrayWithCapacity:5]; + + if ([self isKindOfClass:[UIWindow class]]) + { + UIWindow *window = (UIWindow *)self; + [stackArray insertObject:self atIndex:0]; + + if (window.rootViewController) + { + [stackArray addObjectsFromArray:[window.rootViewController zbw_reverseStackResponders]]; + } + } + else if([self isKindOfClass:[UIView class]]) + { + } + else if([self isKindOfClass:[UITabBarController class]]) + { + UITabBarController *tabBarController = (UITabBarController *)self; + [stackArray addObject:tabBarController]; + + if (tabBarController.presentedViewController) { + [stackArray addObject:[tabBarController.presentedViewController zbw_reverseStackResponders]]; + } else { + UIViewController *selectedVC = tabBarController.selectedViewController; + [stackArray addObjectsFromArray:[selectedVC zbw_reverseStackResponders]]; + } + } + else if([self isKindOfClass:[UINavigationController class]]) + { + UINavigationController *navVC = (UINavigationController *)self; + // NSArray *vcsOfNav = [(UINavigationController *)self viewControllers]; + + [stackArray addObject:self]; +// [stackArray addObjectsFromArray:navVC.viewControllers]; + + if (navVC.presentedViewController) + { + [stackArray addObjectsFromArray:[navVC.presentedViewController zbw_reverseStackResponders]]; + } else { +// [stackArray removeObject:navVC.topViewController]; + [stackArray addObjectsFromArray:[navVC.topViewController zbw_reverseStackResponders]]; + } + } + else if([self isKindOfClass:[UIViewController class]]) + { + UIViewController *vc = (UIViewController *)self; + +// if (vc.navigationController) +// { +// [stackArray addObjectsFromArray:[vc.navigationController zbw_reverseStackResponders]]; +// } +// else +// { + [stackArray addObject:vc]; + if (vc.presentedViewController) + { + [stackArray addObjectsFromArray:[vc.presentedViewController zbw_reverseStackResponders]]; + } else { + [vc.childViewControllers enumerateObjectsUsingBlock:^(__kindof UIViewController * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (![obj.view zbw_outsideWithView:vc.view]) { + [stackArray addObjectsFromArray:[obj zbw_reverseStackResponders]]; + } + }]; +// [stackArray addObjectsFromArray:vc.childViewControllers]; + } +// } + } + + return [stackArray copy]; +} + + +- (id)zbw_topVC:(Class)aClass +{ + NSArray *topArray = [self zbw_reverseStackResponders]; + __block id returnObj = nil; + [topArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:aClass]) { + returnObj = obj; + *stop = YES; + } + }]; + + if (returnObj) { + return returnObj; + } + + NSArray *bototomArray = [self zbw_stackResponders]; + [bototomArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:aClass]) { + returnObj = obj; + *stop = YES; + } + }]; + return returnObj; +} + +- (id)zbw_bottomVC:(Class)aClass +{ + __block id returnObj = nil; + + NSArray *bototomArray = [self zbw_stackResponders]; + [bototomArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj class] == aClass) { + returnObj = obj; + *stop = YES; + } + }]; + + if (returnObj) { + return returnObj; + } + + NSArray *topArray = [self zbw_reverseStackResponders]; + [topArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj class] == aClass) { + returnObj = obj; + *stop = YES; + } + }]; + + return returnObj; +} + +- (UINavigationController *)zbw_topNavigationController +{ + return [self zbw_topVC:[UINavigationController class]]; +} + +- (UINavigationController *)zbw_bottomNavigationController +{ + return [self zbw_bottomVC:[UINavigationController class]]; +} + +- (UITabBarController *)zbw_topTabBarController +{ + return [self zbw_topVC:[UITabBarController class]]; +} + +- (UITabBarController *)zbw_bottomTabBarController +{ + return [self zbw_bottomVC:[UITabBarController class]]; +} + + +@end diff --git a/ZBWUIKit/Category/UIKit+Category/ZBWUIKit+Category.h b/ZBWUIKit/Category/UIKit+Category/ZBWUIKit+Category.h new file mode 100644 index 0000000..ca1a1d6 --- /dev/null +++ b/ZBWUIKit/Category/UIKit+Category/ZBWUIKit+Category.h @@ -0,0 +1,15 @@ +// +// ZBWUIKit+Category.h +// ZBWUIKit +// +// Created by 朱博文 on 16/12/23. +// Copyright © 2016年 朱博文. All rights reserved. +// + +#ifndef ZBWUIKit_Category_h +#define ZBWUIKit_Category_h + +#import "UIResponder+ZBWStack.h" + + +#endif /* ZBWUIKit_Category_h */ diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridCell.h b/ZBWUIKit/CustomViews/GridView/ZBWGridCell.h new file mode 100644 index 0000000..f9e6da6 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridCell.h @@ -0,0 +1,71 @@ +// +// GridCell.h +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import +@class ZBWGridCellButton; +@class ZBWGridCell; +@protocol ZBWGridCellDelegate + +- (void)onGridButtonClick:(id)item; + +- (void)onSelectItem:(ZBWGridCell *)gridCell dataItem:(id)item isSelected:(BOOL)selected; + +@end + + +// cell中button的间距等信息 +struct ZBWAlign +{ + CGFloat left; // 左间距 + CGFloat top; // 上间距 + CGFloat right; // 右间距 + CGFloat bottom; // 下间距 + CGFloat between; // 按钮之间的间距 +}; +typedef struct ZBWAlign ZBWAlign; + +// ******************************************* +// 格网列表的cell,基类 +// ******************************************* +@interface ZBWGridCell : UITableViewCell +{ + NSMutableArray *_btns; // button数组 + NSUInteger _colume; // 列数 + ZBWAlign _align; // 按钮边距和间距 +} +@property(nonatomic, weak)id delegate; + +// 空白区域占位view的颜色。比如一行最多显示3个,但是最后一行只显示了1个,那么后面两个使用占位view。 默认为clear。 +@property (nonatomic, retain) UIColor *spaceAreaColor; + +- (void)setEdit:(BOOL)isEditing; + +// 功能:设置cell对应的数据,并构造btn +// 参数:[items]数据数组 +// 返回值:无 +- (void)setDataArray:(NSArray *)items; + + +// 功能:设置cell对应的数据,并构造btn +// 参数:[items]数据数组 [colume]最大的列数 +// 返回值:无 +- (void)setDataArray:(NSArray *)items colume:(NSUInteger)colume; + + +// -------------------------------- +// 子类重写 +// -------------------------------- + +// 功能:创建cell中对应的栏目btn +// 参数:无 +// 返回值:返回栏目btn +- (ZBWGridCellButton *)createButton; + +- (void)setAlign:(ZBWAlign)align; + +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridCell.m b/ZBWUIKit/CustomViews/GridView/ZBWGridCell.m new file mode 100644 index 0000000..341edd4 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridCell.m @@ -0,0 +1,159 @@ +// +// GridCell.m +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import "ZBWGridCell.h" +#import "ZBWGridCellButton.h" + +@interface ZBWGridCell () + +@property (nonatomic) UIView *placeholderView; + +@end + +@implementation ZBWGridCell +@synthesize delegate = _delegate; + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + _btns = [[NSMutableArray alloc] init]; + _colume = 0; + } + return self; +} + +- (void)setEdit:(BOOL)isEditing +{ + for (ZBWGridCellButton *btn in _btns) + { + [btn setEdit:isEditing]; + } +} + +// 按钮点击效果 +- (void)onBtnClick:(ZBWGridCellButton *)button +{ + if (button.isEditing) + { +// button.isChoosed = !button.isChoosed; + [button setChoosed:!button.isChoosed]; + + if (_delegate && [_delegate respondsToSelector:@selector(onSelectItem:dataItem:isSelected:)]) + { + [_delegate onSelectItem:self dataItem:((ZBWGridViewData *)button.data).data isSelected:button.isChoosed]; + } + } + else + { + if (_delegate && [_delegate respondsToSelector:@selector(onGridButtonClick:)]) + { + [_delegate onGridButtonClick:((ZBWGridViewData *)button.data).data]; + } + } +} + +- (void)setDataArray:(NSArray *)items +{ + _colume = _colume == 0 ? items.count : _colume; + NSInteger remainCount = _btns.count; + for (int i = 0 ; i < items.count ; i++) + { + id item = [items objectAtIndex:i]; + // 如果存在btn + if (i <= remainCount - 1) + { + [(ZBWGridCellButton *)[_btns objectAtIndex:i] setData:item]; + } + else + { + ZBWGridCellButton *btn = [self createButton]; + if (btn) + { + btn.data = item; + [btn addTarget:self action:@selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside]; + [_btns addObject:btn]; + [self.contentView addSubview:btn]; + } + } + } + + // 删除多余的btn + if (remainCount > items.count) + { + NSInteger count = remainCount; + while (count > items.count) + { + id btn = [_btns objectAtIndex:--count]; + [_btns removeObject:btn]; + [btn removeFromSuperview]; + } + } +} + +- (void)setDataArray:(NSArray *)items colume:(NSUInteger)colume +{ + _colume = colume; + [self setDataArray:items]; +} + +- (void)setAlign:(ZBWAlign)align +{ + _align = align; +} + +- (void)setColume:(NSUInteger)colume +{ + _colume = colume; +} + +- (ZBWGridCellButton *)createButton +{ + return nil; +} + +// 重新布局 +- (void)layoutSubviews +{ + [super layoutSubviews]; + CGRect contentFrame = self.frame; + CGFloat left = _align.left; + CGFloat right = _align.right; + CGFloat top = _align.top; + CGFloat bottom = _align.bottom; + CGFloat beteew = _align.between; + + // 按钮高度 + CGFloat btnHeight = contentFrame.size.height - top - bottom; + CGFloat btnWidth = (contentFrame.size.width - left - right - (_colume - 1) * beteew) / _colume; + + CGRect btnRect = CGRectMake(left, top, btnWidth, btnHeight); + for (ZBWGridCellButton *btn in _btns) + { + btn.frame = btnRect; + btnRect.origin.x += btnWidth + beteew; + } + + if (self.spaceAreaColor) { + [self.contentView addSubview:self.placeholderView]; + self.placeholderView.frame = CGRectMake(btnRect.origin.x, btnRect.origin.y, contentFrame.size.width - btnRect.origin.x, btnHeight); + self.placeholderView.backgroundColor = self.spaceAreaColor; + } + +} + +- (UIView *)placeholderView { + if (!_placeholderView) { + _placeholderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; + } + + return _placeholderView; +} + + +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.h b/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.h new file mode 100644 index 0000000..d75b4c5 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.h @@ -0,0 +1,34 @@ +// +// GridCellButton.h +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import + + +@interface ZBWGridViewData : NSObject +@property(nonatomic, retain)id data; +@property(nonatomic,assign)BOOL isChoosed; + +@property (nonatomic, assign) NSInteger index; + +@end + +// ******************************************** +// 格网按钮的基类 +// +// ******************************************** +@interface ZBWGridCellButton : UIButton +@property(nonatomic, retain)id data; // 对应的数据 +@property(nonatomic, assign)BOOL isEditing; // 是否为编辑状态 +@property(nonatomic, assign)BOOL isChoosed; + +#pragma mark 子类重写 +- (void)setEdit:(BOOL)isEditing; + +- (void)setChoosed:(BOOL)Choosed; + +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.m b/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.m new file mode 100644 index 0000000..1ec1ea1 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.m @@ -0,0 +1,44 @@ +// +// GridCellButton.m +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import "ZBWGridCellButton.h" + +@implementation ZBWGridViewData + +@end + + + +@implementation ZBWGridCellButton + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + self.exclusiveTouch = YES; + self.clipsToBounds = YES; + } + return self; +} + +- (void)setData:(id)data +{ + _data = data; + + ZBWGridViewData *a = (ZBWGridViewData *)_data; + [self setChoosed:a.isChoosed]; +} + +#pragma mark 子类重写 +- (void)setEdit:(BOOL)isEditing +{} + +- (void)setChoosed:(BOOL)Choosed +{} +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridView.h b/ZBWUIKit/CustomViews/GridView/ZBWGridView.h new file mode 100644 index 0000000..fb1f7ba --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridView.h @@ -0,0 +1,72 @@ +// +// GridView.h +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import +//#import "PullTableView.h" +#import "ZBWGridCell.h" +@class ZBWGridView; +/** + * 格网控件的代理 + */ +@protocol ZBWGridViewDelegate + +// 点击格网按钮 +- (void)onClickGridBtn:(ZBWGridView *)gridView data:(id)data; + +// 设置格网的列数 +- (NSInteger)numOfColumns:(ZBWGridView *)gridView ; + +// 设置格网行高 +- (float)heightOfRow:(ZBWGridView *)gridView; + +// 设置格网按钮间距 +- (ZBWAlign)alignOfCellBtn:(ZBWGridView *)gridView; + +@optional +- (void)onChange:(ZBWGridView *)gridView; //modified by chester.lee 外面要知道里面的数据变化 + +// 下拉,刷新格网 +- (void)onGridViewRefresh:(ZBWGridView *)gridView; + +// 上拉,加载更多 +- (void)onGridViewLoadMore:(ZBWGridView *)gridView; + +@end + +@interface ZBWGridView : UIView +{ + UITableView *_tableView; // 列表 + NSMutableArray *_items; + + BOOL _isEditing; // 是否为编辑状态 + NSMutableArray *_selectedArray; + +} +@property(nonatomic, weak)id delegate; +@property(nonatomic, retain)NSMutableArray *items; +@property(nonatomic, retain)NSMutableArray *selectedArray; +@property(nonatomic, readonly) UITableView *tableView; +@property(nonatomic) Class cellClazz; + +// 空白区域占位view的颜色。比如一行最多显示3个,但是最后一行只显示了1个,那么后面两个使用占位view。 默认为clear。 +@property(nonatomic, retain) UIColor *spaceAreaColor; + + +- (void)setEdit:(BOOL)isEdit; + +// 用于定制cell +- (Class)cellClass; + +- (CGRect)getTableViewFrame:(CGRect)bounds; + +- (void)reloadData; + +- (void)setHasNext:(BOOL)hasNext; + +- (const NSMutableArray *)getSelectedItems; +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWGridView.m b/ZBWUIKit/CustomViews/GridView/ZBWGridView.m new file mode 100644 index 0000000..4997b65 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWGridView.m @@ -0,0 +1,244 @@ +// +// GridView.m +// iSing +// +// Created by bwzhu on 13-6-25. +// Copyright (c) 2013年 iflytek. All rights reserved. +// + +#import "ZBWGridView.h" +#import "ZBWGridCell.h" +#import "ZBWGridCellButton.h" +@implementation ZBWGridView + +@synthesize delegate = _delegate, items = _items; +@synthesize selectedArray = _selectedArray; + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self initSubViews]; + } + return self; +} + +- (instancetype)init { + if (self = [super init]) { + [self initSubViews]; + } + return self; +} + +- (void)setFrame:(CGRect)frame { + super.frame = frame; + _tableView.frame = [self getTableViewFrame:self.bounds]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + _tableView.frame = [self getTableViewFrame:self.bounds]; +} + +- (void)initSubViews { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:[self getTableViewFrame:self.bounds]]; + _tableView.delegate = self; + _tableView.dataSource = self; + // _tableView.pullDelegate = self; + [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; + [self addSubview:_tableView]; + } +} + +#pragma mark 外部调用 + +- (UITableView *)tableView +{ + return _tableView; +} + +- (const NSMutableArray *)getSelectedItems +{ + if (_isEditing) + { + return _selectedArray; + } + return nil; +} + +- (void)reloadData +{ + [_tableView reloadData]; +// _tableView.pullTableIsRefreshing = NO; +// _tableView.pullTableIsLoadingMore = NO; +} + +- (void)setHasNext:(BOOL)hasNext +{ +// [_tableView setHasNext:hasNext]; +} + +- (void)setEdit:(BOOL)isEdit +{ + if (_isEditing == isEdit) + { + return; + } + _isEditing = isEdit; + _selectedArray = nil; + [self reloadData]; +} + +#pragma 子类重写 + +- (Class)cellClass +{ + return [ZBWGridCell class]; +} + +- (CGRect)getTableViewFrame:(CGRect)bounds +{ + return bounds; +} + +#pragma mark UITableViewDelegate +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return [_delegate heightOfRow:self]; +} + +#pragma mark + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + NSInteger count = _items.count; + NSInteger column = [_delegate numOfColumns:self]; + if (count == 0) + { + return 0; + } + if (column != 0) + { + if (count % column == 0) + { + return count / column; + } + else + { + return count / column + 1; + } + } + return 1; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + static NSString *identifier = @"gridView"; + ZBWGridCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + if (!cell) + { + Class cellClass = self.cellClazz; + if (!cellClass) { + cellClass = [self cellClass]; + } + cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + cell.spaceAreaColor = self.spaceAreaColor; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + [cell setAlign:[_delegate alignOfCellBtn:self]]; + cell.delegate = self; + } + // 获取cell对应的数据 + NSInteger index = indexPath.row; + NSInteger columnCount = [_delegate numOfColumns:self]; + NSMutableArray *items = [NSMutableArray arrayWithCapacity:columnCount]; + for (NSInteger i = index * columnCount; i < _items.count; i++) + { + ZBWGridViewData *data = [[ZBWGridViewData alloc] init]; + data.index = i; + data.data = [_items objectAtIndex:i]; + data.isChoosed = [_selectedArray containsObject:data.data]; + [items addObject:data]; + if (items.count == columnCount) + { + break; + } + } + // 设置cell对应的数据 + [cell setDataArray:items colume:columnCount]; + [cell setEdit:_isEditing]; + return cell; +} + +#pragma mark GridCellDelegate + +- (void)onGridButtonClick:(id)item +{ + if (_delegate && [_delegate respondsToSelector:@selector(onClickGridBtn:data:)]) { + [_delegate onClickGridBtn:self data:item]; + } +} + +- (void)onSelectItem:(ZBWGridCell *)gridCell dataItem:(id)item isSelected:(BOOL)selected +{ + if (!_selectedArray) + { + _selectedArray = [[NSMutableArray alloc] init]; + } + if (selected) + { + if (![_selectedArray containsObject:item]) + { + [_selectedArray addObject:item]; + } + } + else + { + if ([_selectedArray containsObject:item]) + { + [_selectedArray removeObject:item]; + } +} + + + // added by chester.lee 2013-1-20,外部要清楚里面的变化 + if (_delegate && [_delegate respondsToSelector:@selector(onChange:)]) { + [_delegate onChange:self]; + } + +} + +- (void)onDoNothing +{ + [_tableView reloadData]; +// _tableView.pullTableIsLoadingMore = NO; +// _tableView.pullTableIsRefreshing = NO; +} + +//#pragma mark PullTableViewDelegate +//- (void)pullTableViewDidTriggerRefresh:(PullTableView*)pullTableView +//{ +// if (_delegate && [_delegate respondsToSelector:@selector(onGridViewRefresh:)]) +// { +// [_delegate onGridViewRefresh:self]; +// } +// else +// { +// [self performSelector:@selector(onDoNothing) withObject:nil afterDelay:0.2]; +// } +//} +// +//- (void)pullTableViewDidTriggerLoadMore:(PullTableView*)pullTableView +//{ +// if (_delegate && [_delegate respondsToSelector:@selector(onGridViewLoadMore:)]) +// { +// [_delegate onGridViewLoadMore:self]; +// } +// else +// { +// [self performSelector:@selector(onDoNothing) withObject:nil afterDelay:0.2]; +// } +//} + +@end diff --git a/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.h b/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.h new file mode 100644 index 0000000..d4a499b --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.h @@ -0,0 +1,40 @@ +// +// ZBWPageableGridView.h +// Orange +// +// Created by 朱博文 on 2018/11/22. +// Copyright © 2018年 朱博文. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + + +@class ZBWPageableGridView; +@protocol ZBWPageableGridViewDelegate + +@required +- (ZBWGridView *)zbwPageableGridView:(ZBWPageableGridView *)pageableGridView atIndex:(NSInteger)index; + +- (NSInteger)numberOfPagesInZbwPageableGridView:(ZBWPageableGridView *)pageableGridView; + +@end + +@interface ZBWPageableGridView : UIView + +@property (nonatomic, weak) id delegate; + +//@property (nonatomic, retain) NSMutableArray *items; + +- (void)setPagePointImage:(UIImage *)image; + +- (void)reloadData; + +- (ZBWGridView *)dequeueReusableGridView:(NSInteger)index; + +- (void)showAtIndex:(NSInteger)index; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.m b/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.m new file mode 100644 index 0000000..fb4df54 --- /dev/null +++ b/ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.m @@ -0,0 +1,252 @@ +// +// ZBWPageableGridView.m +// Orange +// +// Created by 朱博文 on 2018/11/22. +// Copyright © 2018年 朱博文. All rights reserved. +// + +#import "ZBWPageableGridView.h" +#import "ZBWPageControlView.h" + + +#define kZBWPageableGridView_PageViewHeight 20 + +@interface ZBWPageableGridView () + +// +@property (nonatomic, strong) UIScrollView *scrollView; +// 翻页控件 +@property (nonatomic, retain) UIView *pageView; +@property (nonatomic, retain) ZBWPageControlView *pageControlView; +@property (nonatomic, retain) NSMutableArray *reusableGridViewList; +@property (nonatomic, retain) NSMutableDictionary *usingGridViewMap; + +// 当前页码 +@property (nonatomic, assign) NSInteger currentPageIndex; +// 总页数 +@property (nonatomic, assign) NSInteger totalPages; + +@property (nonatomic, retain) NSArray *showIndexs; + +@end + +@implementation ZBWPageableGridView + +- (instancetype)init { + if (self = [super init]) { + [self initSubViews]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self initSubViews]; + } + return self; +} + +- (void)initSubViews { + [self addSubview:self.scrollView]; + [self addSubview:self.pageView]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.scrollView.frame = self.bounds; + self.pageView.frame = CGRectMake(0, self.height - kZBWPageableGridView_PageViewHeight, self.width, kZBWPageableGridView_PageViewHeight); + self.pageControlView.centerX = self.pageView.width/2; + self.pageControlView.centerY = self.pageView.height/2; +} + +- (void)setPagePointImage:(UIImage *)image { + self.pageControlView.pointImage = image; +} + +- (void)showAtIndex:(NSInteger)index { + if (index >= self.totalPages) { + return; + } + self.currentPageIndex = index; + + CGFloat width = CGRectGetWidth(self.scrollView.bounds); + self.scrollView.contentOffset = CGPointMake(index*width, 0); +} + +- (ZBWGridView *)dequeueReusableGridView:(NSInteger)index { + ZBWGridView *gridView = self.usingGridViewMap[@(index)]; + if (!gridView) { + gridView = self.reusableGridViewList.lastObject; + if (gridView) { + [self.reusableGridViewList removeObject:gridView]; + } + } + + NSLog(@"pageableGridView 获取复用队列数据 %ld , %p", (long)index, gridView); + return gridView; +} + +- (void)reloadData { + // 将items进行分组 + if ([self.delegate respondsToSelector:@selector(numberOfPagesInZbwPageableGridView:)]) { + self.totalPages = [self.delegate numberOfPagesInZbwPageableGridView:self]; + } else { + self.totalPages = 1; + } + + // 如果之前停留的页面比当前最大页面还大,则当前停留在最后一页 + if (self.totalPages > 0 && self.currentPageIndex > self.totalPages - 1) { + self.currentPageIndex = self.totalPages - 1; + } else { + self.currentPageIndex = MAX(self.currentPageIndex, 0); + } + + NSArray *reloadIndex = nil; + if (!self.showIndexs) { + reloadIndex = @[@(0)]; + } else { + if ([(NSNumber *)self.showIndexs.lastObject integerValue] < self.totalPages) { + reloadIndex = self.showIndexs; + } else { + reloadIndex = @[@(self.totalPages - 1)]; + } + } + + // 刷新当前显示的页面 + [self showIndexs:self.showIndexs ?: @[@(0)] force:YES]; +} + +- (ZBWGridView *)gridViewAtIndex:(NSInteger)index { + ZBWGridView *gridView = [self.delegate zbwPageableGridView:self atIndex:index]; + gridView.frame = CGRectMake(index * self.scrollView.width, 0, self.scrollView.width, self.scrollView.height); + return gridView; +} + +- (void)setGridView:(ZBWGridView *)gridView atIndex:(NSInteger)index { + if (!gridView) { + return; + } + [self.scrollView addSubview:gridView]; + gridView.left = index * self.scrollView.width; + self.usingGridViewMap[@(index)] = gridView; +} + +- (void)addToReuseList:(ZBWGridView *)gridView index:(NSInteger)index{ + [gridView removeFromSuperview]; + [self.reusableGridViewList addObject:gridView]; + [self.usingGridViewMap removeObjectForKey:@(index)]; + + NSLog(@"pageableGridView 加入到复用队列 %ld , %p", (long)index, gridView); +} + +- (void)showIndexs:(NSArray *)indexs force:(BOOL)isForce { + if (!isForce) { + if (self.showIndexs && indexs && [[self.showIndexs componentsJoinedByString:@"|"] isEqualToString:[indexs componentsJoinedByString:@"|"]]) { + return; + } + } + self.showIndexs = indexs; + // 回收不需要显示的gridview + NSArray *useringKeys = self.usingGridViewMap.allKeys; + for (int i = 0 ; i < useringKeys.count; i++) { + NSNumber *key = useringKeys[i]; + if (![indexs containsObject:key]) { + [self addToReuseList:self.usingGridViewMap[key] index:key.integerValue]; + } + } + + // 显示需要的gridView + [indexs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSNumber *indexNum = obj; + ZBWGridView *gridView = [self gridViewAtIndex:indexNum.integerValue]; + + [self setGridView:gridView atIndex:indexNum.integerValue]; + [gridView reloadData]; + }]; +} + +#pragma mark- UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil]; + CGFloat offsetX = scrollView.contentOffset.x; + CGFloat width = scrollView.bounds.size.width; + + NSMutableArray *showIndexArray = [NSMutableArray arrayWithCapacity:2]; + NSInteger index = offsetX / width; + CGFloat x = offsetX - index * width; + + [showIndexArray addObject:@(index)]; + if (x > 0 && index + 1 < self.totalPages) { + [showIndexArray addObject:@(index + 1)]; + } + + [self showIndexs:showIndexArray force:NO]; + + self.currentPageIndex = MAX(MIN((offsetX + width/2) /width, self.totalPages), 0); +} + + +#pragma mark - Getter / Setter + +- (void)setTotalPages:(NSInteger)totalPages { + _totalPages = totalPages; + + self.scrollView.contentSize = CGSizeMake(self.scrollView.width * totalPages, self.scrollView.height); + self.pageControlView.numberOfPages = (int)totalPages; + self.pageControlView.centerX = self.pageView.width/2; + self.pageControlView.centerY = self.pageView.height/2; +} + +- (void)setCurrentPageIndex:(NSInteger)currentPageIndex { + _currentPageIndex = currentPageIndex; + self.pageControlView.currentPage = (int)currentPageIndex; +} + +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _scrollView.delegate = self; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.pagingEnabled = YES; + _scrollView.bounces = YES; + } + return _scrollView; +} + +- (UIView *)pageView { + if (!_pageView) { + _pageView = [[UIView alloc] initWithFrame:CGRectMake(0, self.height - kZBWPageableGridView_PageViewHeight, self.width, kZBWPageableGridView_PageViewHeight)]; + _pageView.backgroundColor = kZBW_Color_Clear; + + [_pageView addSubview:self.pageControlView]; + } + return _pageView; +} + +- (ZBWPageControlView *)pageControlView { + if (!_pageControlView) { + _pageControlView = [[ZBWPageControlView alloc] init]; + } + return _pageControlView; +} + +- (NSMutableArray *)reusableGridViewList { + if (!_reusableGridViewList) { + _reusableGridViewList = [NSMutableArray arrayWithCapacity:5]; + } + return _reusableGridViewList; +} + +- (NSMutableDictionary *)usingGridViewMap { + if (!_usingGridViewMap) { + _usingGridViewMap = [NSMutableDictionary dictionaryWithCapacity:3]; + } + return _usingGridViewMap; +} + +@end diff --git a/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.h b/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.h new file mode 100644 index 0000000..a1bc2af --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.h @@ -0,0 +1,24 @@ +// +// ZBWImageTagItemView.h +// ZBWUIKit +// +// Created by 朱博文 on 2021/3/24. +// + +#import "ZBWTagItemView.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + 左图片,右文本的check view + */ +@interface ZBWImageTagItemView : ZBWTagItemView + +// 选中状态下的图片 +@property (nonatomic) UIImage *selectImage; +// 未选中状态下的图片 +@property (nonatomic) UIImage *normalImage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.m b/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.m new file mode 100644 index 0000000..0290fe9 --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.m @@ -0,0 +1,112 @@ +// +// ZBWImageTagItemView.m +// ZBWUIKit +// +// Created by 朱博文 on 2021/3/24. +// + +#import "ZBWImageTagItemView.h" +#import + +@interface ZBWImageTagItemView () + +@property (nonatomic) UIImageView *imageView; +@property (nonatomic) UILabel *titleLabel; + +@end + +@implementation ZBWImageTagItemView + +- (instancetype)initWithIdentify:(NSString *)identify { + if (self = [super init]) { + self.padding = UIEdgeInsetsMake(5, 5, 5, 5); + self.selectedBgColor = kZBW_Color_Orange; + self.selectedTextColor = kZBW_Color_White; + self.selectedFont = kZBW_Font_Micro; + self.selectedBorderColor = kZBW_Color_Orange; + + self.normalBgColor = kZBW_Color_White; + self.normalTextColor = kZBW_Color_Orange; + self.normalFont = kZBW_Font_Micro; + self.normalBorderColor = kZBW_Color_Orange; + + objc_setAssociatedObject(self, ZBWTagItemView_Identify_Key, identify, OBJC_ASSOCIATION_COPY); + } + self.frame = CGRectMake(0, 0, kZBW_SCREEN_WIDTH, 40); + [self addSubview:self.imageView]; + [self addSubview:self.titleLabel]; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onBtnClicked)]; + [self addGestureRecognizer:tapGesture]; + + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + self.imageView.left = self.padding.left; + self.imageView.centerY = self.height / 2; + + self.titleLabel.left = self.imageView.right + 5; + self.titleLabel.centerY = self.height / 2; +} + +- (void)setTitle:(NSString *)title { + self.titleLabel.text = title; +} + + +- (void)updateUI { + if (self.isSelected) { + [self tagItemViewStateSelected]; + } else { + [self tagItemViewStateNormal]; + } +} + +#pragma mark overrider +- (CGSize)sizeThatFits:(CGSize)size { +// CGFloat height = [@"全" boundingRectWithSize:CGRectMake(0, 0, 100, 30).size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : kZBW_Font_Small} context:nil].size.height; + // |-padding-imageview-间隔-title label-padding-| + [self.titleLabel sizeToFit]; + CGFloat width = self.imageView.width + 5 + self.titleLabel.width; + CGFloat height = 15; + width += 10*2; + height += (self.padding.top + self.padding.bottom); + width += (self.padding.left + self.padding.right); + + return CGSizeMake(width, height); +} + +#pragma mark- +- (void)tagItemViewStateNormal { + self.imageView.image = self.normalImage; + self.titleLabel.textColor = self.normalTextColor; + self.titleLabel.font = self.normalFont; +} + +- (void)tagItemViewStateSelected { + self.imageView.image = self.selectImage; + self.titleLabel.textColor = self.selectedTextColor; + self.titleLabel.font = self.selectedFont; +} + +#pragma mark- Getter / Setter + +- (UIImageView *)imageView { + if (!_imageView) { + _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 18, 18)]; + } + return _imageView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(23, 0, 60, 25)]; + } + + return _titleLabel; +} + +@end diff --git a/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.h b/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.h new file mode 100644 index 0000000..fa7e67e --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.h @@ -0,0 +1,75 @@ +// +// TagButton.h +// Orange +// +// Created by 朱博文 on 2017/11/1. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import + +extern const void *ZBWTagItemView_Identify_Key; + +@class ZBWTagItemView; +typedef void(^ZBWTagItemViewSelectedChangedBlock)(BOOL isSelected, ZBWTagItemView *tagItemView); +typedef void(^ZBWTagItemViewDeleteClickBlock)(ZBWTagItemView *tagItemView); +typedef BOOL(^ZBWTagItemViewShouldEditingBlock)(ZBWTagItemView *tagItemView); + +typedef NS_ENUM(NSInteger, ZBWTagItemViewStyle) { + ZBWTagItemViewStyle_Default = 0, // 无样式 + ZBWTagItemViewStyle_CornerRadius = 1, // 圆角,半径=4 + ZBWTagItemViewStyle_Circular = 2 // 半径=高度/2 +}; + +typedef NS_ENUM(NSInteger, ZBWTagItemViewLineStyle) { + ZBWTagItemViewLineStyle_Solid = 0, // 实线 + ZBWTagItemViewLineStyle_Dashed // 虚线 +}; + + +@protocol ZBWTagItemViewUIProtocol + +@optional +- (void)tagItemViewStateNormal; + +- (void)tagItemViewStateSelected; + +- (void)tagItemViewStateEditing; + +@end + +@interface ZBWTagItemView : UIView + +@property (nonatomic, assign) BOOL isSelected; +@property (nonatomic, assign) BOOL isEditing; + +- (instancetype)initWithIdentify:(NSString *)identify ; + +@property (nonatomic, readonly) NSString *identify; // reuse identify + +// 样式 +@property (nonatomic, assign)ZBWTagItemViewStyle style; +@property (nonatomic, assign) ZBWTagItemViewLineStyle lineStyle; +@property (nonatomic) UIColor *selectedBgColor; +@property (nonatomic) UIColor *selectedBorderColor; +@property (nonatomic) UIColor *normalBgColor; +@property (nonatomic) UIColor *normalBorderColor; + +@property (nonatomic) UIColor *selectedTextColor; +@property (nonatomic) UIColor *normalTextColor; +@property (nonatomic) UIFont *selectedFont; +@property (nonatomic) UIFont *normalFont; + +@property (nonatomic) UIColor *searchHighlightTextColor; +@property (nonatomic, assign) NSRange searchHightlightRange; + +@property (nonatomic, copy) NSString *title; +@property (nonatomic, assign) UIEdgeInsets padding; + +// 状态回调 +//@property (nonatomic, copy) ZBWTagItemViewSelectedChangedBlock selectedChangeBlock; +@property (nonatomic, copy) ZBWTagItemViewShouldEditingBlock shouldEditingBlock; + +- (void)updateUI; + +@end diff --git a/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.m b/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.m new file mode 100644 index 0000000..7d42c73 --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWTagItemView.m @@ -0,0 +1,359 @@ +// +// TagButton.m +// Orange +// +// Created by 朱博文 on 2017/11/1. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import "ZBWTagItemView.h" +#import + +const void *ZBWTagItemView_Identify_Key = &ZBWTagItemView_Identify_Key; + + + +@interface ZBWTagDeleteView : UIView +@end + +@implementation ZBWTagDeleteView + +- (void)drawRect:(CGRect)rect { + self.backgroundColor = [UIColor clearColor]; + self.layer.cornerRadius = CGRectGetMaxX(rect)/2; + self.layer.masksToBounds = YES; + + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextClearRect(context, rect); + CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); + CGContextFillRect(context, rect); + +// CGContextAddEllipseInRect(context, rect); +// CGContextClip(context); +// +// CGContextclip +// CGContextAddEllipseInRect(context, rect); +// CGContextSetFillColorWithColor(context, kZBW_Color_Red.CGColor); +// CGContextFillPath(context); + + + CGContextMoveToPoint(context, 0, 0); + CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect)); + CGContextMoveToPoint(context, 0, CGRectGetMaxY(rect)); + CGContextAddLineToPoint(context, CGRectGetMaxX(rect), 0); + CGContextSetLineWidth(context, 1); + CGContextSetStrokeColorWithColor(context, kZBW_Color_White.CGColor); + CGContextStrokePath(context); +} + +@end + + +@interface ZBWTagItemView() + +@property (nonatomic) CAShapeLayer *shapeLayer; +@property (nonatomic) UIButton *contentBtn; +@property (nonatomic) ZBWTagDeleteView *defaultDeleteView; // 删除 + +@end + +@implementation ZBWTagItemView + +- (instancetype)initWithIdentify:(NSString *)identify { + if (self = [super init]) { + self.padding = UIEdgeInsetsMake(5, 5, 5, 5); + self.selectedBgColor = kZBW_Color_Orange; + self.selectedTextColor = kZBW_Color_White; + self.selectedFont = kZBW_Font_Micro; + self.selectedBorderColor = kZBW_Color_Orange; + + self.normalBgColor = kZBW_Color_White; + self.normalTextColor = kZBW_Color_Orange; + self.normalFont = kZBW_Font_Micro; + self.normalBorderColor = kZBW_Color_Orange; + + objc_setAssociatedObject(self, ZBWTagItemView_Identify_Key, identify, OBJC_ASSOCIATION_COPY); + } + [self addSubview:self.contentBtn]; + self.frame = CGRectMake(0, 0, kZBW_SCREEN_WIDTH, 40); + + self.style = _style; +// [self updateUI]; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onBtnClicked)]; + [self addGestureRecognizer:tapGesture]; + + UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressed:)]; + longPressGesture.minimumPressDuration = .6; + [self addGestureRecognizer:longPressGesture]; + + return self; +} + + +- (void)didMoveToSuperview { + if (self.superview) { +// [self updateUI]; + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect rect = CGRectMake(self.padding.left, self.padding.top, self.width - self.padding.left - self.padding.right, self.height - self.padding.top - self.padding.bottom); + + self.contentBtn.frame = rect; + _defaultDeleteView.right = self.bounds.size.width; + self.style = _style; + + [self resetLayer]; +} + +- (void)resetLayer { + if (_shapeLayer) { + UIBezierPath *path = nil; + if (self.style == ZBWTagItemViewStyle_CornerRadius) { + path = [UIBezierPath bezierPathWithRoundedRect:self.contentBtn.bounds cornerRadius:4]; + } else if (self.style == ZBWTagItemViewStyle_Circular) { + path = [UIBezierPath bezierPathWithRoundedRect:self.contentBtn.bounds cornerRadius:self.contentBtn.bounds.size.height/2]; + } + _shapeLayer.path = path.CGPath; + _shapeLayer.frame = self.contentBtn.bounds; + } +} + +- (NSString *)identify { + return objc_getAssociatedObject(self, ZBWTagItemView_Identify_Key); +} + +- (void)setTitle:(NSString *)title { + _title = title; + [self.contentBtn setTitle:title forState:UIControlStateNormal]; + +// [self updateUI]; +} + +- (void)setStyle:(ZBWTagItemViewStyle)style { + _style = style; + switch (style) { + case ZBWTagItemViewStyle_Default: + { + self.contentBtn.layer.cornerRadius = 0; + self.contentBtn.layer.masksToBounds = NO; + } + break; + case ZBWTagItemViewStyle_CornerRadius: + { + self.contentBtn.layer.cornerRadius = 4; + self.contentBtn.layer.masksToBounds = YES; + } + break; + case ZBWTagItemViewStyle_Circular: + { + self.contentBtn.layer.cornerRadius = self.contentBtn.height/2; + self.contentBtn.layer.masksToBounds = YES; + } + break; + + default: + break; + } +} + +- (void)setLineStyle:(ZBWTagItemViewLineStyle)lineStyle { + _lineStyle = lineStyle; +// switch (lineStyle) { +// case ZBWTagItemViewLineStyle_Solid: +// self.contentBtn.layer. +// break; +// +// default: +// break; +// } +} + +- (void)updateUI { + if (_isSelected) { + [self tagItemViewStateSelected]; + } else { + [self tagItemViewStateNormal]; + } +} + +- (void)setIsSelected:(BOOL)isSelected { + if (_isSelected == isSelected) { + return; + } + _isSelected = isSelected; +// [self updateUI]; +// self.selectedChangeBlock ? self.selectedChangeBlock(_isSelected, self) : nil; +} + +- (void)setIsEditing:(BOOL)isEditing { + if (!self.shouldEditingBlock || !self.shouldEditingBlock(self)) { + return; + } + if (_isEditing == isEditing) { + return; + } + _isEditing = isEditing; +// [self updateUI]; +} + + +#pragma mark overrider +- (CGSize)sizeThatFits:(CGSize)size { +// CGFloat height = [@"全" boundingRectWithSize:CGRectMake(0, 0, 100, 30).size options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : kZBW_Font_Small} context:nil].size.height; + + CGSize aSize = [self.contentBtn sizeThatFits:CGSizeMake(kZBW_SCREEN_WIDTH, kZBW_SCREEN_HEIGHT)]; + aSize.width += 10*2; + aSize.height += (self.padding.top + self.padding.bottom); + aSize.width += (self.padding.left + self.padding.right); + return aSize; +} + +#pragma mark- +- (void)tagItemViewStateNormal { + if (self.isEditing) { + [self addSubview:self.defaultDeleteView]; + } else { + [_defaultDeleteView removeFromSuperview]; + } + if (self.lineStyle == ZBWTagItemViewLineStyle_Dashed) { + self.contentBtn.layer.borderWidth = 0; + self.shapeLayer.strokeColor = self.normalBorderColor.CGColor; + [self.contentBtn.layer addSublayer:self.shapeLayer]; + } else { + [_shapeLayer removeFromSuperlayer]; + self.contentBtn.layer.borderWidth = 1; + } + + self.contentBtn.backgroundColor = self.normalBgColor; + self.contentBtn.layer.borderColor = self.normalBorderColor.CGColor; + self.contentBtn.titleLabel.font = self.normalFont; + [self.contentBtn setTitleColor:self.normalTextColor forState:UIControlStateNormal]; + + if (self.searchHighlightTextColor && _title.length > 0) { + NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:_title]; + if (self.searchHightlightRange.length > 0) { + [attrStr addAttribute:NSForegroundColorAttributeName value:self.searchHighlightTextColor range:self.searchHightlightRange]; + } + + self.contentBtn.titleLabel.attributedText = attrStr; + } + +// if (self.searchHightlightRange.length > 0 && self.searchHighlightTextColor && _title.length > 0) { +// NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:_title]; +// [attrStr addAttribute:NSForegroundColorAttributeName value:self.searchHighlightTextColor range:self.searchHightlightRange]; +// self.contentBtn.titleLabel.attributedText = attrStr; +// } else { +// if (self.searchHighlightTextColor) { +// self.contentBtn.titleLabel.attributedText = [[NSAttributedString alloc] initWithString:_title]; +// } +// } +} + +- (void)tagItemViewStateSelected { + if (self.isEditing) { + [self addSubview:self.defaultDeleteView]; + } else { + [_defaultDeleteView removeFromSuperview]; + } + self.contentBtn.backgroundColor = self.selectedBgColor; + if (self.lineStyle == ZBWTagItemViewLineStyle_Dashed) { + self.contentBtn.layer.borderWidth = 0; + + self.shapeLayer.strokeColor = self.selectedBorderColor.CGColor; + [self.contentBtn.layer addSublayer:self.shapeLayer]; + } else { + [_shapeLayer removeFromSuperlayer]; + self.contentBtn.layer.borderWidth = 1; + } + + self.contentBtn.layer.borderColor = self.selectedBorderColor.CGColor; + self.contentBtn.titleLabel.font = self.selectedFont; + [self.contentBtn setTitleColor:self.selectedTextColor forState:UIControlStateNormal]; + + if (self.searchHighlightTextColor) { + self.contentBtn.titleLabel.attributedText = [[NSAttributedString alloc] initWithString:_title]; +// self.contentBtn.titleLabel.attributedText = nil; + } +} + + +#pragma mark- Event + +- (void)onBtnClicked { + if (_isEditing) { + if (self.shouldEditingBlock && self.shouldEditingBlock(self)) { + ZBW_SendUpSignal(@"tagItemViewRemoveClicked", self, nil, self); + } + } else { + ZBW_SendUpSignal(@"tagItemViewClicked", self, nil, self); + } +} + +- (void)onLongPressed:(UILongPressGestureRecognizer *)sender { + if (sender.state == UIGestureRecognizerStateBegan) { + ZBW_SendUpSignal(@"tagItemViewLongPressed", self, nil, self); + } +} + +- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents { + NSAssert(NO, @"不允许在外部设置TagItemView的点击事件"); +} + +#pragma mark- Getter/Setter + +- (UIButton *)contentBtn { +// __weakSelf + if (!_contentBtn) { + _contentBtn = [[UIButton alloc] initWithFrame:self.bounds]; + _contentBtn.userInteractionEnabled = NO; +// _contentBtn.zbwClickCallback = ^{ +// [__weakedSelf onBtnClicked]; +// }; + } + return _contentBtn; +} + +- (ZBWTagDeleteView *)defaultDeleteView { + if (!_defaultDeleteView) { + _defaultDeleteView = [[ZBWTagDeleteView alloc] initWithFrame:CGRectMake(self.width - 12, 0, 12, 12)]; + } + return _defaultDeleteView; +} + +-(CAShapeLayer *)shapeLayer{ + + if (!_shapeLayer) { + + _shapeLayer = [CAShapeLayer layer]; + + _shapeLayer.strokeColor = self.normalBorderColor.CGColor; + + _shapeLayer.fillColor = [UIColor clearColor].CGColor; + + UIBezierPath *path = nil; + if (self.style == ZBWTagItemViewStyle_CornerRadius) { + path = [UIBezierPath bezierPathWithRoundedRect:self.contentBtn.bounds cornerRadius:4]; + } else if (self.style == ZBWTagItemViewStyle_Circular) { + path = [UIBezierPath bezierPathWithRoundedRect:self.contentBtn.bounds cornerRadius:self.contentBtn.bounds.size.height/2]; + } + _shapeLayer.path = path.CGPath; + + _shapeLayer.frame = self.contentBtn.bounds; + + _shapeLayer.lineWidth = 1; + + _shapeLayer.lineCap = @"square"; + + _shapeLayer.lineDashPattern = @[@3, @3]; + + } + + return _shapeLayer; + +} + +@end diff --git a/ZBWUIKit/CustomViews/TagView/ZBWTagView.h b/ZBWUIKit/CustomViews/TagView/ZBWTagView.h new file mode 100644 index 0000000..52e174e --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWTagView.h @@ -0,0 +1,79 @@ +// +// ZBWTagView.h +// Orange +// +// Created by 朱博文 on 2017/10/31. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import +#import "ZBWTagItemView.h" + +typedef NS_ENUM(NSInteger, ZBWTagView_ShowType) { + ZBWTagView_ShowType_OneLine = 0, // 单行显示,左右滚动 + ZBWTagView_ShowType_MultiLine = 1 // 多行显示,上下滚动 +}; + +typedef NS_ENUM(NSInteger, ZBWTagView_SelectType) { + ZBWTagView_SelectType_CannotSelect = 0, // 不可选 + ZBWTagView_SelectType_SingleSelect = 1, // 单选 + ZBWTagView_SelectType_MultiSelect = 2 // 多选 +}; + +@class ZBWTagView; + +typedef NSInteger (^CountOfTagInTagViewCallback)(ZBWTagView *tagView); +typedef ZBWTagItemView *(^TagItemViewOfTagViewCallback)(ZBWTagView *tagView, NSInteger index); +typedef void(^TagItemViewSelectedChangedCallback)(ZBWTagView *tagView, BOOL isSelected, NSInteger index); +typedef void(^TagItemViewDeleteClickCallback)(ZBWTagView *tagView, NSInteger index); +typedef void(^TagItemViewLongPressCallback)(ZBWTagView *tagView, NSInteger index); + +@interface ZBWTagView : UIView + +// 显示类型 +@property (nonatomic, assign) ZBWTagView_ShowType showType; // 默认 TagView_ShowType_MultiLine +// 选择类型 +@property (nonatomic, assign) ZBWTagView_SelectType selectType; // 默认TagView_SelectType_SingleSelect + +// 边距 内边距 +@property (nonatomic, assign) UIEdgeInsets edge; // 默认UIEdgeInsetsMake(10, 10, 10, 10) +// 水平间距 TagItemView 水平间距 +@property (nonatomic, assign) CGFloat hSpace; // 默认10 +// 垂直间距 TagItemView 垂直间距 +@property (nonatomic, assign) CGFloat vSpace; // 默认15 + +// 是否自动调整高度,让内容完全显示。与maxHeight配合使用,最高不超过maxHeight。 +@property (nonatomic, assign) BOOL autoSizeHeight; // 默认 NO +@property (nonatomic, assign) CGFloat minHeight; // 默认0 +@property (nonatomic, assign) CGFloat maxHeight; // 默认0 + +// 宽度自适应 +@property (nonatomic, assign) BOOL autoSizeWidth; // 默认 NO +@property (nonatomic, assign) CGFloat minWidth; // 默认0 +@property (nonatomic, assign) CGFloat maxWidth; // 默认0 + + + +#pragma mark= Datasource callback +@property (nonatomic, copy) CountOfTagInTagViewCallback countOfTagInTagViewCallback; +@property (nonatomic, copy) TagItemViewOfTagViewCallback tagItemViewOfTagViewCallback; + +#pragma mark- Event callback +@property (nonatomic, copy) TagItemViewSelectedChangedCallback tagItemViewSelectedChangedCallback; +@property (nonatomic, copy) TagItemViewDeleteClickCallback tagItemViewDeleteClickCallback; +@property (nonatomic, copy) TagItemViewLongPressCallback tagItemViewLongPressCallback; + +@property (nonatomic, assign, readonly) BOOL isEditing; + + +- (void)setEditing:(BOOL)isEditing; + +- (void)reloadData; + +- (ZBWTagItemView *)reuseTagItemView:(NSString *)identify; + +- (ZBWTagItemView *)tagItemViewOfIndex:(NSInteger)index; +- (NSInteger)indexOfTagItemView:(ZBWTagItemView *)tagItemView; + + +@end diff --git a/ZBWUIKit/CustomViews/TagView/ZBWTagView.m b/ZBWUIKit/CustomViews/TagView/ZBWTagView.m new file mode 100644 index 0000000..3b194e1 --- /dev/null +++ b/ZBWUIKit/CustomViews/TagView/ZBWTagView.m @@ -0,0 +1,272 @@ +// +// ZBWTagView.m +// Orange +// +// Created by 朱博文 on 2017/10/31. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import "ZBWTagView.h" +#import "ZBWTagItemView.h" + +@interface ZBWTagView () + +// 显示的tag button list +@property (nonatomic) NSMutableArray *usingtagBtnList; +// reuse复用缓存 +@property (nonatomic) NSMutableDictionary *reuseMap; + +@property (nonatomic) UIScrollView *scrollView; + +@property (nonatomic, assign) BOOL isEditing; +@end + +@implementation ZBWTagView + +- (instancetype)init { + if (self = [super init]) { + [self initDefaultData]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self =[super initWithFrame:frame]) { + [self initDefaultData]; + } + return self; +} + +- (void)initDefaultData { + self.showType = ZBWTagView_ShowType_MultiLine; + self.selectType = ZBWTagView_SelectType_SingleSelect; + self.edge = UIEdgeInsetsMake(10, 10, 10, 10); + self.hSpace = 10; + self.vSpace = 15; +} + +- (void)reloadData { + [self addSubview:self.scrollView]; + // 所有tagItemView加入到reuse缓存中 + [self moveAllTagItemViewToReuseCache]; + + NSInteger count = self.countOfTagInTagViewCallback(self); + if (count == 0) { + // 高度重置 + return; + } + + for (int i = 0; i < count; i++) { + ZBWTagItemView *tagItemView = self.tagItemViewOfTagViewCallback(self, i); + tagItemView.isEditing = self.isEditing; + [tagItemView updateUI]; + NSAssert(tagItemView, @"【TagView】 tagItemView 不能为nil。"); + [tagItemView sizeToFit]; + [self.scrollView addSubview:tagItemView]; + // 加入到正在使用队列,删除对应的reuse缓存 + [self addToUsingList:tagItemView]; + } + + [self updateUI]; +} + +- (void)updateUI { + if (self.usingtagBtnList.count == 0) { + return; + } + + // int line = 0; + CGFloat originalX = self.edge.left; + CGFloat x = originalX; + CGFloat y = self.edge.top; + CGFloat width = self.width - self.edge.right; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" + CGFloat height = self.height; +#pragma clang diagnostic pop + CGFloat vSpace = self.vSpace; + CGFloat hSpace = self.hSpace; + + CGFloat lastLineHeight = 0; + + CGFloat maxWidth = 0; + + if (self.showType == ZBWTagView_ShowType_OneLine) { + for (int i = 0; i < [self.usingtagBtnList count]; i++) { + ZBWTagItemView *btn = [self.usingtagBtnList objectAtIndex:i]; + + btn.origin = CGPointMake(x, y); + x += (btn.width + hSpace); + lastLineHeight = btn.height; + } + + CGFloat totalWidth = x + self.edge.right - hSpace; + CGFloat totalHeight = y + lastLineHeight + self.edge.bottom; + self.scrollView.contentSize = CGSizeMake(totalWidth, totalHeight); + maxWidth = totalWidth; + } else if (self.showType == ZBWTagView_ShowType_MultiLine) { + for (int i = 0; i < [self.usingtagBtnList count]; i++) { + ZBWTagItemView *btn = [self.usingtagBtnList objectAtIndex:i]; + btn.width = MIN(btn.width, width); + + // 当前行不可以放得下 + if (x + btn.width > width) { + // 换行 + x = originalX; + y += (lastLineHeight + vSpace); + } + + btn.origin = CGPointMake(x, y); + x += (btn.width + hSpace); + lastLineHeight = btn.height; + + maxWidth = MAX(maxWidth, x + self.edge.right - hSpace); + } + + CGFloat totalHeight = y + lastLineHeight + self.edge.bottom; + self.scrollView.contentSize = CGSizeMake(maxWidth, totalHeight); + } + + // self 自动调整大小(高度) + if (self.autoSizeHeight) { + self.height = MAX(MIN((self.maxHeight > 0 ? self.maxHeight : self.scrollView.contentSize.height), self.scrollView.contentSize.height), self.minHeight); + } + + if (self.autoSizeWidth) { + self.width = MAX(MIN(self.maxWidth > 0 ? self.maxWidth : maxWidth, maxWidth), self.minWidth); + } + + // scrollView大小 + self.scrollView.frame = self.bounds; +} + +#pragma mark- Public +- (ZBWTagItemView *)reuseTagItemView:(NSString *)identify{ + NSMutableSet *reuseSet = [self reuseSet:identify]; + return [reuseSet anyObject]; +} + +- (ZBWTagItemView *)tagItemViewOfIndex:(NSInteger)index { + if (self.usingtagBtnList.count <= index) { + return nil; + } + return self.usingtagBtnList[index]; +} +- (NSInteger)indexOfTagItemView:(ZBWTagItemView *)tagItemView { + return [self.usingtagBtnList indexOfObject:tagItemView]; +} + + +- (void)addToUsingList:(ZBWTagItemView *)btn { + // 加入到using数组 + [self.usingtagBtnList addObject:btn]; + // 从reuse缓存中删除 + NSMutableSet *reuseSet = [self reuseSet:btn.identify]; + [reuseSet removeObject:btn]; +} + +// 把所有使用的btn加入到复用缓存 +- (void)moveAllTagItemViewToReuseCache { + for (ZBWTagItemView *tagBtn in self.usingtagBtnList) { + NSMutableSet *reuseSet = [self reuseSet:tagBtn.identify]; + [reuseSet addObject:tagBtn]; + } + // 清空using数组,移出页面 + [self.usingtagBtnList makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [self.usingtagBtnList removeAllObjects]; +} + +- (NSMutableSet *)reuseSet:(NSString *)identify { + if (!identify) { + identify = @"__TagView_NULL_identity__"; + } + NSMutableSet *reuseSet = [self.reuseMap objectForKey:identify]; + if (!reuseSet) { + reuseSet = [[NSMutableSet alloc] initWithCapacity:5]; + self.reuseMap[identify] = reuseSet; + } + return reuseSet; +} + +#pragma mark- Event + +ZBW_UISignal_Up_Handle(,) { + if (ZBW_Is_Signal(@"tagItemViewClicked")) { + signal.arrived = YES; + if (self.selectType == ZBWTagView_SelectType_CannotSelect) { + return; + } + ZBWTagItemView *tagItemView = signal.object; + NSInteger index = [self indexOfTagItemView:tagItemView]; + + if (self.selectType == ZBWTagView_SelectType_SingleSelect) { // 单选 + if (tagItemView.isSelected) { + return; + } + tagItemView.isSelected = YES; + [tagItemView updateUI]; + + // 之前已选中的按钮,设置为NO + for (ZBWTagItemView *btn in self.usingtagBtnList) { + if (btn != tagItemView && btn.isSelected) { // 之前选中的,设置为未选中 + btn.isSelected = NO; + [btn updateUI]; + self.tagItemViewSelectedChangedCallback ? self.tagItemViewSelectedChangedCallback(self, NO, [self.usingtagBtnList indexOfObject:btn]) : nil; + break; + } + } + self.tagItemViewSelectedChangedCallback ? self.tagItemViewSelectedChangedCallback(self, YES, index) : nil; + } else if (self.selectType == ZBWTagView_SelectType_MultiSelect) { // 多选 + tagItemView.isSelected = !tagItemView.isSelected; + [tagItemView updateUI]; + self.tagItemViewSelectedChangedCallback ? self.tagItemViewSelectedChangedCallback(self, tagItemView.isSelected, index) : nil; + } + } +} + +ZBW_UISignal_Up_Handle(ZBWTagItemView, tagItemViewRemoveClicked) { + signal.arrived = YES; + if (!self.isEditing) { + return; + } + ZBWTagItemView *tagItemView = signal.object; + self.tagItemViewDeleteClickCallback ? self.tagItemViewDeleteClickCallback(self, [self indexOfTagItemView:tagItemView]) : nil; +} + +ZBW_UISignal_Up_Handle(ZBWTagItemView, tagItemViewLongPressed) { + signal.arrived = YES; + ZBWTagItemView *tagItemView = signal.object; + self.tagItemViewLongPressCallback ? self.tagItemViewLongPressCallback(self, [self indexOfTagItemView:tagItemView]) : NULL; +} + +#pragma mark- Getter/Setter +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + } + return _scrollView; +} + +- (NSMutableDictionary *)reuseMap { + if (!_reuseMap) { + _reuseMap = [[NSMutableDictionary alloc] init]; + } + return _reuseMap; +} + +- (NSMutableArray *)usingtagBtnList { + if (!_usingtagBtnList) { + _usingtagBtnList = [[NSMutableArray alloc] initWithCapacity:5]; + } + return _usingtagBtnList; +} + +- (void)setEditing:(BOOL)isEditing { + if (_isEditing == isEditing) { + return; + } + _isEditing = isEditing; + [self reloadData]; +} + +@end diff --git a/ZBWUIKit/CustomViews/UITableView+ZBWAddition.h b/ZBWUIKit/CustomViews/UITableView+ZBWAddition.h new file mode 100644 index 0000000..d3436c7 --- /dev/null +++ b/ZBWUIKit/CustomViews/UITableView+ZBWAddition.h @@ -0,0 +1,40 @@ +// +// UITableView+ZBWAddition.h +// Orange +// +// Created by 朱博文 on 2017/5/22. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import + +@interface UITableView (ZBWAddition) + +// 删除多余的分割线 +- (void)zbw_disappearMoreSeparator; + +// tableview 的cell分割线,左边对齐 +- (void)zbw_separatorAlign; + +// iOS 11,默认开启self-sizing,导致cell刷新异常。在此关闭; +- (void)zbw_closeSelfSizing; + +@end + + +typedef NS_ENUM(NSInteger, ZBWTableEmptyState) { + ZBWTableEmptyState_Normal = 0, + ZBWTableEmptyState_SucceedAndEmpty, + ZBWTableEmptyState_ErrorAndEmpty, + ZBWTableEmptyState_Requesting +}; + +typedef void(^ZBWTableViewEmptyStateChangeBlock)(int oldState, int newState, UIView *emptyView); + +@interface UITableView (ZBWAddition_EmptyView) + +@property (nonatomic) UIView *zbw_emptyView; +@property (nonatomic, assign) NSInteger zbw_emptyState; +@property (nonatomic, copy) ZBWTableViewEmptyStateChangeBlock zbw_emptyStateChangeBlock; + +@end diff --git a/ZBWUIKit/CustomViews/UITableView+ZBWAddition.m b/ZBWUIKit/CustomViews/UITableView+ZBWAddition.m new file mode 100644 index 0000000..aaf37ed --- /dev/null +++ b/ZBWUIKit/CustomViews/UITableView+ZBWAddition.m @@ -0,0 +1,143 @@ +// +// UITableView+ZBWAddition.m +// Orange +// +// Created by 朱博文 on 2017/5/22. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import "UITableView+ZBWAddition.h" +#import + +#import "MJRefreshAutoNormalFooter.h" + +const void *UITableView_ZBWAddition_EmptyView_Key = &UITableView_ZBWAddition_EmptyView_Key; +const void *UITableView_ZBWAddition_EmptyView_EmptyState_Key = &UITableView_ZBWAddition_EmptyView_EmptyState_Key; +const void *UITableView_ZBWAddition_EmptyView_EmptyStateChange_Key = &UITableView_ZBWAddition_EmptyView_EmptyStateChange_Key; + + +@implementation UITableView (ZBWAddition_EmptyView) + ++ (void)load { +// return; + // hook reloadData 方法 + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class aClass = NSClassFromString(@"UITableView"); + SEL reloadSelector = @selector(reloadData); + Method reloadMethod = class_getInstanceMethod(aClass, reloadSelector); + + Method zbwReloadMethod = class_getInstanceMethod(aClass, @selector(zbw_reloadData)); + method_exchangeImplementations(reloadMethod, zbwReloadMethod); + }); +} + +- (void)zbw_reloadData { +// if (!self.superview) { +// return; +// } + + [self zbw_reloadData]; + + @try { + NSInteger count = self.visibleCells.count; + self.zbw_emptyView.hidden = count > 0; + self.mj_footer.hidden = count == 0; + } + @catch (NSException *e) { + + } + +// NSInteger count = 0; +// BOOL exceptioned = NO; +// @try { +// count = self.visibleCells.count; +// } +// @catch (NSException *e) { +// exceptioned = YES; +// } +// +// if (exceptioned) { +// +// @try { +// exceptioned = NO; +// NSInteger sections = [self.dataSource numberOfSectionsInTableView:self]; +// for (int i = 0 ; i < sections; i++) { +// NSInteger rows = [self.dataSource tableView:self numberOfRowsInSection:i]; +// count += rows; +// if (count > 0) { +// break; +// } +// } +// } +// @catch (NSException *e){ +// exceptioned = YES; +// } +// } +// +// if (!exceptioned) { +// self.zbw_emptyView.hidden = count > 0; +// } else { +// self.zbw_emptyView.hidden = YES; +// } +} + + +- (void)setZbw_emptyView:(UIView *)zbw_emptyView { + objc_setAssociatedObject(self, UITableView_ZBWAddition_EmptyView_Key, zbw_emptyView, OBJC_ASSOCIATION_RETAIN); + [self addSubview:zbw_emptyView]; +} + +- (UIView *)zbw_emptyView { + return objc_getAssociatedObject(self, UITableView_ZBWAddition_EmptyView_Key); +} + +- (void)setZbw_emptyState:(NSInteger)zbw_emptyState { + NSInteger oldState = self.zbw_emptyState; + objc_setAssociatedObject(self, UITableView_ZBWAddition_EmptyView_EmptyState_Key, @(zbw_emptyState), OBJC_ASSOCIATION_RETAIN); + + UIView *view = self.zbw_emptyView; + ZBWTableViewEmptyStateChangeBlock block = self.zbw_emptyStateChangeBlock; + (block && view) ? block(oldState, zbw_emptyState, view) : nil; +} + +- (NSInteger)zbw_emptyState { + NSNumber *value = objc_getAssociatedObject(self, UITableView_ZBWAddition_EmptyView_EmptyState_Key); + + return value.integerValue; +} + +- (void)setZbw_emptyStateChangeBlock:(ZBWTableViewEmptyStateChangeBlock)zbw_emptyStateChangeBlock { + objc_setAssociatedObject(self, UITableView_ZBWAddition_EmptyView_EmptyStateChange_Key, zbw_emptyStateChangeBlock, OBJC_ASSOCIATION_COPY); +} + +- (ZBWTableViewEmptyStateChangeBlock)zbw_emptyStateChangeBlock { + return objc_getAssociatedObject(self, UITableView_ZBWAddition_EmptyView_EmptyStateChange_Key); +} + +@end + + +@implementation UITableView (ZBWAddition) + +- (void)zbw_disappearMoreSeparator { + self.tableFooterView = [[UIView alloc] init]; + [self zbw_closeSelfSizing]; +} + +- (void)zbw_separatorAlign { + if ([self respondsToSelector:@selector(setSeparatorInset:)]){ + [self setSeparatorInset:UIEdgeInsetsZero]; + } + if ([self respondsToSelector:@selector(setLayoutMargins:)]){ + [self setLayoutMargins:UIEdgeInsetsZero]; + } +} + +- (void)zbw_closeSelfSizing { + self.estimatedRowHeight =0; + self.estimatedSectionHeaderHeight =0; + self.estimatedSectionFooterHeight =0; +} + +@end diff --git a/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.h b/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.h new file mode 100644 index 0000000..322776c --- /dev/null +++ b/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.h @@ -0,0 +1,36 @@ +// +// UIView+ZBWLoadingView.h +// Orange +// +// Created by 朱博文 on 2017/5/17. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import +#import "ZBWLoadingView.h" + +#define LV_DefaultOffsetY kZBW_PHONE_ADAPTER(-10, -30, -40, -50) + +@interface UIView (ZBWLoadingView) + +@property (nonatomic) UILabel *zbw_lv_tipLabel; +@property (nonatomic, weak) ZBWLoadingView *zbw_loadingView; +@property (nonatomic) UIView *zbw_lv_bgView; + +- (void)zbw_defaultLoading; + +- (void)zbw_defaultLoadingWithTipStr:(NSString *)tipStr; + +- (void)zbw_loading; + +- (void)zbw_loadingOffetY:(CGFloat)offsetY; + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr; + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr offsetY:(CGFloat)offsetY; + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr offsetY:(CGFloat)offsetY afterTime:(float)afterTime; + +- (void)zbw_dismssLoading; + +@end diff --git a/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.m b/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.m new file mode 100644 index 0000000..51311c9 --- /dev/null +++ b/ZBWUIKit/CustomViews/UIView+ZBWLoadingView.m @@ -0,0 +1,232 @@ +// +// UIView+LoadingView.m +// Orange +// +// Created by 朱博文 on 2017/5/17. +// Copyright © 2017年 朱博文. All rights reserved. +// + +#import "UIView+ZBWLoadingView.h" +#import + +static const void *UIView$ZBWLoadingView_Key = &UIView$ZBWLoadingView_Key; +static const void *UIView$ZBWLVTipLabel_Key = &UIView$ZBWLVTipLabel_Key; +static const void *UIView$ZBWLVBgView_Key = &UIView$ZBWLVBgView_Key; + +static const void *UIView$ZBWLVNSOperation_Key = &UIView$ZBWLVNSOperation_Key; + +@implementation UIView (ZBWLoadingView) + +- (NSOperation *)zbwDelayOperation { + return objc_getAssociatedObject(self, UIView$ZBWLVNSOperation_Key); +} + +- (void)setZbwDelayOperation:(NSOperation *) operation{ + objc_setAssociatedObject(self, UIView$ZBWLVNSOperation_Key, operation, OBJC_ASSOCIATION_RETAIN); +} + +- (void)zbw_defaultLoading +{ + [self zbw_loadingOffetY:LV_DefaultOffsetY]; +} + +- (void)zbw_defaultLoadingWithTipStr:(NSString *)tipStr +{ + [self zbw_loadingWithTipStr:tipStr offsetY:LV_DefaultOffsetY]; +} + + +- (void)zbw_loading +{ + [self zbw_loadingOffetY:0]; +} + +- (void)zbw_loadingOffetY:(CGFloat)offsetY +{ + [self zbw_loadingWithTipStr:nil offsetY:offsetY]; +} + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr +{ + [self zbw_loadingWithTipStr:tipStr offsetY:0]; +} + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr offsetY:(CGFloat)offsetY +{ + if (!self.zbw_loadingView) + { + self.zbw_loadingView = [ZBWLoadingView loadingInView:self]; + [self.zbw_loadingView loading]; + } + [self bringSubviewToFront:self.zbw_loadingView]; + self.zbw_loadingView.center = CGPointMake(self.zbw_loadingView.center.x, self.zbw_loadingView.center.y + offsetY); + + if (tipStr) + { + if (!self.zbw_lv_tipLabel) + { + self.zbw_lv_tipLabel = [[UILabel alloc] init]; + self.zbw_lv_tipLabel.numberOfLines = 0; + self.zbw_lv_tipLabel.textAlignment = NSTextAlignmentCenter; + self.zbw_lv_tipLabel.font = kZBW_Font_Mid_2; + self.zbw_lv_tipLabel.textColor = kZBW_Color_White; + self.zbw_lv_tipLabel.backgroundColor = [UIColor clearColor]; + } + self.zbw_lv_tipLabel.text = tipStr; + + self.zbw_lv_tipLabel.frame = CGRectMake(0, 0, self.frame.size.width - 40, 100); + [self.zbw_lv_tipLabel sizeToFit]; + + if (!self.zbw_lv_bgView) { + self.zbw_lv_bgView = [[UIView alloc] init]; + self.zbw_lv_bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.6]; + self.zbw_lv_bgView.layer.cornerRadius = 6; + self.zbw_lv_bgView.layer.masksToBounds = YES; + + [self addSubview:self.zbw_lv_bgView]; + } + CGFloat lv_bgH = self.zbw_loadingView.height + self.zbw_lv_tipLabel.height + 10*3; + CGFloat lv_bgW = MAX(self.zbw_loadingView.width, self.zbw_lv_tipLabel.width) + 10*2; + self.zbw_lv_bgView.frame = CGRectMake((self.width - lv_bgW)/2, (self.height - lv_bgH)/2, lv_bgW, lv_bgH); + + [self.zbw_lv_bgView addSubview:self.zbw_loadingView]; + [self.zbw_lv_bgView addSubview:self.zbw_lv_tipLabel]; + self.zbw_loadingView.centerX = self.zbw_lv_tipLabel.centerX = lv_bgW/2; + self.zbw_loadingView.top = 10; + self.zbw_lv_tipLabel.top = self.zbw_loadingView.bottom + 10; + } + else + { + [self.zbw_lv_tipLabel removeFromSuperview]; + self.zbw_lv_tipLabel = nil; + + [self.zbw_lv_bgView removeFromSuperview]; + self.zbw_lv_bgView = nil; + } + +} + +//- (void)loadingWithTipStr:(NSString *)tipStr offsetY:(CGFloat)offsetY +//{ +// if (!self.lv_loadingView) +// { +// self.lv_loadingView = [LoadingView loadingInView:self]; +// [self.lv_loadingView loading]; +// } +// [self bringSubviewToFront:self.lv_loadingView]; +// self.lv_loadingView.center = CGPointMake(self.lv_loadingView.center.x, self.lv_loadingView.center.y + offsetY); +//// [self.lv_loadingView loading]; +// +// CGRect loadingViewFrame = self.lv_loadingView.frame; +// +// if (tipStr) +// { +// if (!self.lv_tipLabel) +// { +// self.lv_tipLabel = [[UILabel alloc] init]; +// self.lv_tipLabel.numberOfLines = 0; +// self.lv_tipLabel.textAlignment = NSTextAlignmentCenter; +// self.lv_tipLabel.font = kZBW_Font_Mid_2; +// self.lv_tipLabel.textColor = kZBW_Color_White; +// self.lv_tipLabel.backgroundColor = [UIColor clearColor]; +// [self addSubview:self.lv_tipLabel]; +// } +// self.lv_tipLabel.text = tipStr; +// +// self.lv_tipLabel.frame = CGRectMake(0, 0, self.frame.size.width - 40, 100); +// [self.lv_tipLabel sizeToFit]; +// CGRect rect = self.lv_tipLabel.frame; +// rect.origin.x = (CGRectGetWidth(self.frame) - CGRectGetWidth(rect)) / 2; +// rect.origin.y = CGRectGetHeight(loadingViewFrame) + loadingViewFrame.origin.y + 10; +// +// self.lv_tipLabel.frame = rect; +// [self bringSubviewToFront:self.lv_tipLabel]; +// +// if (!self.lv_bgView) { +// self.lv_bgView = [[UIView alloc] init]; +// self.lv_bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.6]; +// self.lv_bgView.layer.cornerRadius = 6; +// self.lv_bgView.layer.masksToBounds = YES; +// +// +// CGFloat lv_bgX = MIN(self.lv_tipLabel.frame.origin.x, self.lv_loadingView.frame.origin.x); +// CGFloat lv_bgY = MIN(self.lv_loadingView.frame.origin.y, self.lv_tipLabel.frame.origin.y); +// CGFloat lv_bgW = MAX(CGRectGetMaxX(self.lv_tipLabel.frame), CGRectGetMaxX(self.lv_loadingView.frame)) - lv_bgX; +// CGFloat lv_bgH = MAX(CGRectGetMaxY(self.lv_tipLabel.frame), CGRectGetMaxY(self.lv_loadingView.frame)) -lv_bgY; +// CGRect lv_frame = CGRectMake(lv_bgX, lv_bgY, lv_bgW, lv_bgH); +// self.lv_bgView.frame = CGRectInset(lv_frame, -10, -10); +// +// [self insertSubview:self.lv_bgView belowSubview:self.lv_loadingView]; +// } +// } +// else +// { +// [self.lv_tipLabel removeFromSuperview]; +// self.lv_tipLabel = nil; +// +// [self.lv_bgView removeFromSuperview]; +// self.lv_bgView = nil; +// } +// +//} + +- (void)zbw_loadingWithTipStr:(NSString *)tipStr offsetY:(CGFloat)offsetY afterTime:(float)afterTime { + NSBlockOperation *delayShowOperation = [NSBlockOperation blockOperationWithBlock:^{ + + }]; + + [self setZbwDelayOperation:delayShowOperation]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{ + if (delayShowOperation.isCancelled) { + return ; + } + [self zbw_loadingWithTipStr:tipStr offsetY:offsetY]; + }); +} + +- (void)zbw_dismssLoading +{ + [[self zbwDelayOperation] cancel]; + [self setZbwDelayOperation:nil]; + + [self.zbw_loadingView removeFromSuperview]; + self.zbw_loadingView = nil; + + [self.zbw_lv_tipLabel removeFromSuperview]; + self.zbw_lv_tipLabel = nil; + + [self.zbw_lv_bgView removeFromSuperview]; + self.zbw_lv_bgView = nil; +} + +- (void)setZbw_loadingView:(ZBWLoadingView *)zbw_loadingView +{ + objc_setAssociatedObject(self, UIView$ZBWLoadingView_Key, zbw_loadingView, OBJC_ASSOCIATION_RETAIN); +} + +- (ZBWLoadingView *)zbw_loadingView +{ + return objc_getAssociatedObject(self, UIView$ZBWLoadingView_Key); +} + + +- (void)setZbw_lv_tipLabel:(UILabel *)zbw_lv_tipLabel +{ + objc_setAssociatedObject(self, UIView$ZBWLVTipLabel_Key, zbw_lv_tipLabel, OBJC_ASSOCIATION_RETAIN); +} + +- (UILabel *)zbw_lv_tipLabel +{ + return objc_getAssociatedObject(self, UIView$ZBWLVTipLabel_Key); +} + +- (void)setZbw_lv_bgView:(UIView *)zbw_lv_bgView { + objc_setAssociatedObject(self, UIView$ZBWLVBgView_Key, zbw_lv_bgView, OBJC_ASSOCIATION_RETAIN); +} + +- (UIView *)zbw_lv_bgView { + return objc_getAssociatedObject(self, UIView$ZBWLVBgView_Key); +} + +@end diff --git a/ZBWUIKit/CustomViews/ZBWBannerView.h b/ZBWUIKit/CustomViews/ZBWBannerView.h new file mode 100644 index 0000000..2251025 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWBannerView.h @@ -0,0 +1,27 @@ +// +// HomePageBannerView.h +// +// +// Created by limengqiang on 15/7/31. +// +// + +#import + + +@interface ZBWBannerItemInfo : NSObject + +@property (nonatomic, copy) NSString *imageUrl; +@property (nonatomic) id object; + ++ (instancetype)bannerItemInfo:(NSString *)imageUrl object:(id)object; + +@end + +@interface ZBWBannerView : UIView +@property (nonatomic, assign) float timeSecond; +- (void)begin; +- (void)stopTimer; +@property (nonatomic, retain) NSArray *itemArray; + +@end diff --git a/ZBWUIKit/CustomViews/ZBWBannerView.m b/ZBWUIKit/CustomViews/ZBWBannerView.m new file mode 100644 index 0000000..bcff5f7 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWBannerView.m @@ -0,0 +1,253 @@ +// +// HomePageBannerView.m +// +// +// Created by limengqiang on 15/7/31. +// +// + +#import "ZBWBannerView.h" +#import "ZBWGlobalTimer.h" +#import "ZBWPageControlView.h" + + +#define ADAPTIVE_SCALE floorf(([[UIScreen mainScreen] bounds].size.width/320.0) * 100)/100 + +@implementation ZBWBannerItemInfo + ++ (instancetype)bannerItemInfo:(NSString *)imageUrl object:(id)object +{ + ZBWBannerItemInfo *info = [[ZBWBannerItemInfo alloc] init]; + info.imageUrl = imageUrl; + info.object = object; + + return info; +} + +@end + +@interface ZBWBannerView(){ + UIScrollView *_scrollView; + UIImageView *_imageViewLeft; + UIImageView *_imageViewCurrent; + UIImageView *_imageViewRight; + int _currentIndex; + + ZBWPageControlView *_pageControlView; + BOOL _isStop; +} + +@end + +@implementation ZBWBannerView + +- (id)initWithFrame:(CGRect)frame +{ + NSLog(@"%s", __func__); + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor whiteColor]; + + _currentIndex = 0; + + _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; + _scrollView.contentSize = CGSizeMake(frame.size.width * 3, frame.size.height); + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.delegate = self; + _scrollView.pagingEnabled = YES; + _scrollView.scrollsToTop = NO; + [self addSubview:_scrollView]; + + UIView *left = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; + left.clipsToBounds = YES; + [_scrollView addSubview:left]; + + _imageViewLeft = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; + _imageViewLeft.zbw_identify = @"BannerImageView"; + [left addSubview:_imageViewLeft]; + + + UIView *current = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width, 0, frame.size.width, frame.size.height)]; + current.clipsToBounds = YES; + [_scrollView addSubview:current]; + + _imageViewCurrent = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; + _imageViewCurrent.zbw_identify = @"BannerImageView"; + [current addSubview:_imageViewCurrent]; + + UIView *right = [[UIView alloc] initWithFrame:CGRectMake(frame.size.width * 2, 0, frame.size.width, frame.size.height)]; + right.clipsToBounds = YES; + [_scrollView addSubview:right]; + + _imageViewRight = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; + _imageViewRight.zbw_identify = @"BannerImageView"; + [right addSubview:_imageViewRight]; + + UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)]; + self.userInteractionEnabled = YES; + [self addGestureRecognizer:tapGestureRecognize]; + +// _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - 16 * ADAPTIVE_SCALE, self.width, 10 * ADAPTIVE_SCALE)]; +// _pageControl.userInteractionEnabled = NO; +// _pageControl.numberOfPages = 1; +// _pageControl.currentPage = 0; +// _pageControl.hidesForSinglePage = YES; +// if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0) { +// _pageControl.pageIndicatorTintColor = [UIColor colorWithWhite:0.0 alpha:0.3]; +// _pageControl.currentPageIndicatorTintColor = [UIColor colorWithHexColorString:@"f53e7b"]; +// } +// [self addSubview:_pageControl]; + + _pageControlView = [[ZBWPageControlView alloc] init]; + _pageControlView.numberOfPages = 1; + _pageControlView.currentPage = 0; + [self addSubview:_pageControlView]; + + } + return self; +} + +- (void)setItemArray:(NSArray *)itemArray { + _itemArray = itemArray; + if (self.itemArray == nil || [self.itemArray count] == 0) { + return; + } + _currentIndex = 0; + _pageControlView.numberOfPages = (int)_itemArray.count; + [_pageControlView setFrame:CGRectMake(2, (int)(self.height - _pageControlView.height - 6 * ADAPTIVE_SCALE), _pageControlView.width, _pageControlView.height)]; + _pageControlView.centerX = self.width/2; + + _isStop = NO; + + [self restoreScrollView]; + + if (self.itemArray != nil && [self.itemArray count] == 1) { + _scrollView.scrollEnabled = NO; + } else { + _scrollView.scrollEnabled = YES; + } +} + +- (void)begin +{ + if (self.itemArray != nil && [self.itemArray count] == 1) { + [ZBWGlobalTimer removeTarget:self type:self.timeSecond]; + } else { + [ZBWGlobalTimer addTarget:self selector:@selector(timeScroll) type:self.timeSecond]; + } +} + +#pragma mark UIScrollViewDelegate; +- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ + float scrollViewOffset = scrollView.contentOffset.x - scrollView.width; + if (scrollViewOffset > 0) { + float proportion = scrollViewOffset / scrollView.width; + float imageViewOffset = (scrollView.width) / 2 * proportion; + _imageViewCurrent.left = imageViewOffset; + _imageViewRight.left = imageViewOffset - (scrollView.width) / 2; + }else{ + float proportion = - scrollViewOffset / scrollView.width; + float imageViewOffset = (scrollView.width) / 2 * proportion; + _imageViewCurrent.left = - imageViewOffset; + _imageViewLeft.left = - imageViewOffset + (scrollView.width) / 2; + } + if (scrollView.contentOffset.x >= _scrollView.width * 2) { + [self addCurrentIndex:YES]; + [self restoreScrollView]; + }else if (scrollView.contentOffset.x <= 0){ + [self addCurrentIndex:NO]; + [self restoreScrollView]; + } +} + +//// 定时右滑滑动结束后执行。(该滚动需要代码触发且Animation:YES) +//- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{ +// if (scrollView.contentOffset.x == _scrollView.width * 2) { +// [self addCurrentIndex:YES]; +// } +// [self restoreScrollView]; +//} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + [self stopTimer]; +} + +//scrollView 停止滚动执行。(该滚动需要是手指触发的滚动) +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ + [self begin]; +} + + +//scrollView 定时右滑 +- (void)timeScroll{ + if ([self zbw_outsideWithScreen]) { + [self stopTimer]; + return; + } + if (_scrollView.contentOffset.x == _scrollView.width) { + [_scrollView setContentOffset:CGPointMake(_scrollView.width * 2, 0) animated:YES]; + } +} + +//scrollView 复位 +- (void)restoreScrollView{ + +// _pageControl.currentPage = _currentIndex; + if (_isStop) { + return; + } + _pageControlView.currentPage = _currentIndex; + +// ZBW_SendUpSignal(@"currentItem", @(_currentIndex), nil, self); + + [_scrollView setContentOffset:CGPointMake(_scrollView.width, 0) animated:NO]; + _imageViewLeft.left = _scrollView.width / 2; + _imageViewCurrent.left = 0; + _imageViewRight.left = - _scrollView.width / 2; + + int leftIndex = _currentIndex - 1; + if (leftIndex < 0) { + leftIndex = (int)[self.itemArray count] - 1; + } + + int rightIndex = _currentIndex + 1; + if (rightIndex >= [self.itemArray count]) { + rightIndex = 0; + } + + ZBWBannerItemInfo *leftItem = [self.itemArray objectAtIndex:leftIndex]; +// [_imageViewLeft imageLoabBridge:leftItem.imageUrl]; + [_imageViewLeft zbw_loadImage:leftItem.imageUrl]; + ZBWBannerItemInfo *currentItem = [self.itemArray objectAtIndex:_currentIndex]; + [_imageViewCurrent zbw_loadImage:currentItem.imageUrl]; + ZBWBannerItemInfo *rightItem = [self.itemArray objectAtIndex:rightIndex]; + [_imageViewRight zbw_loadImage:rightItem.imageUrl]; +} + +- (void)addCurrentIndex:(BOOL)isAdd{ + if (isAdd) { + _currentIndex ++; + if (_currentIndex >= [self.itemArray count]) { + _currentIndex = 0; + } + }else{ + _currentIndex --; + if (_currentIndex < 0) { + _currentIndex = (int)[self.itemArray count] - 1; + } + } +// NSLog(@"showCurrentIndex----%d",_currentIndex); +} + +- (void)stopTimer{ + [ZBWGlobalTimer removeTarget:self type:self.timeSecond]; +} + +- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer +{ + ZBWBannerItemInfo *info = [self.itemArray objectAtIndex:_currentIndex]; + ZBW_SendUpSignal(@"click", info.object, nil, self); +} + +@end diff --git a/ZBWUIKit/CustomViews/ZBWCustomViews.h b/ZBWUIKit/CustomViews/ZBWCustomViews.h new file mode 100644 index 0000000..3fbb3d2 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWCustomViews.h @@ -0,0 +1,17 @@ +// +// ZBWCustomViews.h +// ZBWUIKit +// +// Created by 朱博文 on 16/12/23. +// Copyright © 2016年 朱博文. All rights reserved. +// + +#ifndef ZBWCustomViews_h +#define ZBWCustomViews_h + +#import "ZBWSegmentView.h" +#import "ZBWGridView.h" +#import "ZBWGridCell.h" +#import "ZBWGridCellButton.h" + +#endif /* ZBWCustomViews_h */ diff --git a/ZBWUIKit/CustomViews/ZBWLoadingView.h b/ZBWUIKit/CustomViews/ZBWLoadingView.h new file mode 100644 index 0000000..9c36be8 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWLoadingView.h @@ -0,0 +1,80 @@ +// +// ZBWLoadingView.h +// +// +// Created by Bowen on 15/5/6. +// Copyright (c) 2015年. All rights reserved. +// + +#import + +/** + * 加载view + */ +@interface ZBWLoadingView : UIView + +// 前景色 +@property (nonatomic, retain)UIColor *fgLineColor UI_APPEARANCE_SELECTOR; +// 背景色 +@property (nonatomic, retain)UIColor *bgLineColor UI_APPEARANCE_SELECTOR; +// 圆的线宽,默认6 +@property (nonatomic, assign)CGFloat lineWidth; +// 一次动画的时间,默认0.5 +@property (nonatomic, assign)NSTimeInterval duration; +// 旋转角度,默认70 +@property (nonatomic, assign)CGFloat rotationAngle; + ++ (ZBWLoadingView *)loadingView; + ++ (ZBWLoadingView *)loadingInView:(UIView *)inView; + +/** + UI_APPEARANCE_SELECTOR 无法完全解决。 当inView还未加载的时候,UI_APPEARANCE_SELECTOR的值不会生效。 + 设置默认的前景颜色 + */ ++ (void)setDefaultFgLineColor:(UIColor *)color; + +/** + 设置默认的背景颜色 + */ ++ (void)setDefaultBgLineColor:(UIColor *)color; + + +/** + * 动画。 修改上面的属性后,一定要调用loading,才会更新页面。 + */ +- (void)loading; + +@end + +/* example + + 1、 +LoadingView *view1 = [LoadingView loadingView]; +[self.view addSubview:view1]; +[view1 loading]; +view1.center = CGPointMake(100, 200); + + 2、 +LoadingView *view2 = [LoadingView loadingInView:self.view]; +view2.center = CGPointMake(100, 300); + + 3、 +LoadingView *view3 = [LoadingView loadingInView:self.view]; +view3.frame = CGRectMake(200, 200, 100, 100); +view3.lineWidth = 10; +view3.fgLineColor = [UIColor redColor]; +view3.bgLineColor = [UIColor greenColor]; +view3.duration = 1; +[view3 loading]; + + 4、 +LoadingView *view4 = [LoadingView loadingInView:self.view]; +view4.frame = CGRectMake(200, 400, 60, 100); +view4.lineWidth = 10; +view4.fgLineColor = [UIColor redColor]; +view4.duration = .5; +view4.rotationAngle = 30; +[view4 loading]; + + */ diff --git a/ZBWUIKit/CustomViews/ZBWLoadingView.m b/ZBWUIKit/CustomViews/ZBWLoadingView.m new file mode 100644 index 0000000..7e441eb --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWLoadingView.m @@ -0,0 +1,310 @@ +// +// ZBWLoadingView.m +// +// +// Created by Bowen on 15/5/6. +// Copyright (c) 2015年. All rights reserved. +// + +#import "ZBWLoadingView.h" + +#define ZBWLoadingView_LineWidth 6 +#define ZBWLoadingView_Width 40 +#define ZBWLoadingView_Duration 0.5 + +#define ZBWLoadingView_rotationAngle 70 + +#define ZBWLoadingView_Color_Light [[UIColor blackColor] colorWithAlphaComponent:0.1] +#define ZBWLoadingView_Color_Dark [[UIColor blackColor] colorWithAlphaComponent:0.1] + +/** + * 自定义Layer + */ +@interface ZBWLoadingLayer : CALayer +@property (nonatomic, assign)float progress; +@property (nonatomic, assign)float lineWidth; +@property (nonatomic, assign)CGFloat rotationAngle; +@property (nonatomic, retain)UIColor *lineColor; + +@end + + +@implementation ZBWLoadingLayer + +@dynamic lineWidth; +@dynamic rotationAngle; +@dynamic lineColor; + ++ (BOOL)needsDisplayForKey:(NSString *)key +{ + if ([key isEqualToString:@"progress"]) { + return YES; + } + return [super needsDisplayForKey:key]; +} + ++ (instancetype)layer +{ + ZBWLoadingLayer *layer = [[ZBWLoadingLayer alloc] init]; + return layer; +} + +- (void)drawInContext:(CGContextRef)ctx +{ + CGRect rect = self.bounds; + CGFloat width = CGRectGetWidth(rect); + float startAngle = (self.rotationAngle - 90) - (_progress * 360) / 2; + float endAngle = (self.rotationAngle - 90) + (_progress * 360) / 2; + UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)) radius:(width - self.lineWidth) / 2 startAngle:kZBW_DEGREES_TO_RADIANS(startAngle) endAngle:kZBW_DEGREES_TO_RADIANS(endAngle) clockwise:YES]; + + CGContextSaveGState(ctx); + CGContextSetStrokeColorWithColor(ctx, self.lineColor.CGColor); + CGContextSetLineWidth(ctx, self.lineWidth); + CGContextAddPath(ctx, path.CGPath); + CGContextSetShouldAntialias(ctx,true); + CGContextStrokePath(ctx); + CGContextRestoreGState(ctx); +} + + +@end + + + +@interface ZBWLoadingView () + +@property (nonatomic, strong)UIBezierPath *path; +@property (nonatomic, strong)ZBWLoadingLayer *animationLayer; + +@property (nonatomic, strong)CAShapeLayer *circleLayer1; +@property (nonatomic, strong)CAShapeLayer *circleLayer2; + +@end + +@implementation ZBWLoadingView + +static UIColor *s_fgColor; +static UIColor *s_bgColor; + ++ (ZBWLoadingView *)loadingInView:(UIView *)inView +{ + ZBWLoadingView *loadingView = [ZBWLoadingView loadingView]; + CGRect rect = inView.bounds; + loadingView.center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); + [inView addSubview:loadingView]; + [loadingView loading]; + return loadingView; +} + ++ (ZBWLoadingView *)loadingView +{ + ZBWLoadingView *loadingView = [[ZBWLoadingView alloc] initWithFrame:CGRectMake(0, 0, ZBWLoadingView_Width, ZBWLoadingView_Width)]; + return loadingView; +} + +/** + 设置默认的前景颜色 + */ ++ (void)setDefaultFgLineColor:(UIColor *)color { + s_fgColor = color; +} + +/** + 设置默认的背景颜色 + */ ++ (void)setDefaultBgLineColor:(UIColor *)color { + s_bgColor = color; +} + +- (instancetype)init +{ + if (self = [super init]) + { + [self initData]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) + { + [self initData]; + } + return self; +} + +- (void)initData +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; + +// self.fgLineColor = kZBW_Color_Orange; +// self.bgLineColor = ZBWLoadingView_Color_Light; + self.lineWidth = ZBWLoadingView_LineWidth; + self.duration = ZBWLoadingView_Duration; + self.rotationAngle = ZBWLoadingView_rotationAngle; +} + +// 正方形frame +- (void)setFrame:(CGRect)frame +{ + CGRect rect = CGRectMake(frame.origin.x, frame.origin.y, MIN(frame.size.width, frame.size.height), MIN(frame.size.width, frame.size.height)); + [super setFrame:rect]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self clean]; +} + +- (void)onAppDidEnterBackground +{ + [self clean]; +} + +- (void)onAppDidBecomeActive +{ + [self loading]; +} + +- (void)clean +{ + if (_animationLayer) + { + [_animationLayer removeAllAnimations]; + [_animationLayer removeFromSuperlayer]; + _animationLayer = nil; + } + if (_circleLayer1) + { + [_circleLayer1 removeAllAnimations]; + [_circleLayer1 removeFromSuperlayer]; + _circleLayer1 = nil; + } + if (_circleLayer2) + { + [_circleLayer2 removeAllAnimations]; + [_circleLayer2 removeFromSuperlayer]; + _circleLayer2 = nil; + } + _path = nil; +} + +- (void)loading +{ + if (!self.fgLineColor) { + if (s_fgColor) { + self.fgLineColor = s_fgColor; + } else { + self.fgLineColor = ZBWLoadingView_Color_Dark; + } + } + if (!self.bgLineColor) { + if (s_bgColor) { + self.bgLineColor = s_bgColor; + } else { + self.bgLineColor = ZBWLoadingView_Color_Light; + } + } + // step1: 清理sublayer + [self clean]; + + // 根据当前属性设置,重新定义frame + CGRect frame = self.frame; + + // step3:添加sublayer + self.backgroundColor = [UIColor clearColor]; + [self.layer addSublayer:self.animationLayer]; + + self.circleLayer1 = [CAShapeLayer layer]; + self.circleLayer1.backgroundColor = [UIColor clearColor].CGColor; + self.circleLayer1.bounds = self.animationLayer.bounds; + self.circleLayer1.position = self.animationLayer.position; + self.circleLayer1.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((CGRectGetWidth(frame) - self.lineWidth) / 2, 0, self.lineWidth, self.lineWidth)].CGPath; + self.circleLayer1.fillColor = [UIColor whiteColor].CGColor; + [self.layer addSublayer:self.circleLayer1]; + + + self.circleLayer2 = [CAShapeLayer layer]; + self.circleLayer2.backgroundColor = [UIColor clearColor].CGColor; + self.circleLayer2.bounds = self.animationLayer.bounds; + self.circleLayer2.position = self.animationLayer.position; + self.circleLayer2.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((CGRectGetWidth(frame) - self.lineWidth) / 2, 0, self.lineWidth, self.lineWidth)].CGPath; + self.circleLayer2.fillColor = [UIColor whiteColor].CGColor; + [self.layer addSublayer:self.circleLayer2]; + + // step4:为subulayer添加动画 +// self.animationLayer.progress = .5; + [self.animationLayer setNeedsDisplay]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"]; + animation.fromValue = [NSNumber numberWithFloat:0]; + animation.toValue = [NSNumber numberWithFloat:1.0]; + animation.repeatCount = INT32_MAX; + animation.autoreverses = YES; + animation.duration = self.duration; +// + [self.animationLayer addAnimation:animation forKey:nil]; + + + CABasicAnimation *rotationAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; + rotationAnimation1.fromValue = [NSNumber numberWithFloat:kZBW_DEGREES_TO_RADIANS(self.rotationAngle)]; + rotationAnimation1.toValue = [NSNumber numberWithFloat:kZBW_DEGREES_TO_RADIANS(self.rotationAngle - 180)]; + rotationAnimation1.repeatCount = INT32_MAX; + rotationAnimation1.autoreverses = YES; + rotationAnimation1.duration = self.duration; + + [self.circleLayer1 addAnimation:rotationAnimation1 forKey:nil]; + + CABasicAnimation *rotationAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; + rotationAnimation2.fromValue = [NSNumber numberWithFloat:kZBW_DEGREES_TO_RADIANS(self.rotationAngle)]; + rotationAnimation2.toValue = [NSNumber numberWithFloat:kZBW_DEGREES_TO_RADIANS(self.rotationAngle + 180)]; + rotationAnimation2.repeatCount = INT32_MAX; + rotationAnimation2.autoreverses = YES; + rotationAnimation2.duration = self.duration; + + [self.circleLayer2 addAnimation:rotationAnimation2 forKey:nil]; +} + +- (ZBWLoadingLayer *)animationLayer +{ + if (!_animationLayer) + { + _animationLayer = [ZBWLoadingLayer layer]; + _animationLayer.bounds = self.bounds; + _animationLayer.lineWidth = self.lineWidth; + _animationLayer.rotationAngle = self.rotationAngle; + _animationLayer.lineColor = self.fgLineColor; + _animationLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + } + return _animationLayer; +} + +- (UIBezierPath *)path +{ + if (!_path) + { + CGRect rect = self.bounds; + CGFloat width = CGRectGetWidth(rect); + _path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)) radius:(width - self.lineWidth) / 2 startAngle:kZBW_DEGREES_TO_RADIANS(self.rotationAngle - 90) endAngle:kZBW_DEGREES_TO_RADIANS(360 + (self.rotationAngle - 90)) clockwise:YES]; + } + return _path; +} + +- (void)drawRect:(CGRect)rect +{ + // 绘制圆圈 + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextClearRect(context, rect); + + CGContextSetStrokeColorWithColor(context, self.bgLineColor.CGColor); + CGContextSetLineWidth(context, self.lineWidth); + + CGContextAddPath(context, self.path.CGPath); + CGContextSetShouldAntialias(context,true); + CGContextStrokePath(context); +} + + +@end diff --git a/ZBWUIKit/CustomViews/ZBWPageControlView.h b/ZBWUIKit/CustomViews/ZBWPageControlView.h new file mode 100644 index 0000000..50b33bb --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWPageControlView.h @@ -0,0 +1,23 @@ +// +// ZBWPageControlView.h +// Orange +// +// Created by 朱博文 on 2018/11/22. +// Copyright © 2018年 朱博文. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ZBWPageControlView : UIView + +@property (nonatomic, assign) int numberOfPages; +@property (nonatomic, assign) int currentPage; + +@property (nonatomic) UIColor *pointColor UI_APPEARANCE_SELECTOR; +@property (nonatomic) UIImage *pointImage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ZBWUIKit/CustomViews/ZBWPageControlView.m b/ZBWUIKit/CustomViews/ZBWPageControlView.m new file mode 100644 index 0000000..2c831c9 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWPageControlView.m @@ -0,0 +1,77 @@ +// +// ZBWPageControlView.m +// Orange +// +// Created by 朱博文 on 2018/11/22. +// Copyright © 2018年 朱博文. All rights reserved. +// + +#import "ZBWPageControlView.h" +@implementation ZBWPageControlView + +- (instancetype)init +{ + if (self=[super init]) { + if (!self.pointColor) { + self.pointColor = [ZBWPageControlView appearance].pointColor; + } + self.pointImage = [UIImage zbw_createCycleImageWithColor:self.pointColor radius:6]; + } + return self; +} + +- (void)setNumberOfPages:(int)numberOfPages{ + if (numberOfPages == _numberOfPages) { + return; + } + + _numberOfPages = numberOfPages; + self.clipsToBounds = NO; + [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + if (numberOfPages > 1) { + float width = 0; + for (int i = 0; i < numberOfPages; i ++) { + if (i == 0) { + UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(8, 0, 18, 6)]; + btn.tag = 100 + i; + UIImage *image = self.pointImage; + image = [image stretchableImageWithLeftCapWidth:3 topCapHeight:0]; + [btn setBackgroundImage:image forState:UIControlStateNormal]; + [self addSubview:btn]; + width += 18+8; + } else { + UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(width + 8, 0, 6, 6)]; + btn.tag = 100 + i; + [btn setBackgroundImage:self.pointImage forState:UIControlStateNormal]; + btn.alpha = .5; + [self addSubview:btn]; + width += 14; + } + } + self.width = width; + self.height = 6; + } +} + +- (void)setCurrentPage:(int)currentPage{ + [UIView animateWithDuration:.3 animations:^{ + float width = 0; + for (int i = 0; i < self.numberOfPages; i ++) { + UIButton *btn = (UIButton *)[self viewWithTag:100+i]; + UIImage *image = self.pointImage; + image = [image stretchableImageWithLeftCapWidth:3 topCapHeight:0]; + if (i == currentPage) { + btn.frame = CGRectMake(width + 8, 0, 18, 6); + width += 18+8; + btn.alpha = 1; + } else { + btn.frame = CGRectMake(width + 8, 0, 6, 6); + width += 14; + btn.alpha = .5; + } + [btn setBackgroundImage:image forState:UIControlStateNormal]; + } + }]; +} + +@end diff --git a/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.h b/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.h new file mode 100644 index 0000000..2bd0086 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.h @@ -0,0 +1,24 @@ +// +// ZBWPhoneNumTextField.h +// ZBWPhoneNumTextField +// +// Created by Bowen on 14/12/5. +// Copyright (c) 2014年 Bowen. All rights reserved. +// + +#import + +/* + * 手机号输入TextField控件 + * 自动按3-4-4分割 + */ +@interface ZBWPhoneNumTextField : UITextField + +// 有效手机号的最大长度,默认为11 +@property(nonatomic, assign)NSUInteger maxLength; +// 真实的手机号 +@property(nonatomic, copy) NSString *phoneNum; + +@property (nonatomic, weak) id phoneNumTextFieldDelegate; + +@end diff --git a/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.m b/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.m new file mode 100644 index 0000000..e643e3e --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWPhoneNumTextField.m @@ -0,0 +1,422 @@ +// +// ZBWPhoneNumTextField.m +// ZBWPhoneNumTextField +// +// Created by Bowen on 14/12/5. +// Copyright (c) 2014年 Bowen. All rights reserved. +// + +#import "ZBWPhoneNumTextField.h" +#import + +#define MaxLength_Of_PhoneNum 11 + + +/** + * 由于iOS7.1系统中,UITextField的delegate如果设置成UITextField自身,会出现卡死,cup占用100%,因此使用次类来中转 + */ +@interface ZBWDelegateProxy : NSObject + +@property (nonatomic, weak) id phoneNumTextFieldDelegate; + +@end + +@implementation ZBWDelegateProxy + +#pragma mark- +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + ZBWPhoneNumTextField *_self = (ZBWPhoneNumTextField *)textField; + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textField:_self shouldChangeCharactersInRange:range replacementString:string]; + } + + // 输入字符不能包括"0123456789 -"以外的字符 + if ([string rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789 -"].invertedSet options:NSCaseInsensitiveSearch].location != NSNotFound) { + return NO; + } + + string = [string stringByReplacingOccurrencesOfString:@"-" withString:@""]; + + // 删除符 +// if ([string isEqualToString:@""]) +// { +// NSString *phoneNum = _self.phoneNum; +// if (phoneNum.length >= 1) +// { +// NSString *text = _self.text; +// NSString *replaceStr = [text substringWithRange:range]; +// if ([replaceStr isEqualToString:@" "]) { +// text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location - 1, 1) withString:string]; +// } +// else +// { +// text = [text stringByReplacingCharactersInRange:range withString:string]; +// } +// _self.phoneNum = [text stringByReplacingOccurrencesOfString:@" " withString:@""]; +// } +// return NO; +// } + NSString *oldStr = textField.text; + NSString *newStr = [oldStr stringByReplacingCharactersInRange:range withString:string]; + NSString *truePhoneNum = [[newStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@" " withString:@""]; + + + // 有效数值过大, 不允许输入 + if (truePhoneNum.length > _self.maxLength) + { + return NO; + } + else + { + _self.phoneNum = truePhoneNum; + + NSString *startStr = [[NSString stringWithFormat:@"%@%@",[oldStr substringToIndex:range.location],string] stringByReplacingOccurrencesOfString:@" " withString:@""]; + NSInteger length = startStr.length; + + UITextPosition* beginning = _self.beginningOfDocument; + + range.length = 0; range.location = length > 7 ? length + 2 : (length > 3 ? length + 1 : length); + UITextPosition* startPosition = [_self positionFromPosition:beginning offset:range.location]; + UITextPosition* endPosition = [_self positionFromPosition:beginning offset:range.location + range.length]; + UITextRange* selectionRange = [_self textRangeFromPosition:startPosition toPosition:endPosition]; + + [_self setSelectedTextRange:selectionRange]; + + return NO; + } +} + + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldShouldBeginEditing:textField]; + } + return YES; +} +- (void)textFieldDidBeginEditing:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldDidBeginEditing:textField]; + } +} +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldShouldEndEditing:textField]; + } + return YES; +} +- (void)textFieldDidEndEditing:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldDidEndEditing:textField]; + } +} + +- (BOOL)textFieldShouldClear:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldShouldClear:textField]; + } + ((ZBWPhoneNumTextField *)textField).phoneNum = @""; + return YES; +} +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { + return [_phoneNumTextFieldDelegate textFieldShouldReturn:textField]; + } + return YES; +} + + +@end + + +@interface ZBWPhoneNumTextField () + +@property (nonatomic) ZBWDelegateProxy *proxy; + +@property (nonatomic) NSAttributedString *attributedPlaceholderForIOS7; // ios7.1 非常奇怪,attributedPlaceholder设置后,font无法修改,与text的font始终一致。 + +@end + +@implementation ZBWPhoneNumTextField + +- (void)awakeFromNib +{ + [super awakeFromNib]; + [self initData]; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) + { + [self initData]; + } + return self; +} + +- (void)initData +{ + self.proxy = [[ZBWDelegateProxy alloc] init]; + super.delegate = self.proxy; + self.maxLength = MaxLength_Of_PhoneNum; + self.keyboardType = UIKeyboardTypeNumberPad; + +#if 0 + UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)]; + + UIBarButtonItem *spaceBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + UIBarButtonItem *okBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(resignFirstResponder)]; + toolBar.items = @[spaceBarButtonItem, okBarButtonItem]; + + self.inputAccessoryView = toolBar; +#endif +} + +// 重写delegate,避免外部错误设置 +- (void)setDelegate:(id)delegate +{ + super.delegate = self.proxy; +} + +- (void)setPhoneNumTextFieldDelegate:(id)phoneNumTextFieldDelegate +{ + self.proxy.phoneNumTextFieldDelegate = phoneNumTextFieldDelegate; +} + +// 重写键盘,避免外部错误设置 +- (void)setKeyboardType:(UIKeyboardType)keyboardType +{ + super.keyboardType = UIKeyboardTypePhonePad; +} + +- (void)setAttributedPlaceholder:(NSAttributedString *)attributedPlaceholder +{ + if ([[UIDevice currentDevice] systemVersion].floatValue < 8.0) { + self.attributedPlaceholderForIOS7 = attributedPlaceholder; + } + + super.attributedPlaceholder = attributedPlaceholder; +} + +// 获取真实手机号 +- (NSString *)phoneNum +{ + return [[self.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@" " withString:@""]; +} + +// 设置手机号 +- (void)setPhoneNum:(NSString *)phoneNum +{ + phoneNum = [phoneNum stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + NSUInteger length = phoneNum.length; + if (length > self.maxLength) + { + return; + } + + // 3-4-4 + if (length >= 8) + { + self.text = [NSString stringWithFormat:@"%@ %@ %@", [phoneNum substringToIndex:3], [phoneNum substringWithRange:NSMakeRange(3, 4)], [phoneNum substringFromIndex:7]]; + } + else if (length >= 4) + { + self.text = [NSString stringWithFormat:@"%@ %@", [phoneNum substringToIndex:3], [phoneNum substringFromIndex:3]]; + } + else + { + self.text = phoneNum; + } +} + +- (CGRect)placeholderRectForBounds:(CGRect)bounds +{ + CGRect rect = [super placeholderRectForBounds:bounds]; + return CGRectOffset(rect, 0, 0); +} + +- (void)drawPlaceholderInRect:(CGRect)rect +{ + if (!self.attributedPlaceholderForIOS7) { + [super drawPlaceholderInRect:rect]; + return; + } + + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextScaleCTM(context, 1, -1); + + CTLineRef lineRef = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)self.attributedPlaceholderForIOS7); + CGContextTranslateCTM(context, + 0, + -CGRectGetHeight(rect)+ (CGRectGetHeight(rect) - CTLineGetBoundsWithOptions(lineRef, kCTLineBoundsUseGlyphPathBounds).size.height)/2 +3); + CTLineDraw(lineRef, context); + CFRelease(lineRef); +} + +@end + + +//@interface ZBWPhoneNumTextField () +//@end +// +//@implementation ZBWPhoneNumTextField +// +//- (void)awakeFromNib +//{ +// [self initData]; +//} +// +//- (instancetype)initWithFrame:(CGRect)frame +//{ +// if (self = [super initWithFrame:frame]) +// { +// [self initData]; +// } +// return self; +//} +// +//- (void)initData +//{ +// super.delegate = self; +// self.maxLength = MaxLength_Of_PhoneNum; +// self.keyboardType = UIKeyboardTypeNumberPad; +//} +// +//// 重写delegate,避免外部错误设置 +//- (void)setDelegate:(id)delegate +//{ +// super.delegate = self; +//} +// +//// 重写键盘,避免外部错误设置 +//- (void)setKeyboardType:(UIKeyboardType)keyboardType +//{ +// super.keyboardType = UIKeyboardTypePhonePad; +//} +// +//// 获取真实手机号 +//- (NSString *)phoneNum +//{ +// return [[self.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@" " withString:@""]; +//} +// +//// 设置手机号 +//- (void)setPhoneNum:(NSString *)phoneNum +//{ +// phoneNum = [phoneNum stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; +// NSUInteger length = phoneNum.length; +// if (length > self.maxLength) +// { +// return; +// } +// +// // 3-4-4 +// if (length >= 8) +// { +// self.text = [NSString stringWithFormat:@"%@ %@ %@", [phoneNum substringToIndex:3], [phoneNum substringWithRange:NSMakeRange(3, 4)], [phoneNum substringFromIndex:7]]; +// } +// else if (length >= 4) +// { +// self.text = [NSString stringWithFormat:@"%@ %@", [phoneNum substringToIndex:3], [phoneNum substringFromIndex:3]]; +// } +// else +// { +// self.text = phoneNum; +// } +//} +// +////- (CGRect)placeholderRectForBounds:(CGRect)bounds +////{ +//// CGRect rect = [super placeholderRectForBounds:bounds]; +//// return CGRectOffset(rect, 0, 3); +////} +// +//#pragma mark- +//- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textField:self shouldChangeCharactersInRange:range replacementString:string]; +// } +// +// if ([string rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789 -"].invertedSet options:NSCaseInsensitiveSearch].location != NSNotFound) { +// return NO; +// } +// +// string = [string stringByReplacingOccurrencesOfString:@"-" withString:@""]; +// +// // 删除符 +// if ([string isEqualToString:@""]) +// { +// NSString *phoneNum = self.phoneNum; +// if (phoneNum.length >= 1) +// { +// self.phoneNum = [phoneNum substringToIndex:phoneNum.length - 1]; +// } +// return NO; +// } +// NSString *oldStr = textField.text; +// NSString *newStr = [oldStr stringByReplacingCharactersInRange:range withString:string]; +// NSString *truePhoneNum = [[newStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] stringByReplacingOccurrencesOfString:@" " withString:@""]; +// // 有效数值过大, 不允许输入 +// if (truePhoneNum.length > self.maxLength) +// { +// return NO; +// } +// else +// { +// self.phoneNum = truePhoneNum; +// return NO; +// } +//} +// +// +//- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldShouldBeginEditing:self]; +// } +// return YES; +//} +//- (void)textFieldDidBeginEditing:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldDidBeginEditing:self]; +// } +//} +//- (BOOL)textFieldShouldEndEditing:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldShouldEndEditing:self]; +// } +// return YES; +//} +//- (void)textFieldDidEndEditing:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldDidEndEditing:self]; +// } +//} +// +//- (BOOL)textFieldShouldClear:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldShouldClear:self]; +// } +// self.phoneNum = @""; +// return YES; +//} +//- (BOOL)textFieldShouldReturn:(UITextField *)textField +//{ +// if (_phoneNumTextFieldDelegate && [_phoneNumTextFieldDelegate respondsToSelector:_cmd]) { +// return [_phoneNumTextFieldDelegate textFieldShouldReturn:self]; +// } +// return YES; +//} +// +//@end diff --git a/ZBWUIKit/CustomViews/ZBWSegmentView.h b/ZBWUIKit/CustomViews/ZBWSegmentView.h new file mode 100644 index 0000000..98bde85 --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWSegmentView.h @@ -0,0 +1,64 @@ +// +// ZBWSegmentView.h +// +// +// Created by Bowen on 16/4/20. +// Copyright © 2016年. All rights reserved. +// + +#import + +typedef void (^ZBWSegmentChangeBlock)(NSInteger index); + +/* + 当segmentItem比较少时,如何排列显示。 +*/ +typedef NS_ENUM(NSInteger, ZBWSegmentItemDisplayType) { + ZBWSegmentItemDisplayType_FullWidth = 0, // 宽度填满,平均分配宽度。 默认。 + ZBWSegmentItemDisplayType_Center = 1, // 宽度不变,居中显示; + ZBWSegmentItemDisplayType_Left = 2 // 宽度不变,靠左显示; +}; + +@class ZBWSegmentItem; + +@protocol ZBWSegmentItemProtocol + +- (UIView *)customView; + +- (void)segmentItem:(ZBWSegmentItem *)item containerFrameChanged:(CGRect)rect; + +- (void)segmentItem:(ZBWSegmentItem *)item selectedChanged:(BOOL)isSelected ; + +@end + + +@interface ZBWSegmentItem : NSObject + +@property (nonatomic, retain) UIFont *normalFont; +@property (nonatomic, retain) UIFont *selectedFont; +@property (nonatomic, retain) UIColor *normalColor; +@property (nonatomic, retain) UIColor *selectedColor; +@property (nonatomic, retain) UIImage *normalImage; +@property (nonatomic, retain) UIImage *selectedImage; +@property (nonatomic, retain) UIImage *bgImage; +@property (nonatomic, copy) NSString *title; +@property (nonatomic, assign) CGFloat spaceH; + +@end + + +@interface ZBWSegmentView : UIView + +@property (nonatomic, assign) NSInteger selectedIndex; +@property (nonatomic, copy) ZBWSegmentChangeBlock indexChangeBlock; +@property (nonatomic, retain) UIColor *selectionIndicatorColor; +@property (nonatomic, assign) ZBWSegmentItemDisplayType displayType; +@property (nonatomic, copy) NSArray *items; + ++ (instancetype)initWithFrame:(CGRect)frame + horizontalMargin:(CGFloat)horizontalMargin + selectionIndicatorColor:(UIColor *)selectionIndicatorColor + displayType:(ZBWSegmentItemDisplayType)displayType + segmentItem:(NSArray *)items; + +@end diff --git a/ZBWUIKit/CustomViews/ZBWSegmentView.m b/ZBWUIKit/CustomViews/ZBWSegmentView.m new file mode 100644 index 0000000..3c407da --- /dev/null +++ b/ZBWUIKit/CustomViews/ZBWSegmentView.m @@ -0,0 +1,368 @@ +// +// ZBWSegmentView.m +// +// +// Created by Bowen on 16/4/20. +// Copyright © 2016年. All rights reserved. +// + +#import "ZBWSegmentView.h" + +@interface ZBWSegmentItem () + +@property (nonatomic) UIButton *itemView; +@property (nonatomic) CGFloat offsetX; +@property (nonatomic) CGFloat width; +@property (nonatomic) CGFloat contentWidth; + + +@property (nonatomic) NSInteger index; +@property (nonatomic) BOOL isSelected; + + +@property (nonatomic, copy) dispatch_block_t clickBlock; + +@end + +@implementation ZBWSegmentItem + +- (instancetype)init +{ + if (self = [super init]) { + self.normalColor = [UIColor blackColor]; + self.normalFont = [UIFont systemFontOfSize:14]; + self.selectedFont = [UIFont systemFontOfSize:16]; + self.selectedColor = [UIColor orangeColor]; + self.spaceH = 10; + } + return self; +} + +- (UIButton *)itemView +{ + if (!_itemView) { + UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 40)]; + [btn addTarget:self action:@selector(onBtnClick) forControlEvents:UIControlEventTouchUpInside]; + + UIView *customView = nil; + if ([self respondsToSelector:@selector(customView)]) { + customView = [self customView]; + } + + _itemView = btn; + + if (customView) { + [_itemView addSubview:customView]; + + self.width = customView.width + 2*self.spaceH; + } else { + if (self.bgImage) { + [btn setBackgroundImage:self.bgImage forState:UIControlStateNormal]; + } + if (self.normalImage && self.selectedImage) { + [btn setImage:self.normalImage forState:UIControlStateNormal]; + [btn setImage:self.selectedImage forState:UIControlStateHighlighted]; + [btn setImage:self.selectedImage forState:UIControlStateSelected]; + self.contentWidth = self.selectedImage.size.width; + } + else if (self.title) { + [btn setTitle:self.title forState:UIControlStateNormal]; + [btn setTitleColor:self.normalColor forState:UIControlStateNormal]; + [btn setTitleColor:self.selectedColor forState:UIControlStateHighlighted]; + [btn setTitleColor:self.selectedColor forState:UIControlStateSelected]; + btn.titleLabel.font = self.normalFont; + + self.contentWidth = [self.title boundingRectWithSize:CGSizeMake( 200, 40) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.selectedFont} context:nil].size.width; + } + + [_itemView sizeToFit]; + self.width = _itemView.frame.size.width + 2*self.spaceH; + } + + } + return _itemView; +} + +- (void)onBtnClick +{ + self.clickBlock ? self.clickBlock() : nil; +} + +#pragma mark- + +#pragma mark- Setter + +- (void)setIsSelected:(BOOL)isSelected +{ + if (_isSelected == isSelected) { + return; + } + _isSelected = isSelected; + + if (_isSelected) { + self.itemView.titleLabel.font = self.selectedFont ?: self.normalFont; + } else { + self.itemView.titleLabel.font = self.normalFont; + } + self.itemView.selected = isSelected; + + if ([self respondsToSelector:@selector(segmentItem:selectedChanged:)]) { + [self segmentItem:self selectedChanged:isSelected]; + } +} + +- (void)setWidth:(CGFloat)width +{ + _width = width; + CGRect rect = self.itemView.frame; + rect.size.width = width; + self.itemView.frame = rect; + + if ([self respondsToSelector:@selector(segmentItem:containerFrameChanged:)]) { + [self segmentItem:self containerFrameChanged:rect]; + } +} + +- (void)setOffsetX:(CGFloat)offsetX +{ + _offsetX = offsetX; + CGRect rect = self.itemView.frame; + rect.origin.x = _offsetX; + self.itemView.frame = rect; +} + +- (void)setNormalFont:(UIFont *)normalFont +{ + if (!normalFont) { + return; + } + + _normalFont = normalFont; +} + +- (void)setSelectedFont:(UIFont *)selectedFont +{ + if (!selectedFont) { + return; + } + + _selectedFont = selectedFont; +} + +- (void)setNormalColor:(UIColor *)normalColor +{ + if (!normalColor) { + return; + } + + _normalColor = normalColor; +} + +- (void)setSelectedColor:(UIColor *)selectedColor +{ + if (!selectedColor) { + return; + } + + _selectedColor = selectedColor; +} + +@end + +@interface ZBWSegmentView () + +@property (nonatomic, assign) CGFloat horizontalMargin; +@property (nonatomic) UIScrollView *scrollView; +@property (nonatomic) UIView *selectionIndicatorView; + +@end + +@implementation ZBWSegmentView + ++ (instancetype)initWithFrame:(CGRect)frame + horizontalMargin:(CGFloat)horizontalMargin + selectionIndicatorColor:(UIColor *)selectionIndicatorColor + displayType:(ZBWSegmentItemDisplayType)displayType + segmentItem:(NSArray *)items +{ + ZBWSegmentView *segmentView = [[ZBWSegmentView alloc] initWithFrame:frame]; + segmentView.horizontalMargin = horizontalMargin; + segmentView.selectionIndicatorColor = selectionIndicatorColor; + segmentView.displayType = displayType; + segmentView.items = items; + + return segmentView; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + [self initData]; + } + return self; +} + +- (instancetype)init +{ + if (self = [super init]) { + [self initData]; + } + return self; +} + +- (void)initData +{ + _selectedIndex = -1; + self.horizontalMargin = 10; + self.selectionIndicatorColor = [UIColor orangeColor]; + [self addSubview:self.scrollView]; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + [self updateUI]; +} + +- (void)updateUI +{ + self.scrollView.frame = self.bounds; + + NSInteger scrollWidth = self.scrollView.frame.size.width; + NSInteger count = _items.count; + CGFloat offsetX = self.horizontalMargin; + for (int i = 0; i < count; i++) { + ZBWSegmentItem *item = _items[i]; + __weak typeof(self) weakSelf = self; + item.clickBlock = ^{ + weakSelf.selectedIndex = i; + // 回调上层 + weakSelf.indexChangeBlock ? weakSelf.indexChangeBlock(i) : nil; + }; + item.offsetX = offsetX; + UIView *view = item.itemView; + CGRect rect = view.frame; + rect.size.height = CGRectGetHeight(self.bounds); + view.frame = rect; + + offsetX += item.width; + [self.scrollView addSubview:view]; + } + offsetX += self.horizontalMargin; + + // 如果没有填充满,要填充满 + if (count > 0 && offsetX < scrollWidth) { + switch (self.displayType) { + case ZBWSegmentItemDisplayType_Center: + { + CGFloat addOffsetX = (scrollWidth - offsetX)/2; + for (int i = 0 ; i < self.items.count; i++) { + ZBWSegmentItem *item = self.items[i]; + item.offsetX += addOffsetX; + } + } + break; + case ZBWSegmentItemDisplayType_FullWidth: + { + CGFloat addWidth = (scrollWidth - offsetX)/count; + for (int i = 0 ; i < self.items.count; i++) { + ZBWSegmentItem *item = self.items[i]; + item.width += addWidth; + item.offsetX += addWidth * i; + } + } + default: + break; + } + } + + self.scrollView.contentSize = CGSizeMake(offsetX, CGRectGetHeight(self.bounds)); + + [self.scrollView addSubview:self.selectionIndicatorView]; + CGRect rect = self.selectionIndicatorView.frame; + rect.origin.y = CGRectGetHeight(self.bounds) - CGRectGetHeight(rect); + self.selectionIndicatorView.frame = rect; +} + +- (void)setItems:(NSArray *)items +{ + _items = items; + + [self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + [self updateUI]; +} + +#pragma mark- Setter + +- (void)setSelectedIndex:(NSInteger)selectedIndex +{ + if (self.items.count <= selectedIndex) { + return; + } +// if (_selectedIndex == selectedIndex) { +// return; +// } + + // 之前的选中item,修改成未选中 + if (_selectedIndex >= 0 && _selectedIndex < self.items.count) { + ZBWSegmentItem *lastSelecteItem = self.items[_selectedIndex]; + lastSelecteItem.isSelected = NO; + } + + _selectedIndex = selectedIndex; + ZBWSegmentItem *selectedItem = self.items[selectedIndex]; + selectedItem.isSelected = YES; + + // 选中标记view,动画 + CGRect rect = self.selectionIndicatorView.frame; +// rect.origin.x = selectedItem.offsetX; +// rect.size.width = selectedItem.width; + rect.origin.x = selectedItem.offsetX + (selectedItem.width - selectedItem.contentWidth)/2; + rect.size.width = selectedItem.contentWidth; + + [UIView animateWithDuration:.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + self.selectionIndicatorView.frame = rect; + } completion:nil]; + + // scroll 到中间 + CGRect visibleRect = self.scrollView.bounds; + visibleRect.origin.x = ((selectedItem.offsetX + selectedItem.width/2) - CGRectGetWidth(visibleRect)/2); + [self.scrollView scrollRectToVisible:visibleRect animated:YES]; +} + +- (void)setSelectionIndicatorColor:(UIColor *)selectionIndicatorColor +{ + if (!selectionIndicatorColor) { + return; + } + _selectionIndicatorColor = selectionIndicatorColor; + + _selectionIndicatorView.backgroundColor = selectionIndicatorColor; +} + +#pragma mark- Getter + +- (UIScrollView *)scrollView +{ + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _scrollView.showsVerticalScrollIndicator = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + } + return _scrollView; +} + +- (UIView *)selectionIndicatorView +{ + if (!_selectionIndicatorView) { + _selectionIndicatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 2)]; + _selectionIndicatorView.userInteractionEnabled = NO; + _selectionIndicatorView.backgroundColor = self.selectionIndicatorColor; + } + + return _selectionIndicatorView; +} + +@end diff --git a/ZBWUIKit/ViewControllers/ZBWSegmentViewController.h b/ZBWUIKit/ViewControllers/ZBWSegmentViewController.h new file mode 100644 index 0000000..55c5e09 --- /dev/null +++ b/ZBWUIKit/ViewControllers/ZBWSegmentViewController.h @@ -0,0 +1,65 @@ +// +// ZBWSegmentViewController.h +// ContactDemo +// +// Created by Bowen on 15/11/17. +// Copyright © 2015年. All rights reserved. +// + +#import +#import "ZBWSegmentView.h" + +@interface UIViewController (ZBWSegment) +@property (nonatomic) NSString *zbw_segmentIdentify; +@property (nonatomic) NSInteger zbw_segmentIndex; +@end + + +@class ZBWSegmentViewController; +@class ZBWSegmentItem; +@protocol ZBWSegmentViewControllerPotocol + +- (UIViewController *)segmentVC:(ZBWSegmentViewController *)segmentVC vcForIndex:(NSInteger)index; + +- (NSArray *)segmentItems:(ZBWSegmentViewController *)segmentVC; + +- (void)segmentVC:(ZBWSegmentViewController *)segmentVC willDisplayVC:(UIViewController *)vc forIndex:(NSInteger)index; +- (void)segmentVC:(ZBWSegmentViewController *)segmentVC didEndDisplayingVC:(UIViewController *)vc forIndex:(NSInteger)index; + +@end + + +@interface ZBWSegmentViewController : UIViewController + +@property (nonatomic, assign) float heightOfSegmentView; // segment高度 默认56 +@property (nonatomic, assign) ZBWSegmentItemDisplayType segmentItemDisplayType; +@property (nonatomic) UIColor *selectionIndicatorColor; // 默认[UIColor orangeColor] +@property (nonatomic) UIColor *bgColorOfSegmentView; // 默认 [UIColor whiteColor] +@property (nonatomic, readonly) NSInteger currentIndex; +@property (nonatomic, weak, readonly) UIViewController *currentVc; + +@property (nonatomic, readonly) UIScrollView *scrollView; + +@property (nonatomic, weak) id dataSource; + + +@property (nonatomic, assign) BOOL dontCleanOtherVC; // 划出屏幕不卸载。默认NO:卸载。 + +// 垂直偏移量 +@property (nonatomic, assign) float offsetY; // segmentview 、scrollview整体垂直偏移 + + +- (UIViewController *)dequeueReusableVCWithIdentifier:(NSString *)identifier; + + +- (void)reloadSegmentView; +- (void)reloadData; +- (void)showViewControllerAtIndex:(NSInteger)index; + +- (void)showViewControllerAtIndex:(NSInteger)index animation:(BOOL)animation; + +- (void)setOffsetY:(float)offsetY animation:(BOOL)animation; + +- (void)setSegmentViewHidden:(BOOL)hidden animated:(BOOL)animated; + +@end diff --git a/ZBWUIKit/ViewControllers/ZBWSegmentViewController.m b/ZBWUIKit/ViewControllers/ZBWSegmentViewController.m new file mode 100644 index 0000000..95acc9c --- /dev/null +++ b/ZBWUIKit/ViewControllers/ZBWSegmentViewController.m @@ -0,0 +1,427 @@ +// +// ZBWSegmentViewController.m +// ContactDemo +// +// Created by Bowen on 15/11/17. +// Copyright © 2015年. All rights reserved. +// + +#import "ZBWSegmentViewController.h" +#import + +const void *UIViewController_ZBWSegmentIdentify_Key = &UIViewController_ZBWSegmentIdentify_Key; +const void *UIViewController_ZBWSegmentIndex_Key = &UIViewController_ZBWSegmentIndex_Key; +@implementation UIViewController (ZBWSegment) + +- (void)setZbw_segmentIdentify:(NSString *)zbw_segmentIdentify +{ + objc_setAssociatedObject(self, UIViewController_ZBWSegmentIdentify_Key, zbw_segmentIdentify, OBJC_ASSOCIATION_COPY); +} + +- (NSString *)zbw_segmentIdentify +{ + return objc_getAssociatedObject(self, UIViewController_ZBWSegmentIdentify_Key); +} + +- (void)setZbw_segmentIndex:(NSInteger)zbw_segmentIndex +{ + objc_setAssociatedObject(self, UIViewController_ZBWSegmentIndex_Key, @(zbw_segmentIndex), OBJC_ASSOCIATION_RETAIN); +} + +- (NSInteger)zbw_segmentIndex +{ + NSNumber *indexNum = objc_getAssociatedObject(self, UIViewController_ZBWSegmentIndex_Key); + return indexNum ? indexNum.integerValue : -1; +} + +@end + + + +#define kTX_Segment_Y ((self.navigationController && self.navigationController == self.parentViewController && self.navigationController.navigationBar && !self.navigationController.navigationBar.hidden) ? 64 : 0) +#define kTX_SegmentHeight 56 + +#define kZBWSegmentVC_No_Reuse_Identify @"com.haihu.ZBWSegmentVC_No_Reuse_Identify" + +@interface ZBWSegmentViewController () + +@property (nonatomic) UIScrollView *scrollView; +@property (nonatomic) ZBWSegmentView *segmentControl; + +@property (nonatomic) NSInteger defaultIndex; + +@property (nonatomic, assign) NSInteger count; + +@property (nonatomic) NSMutableDictionary *reusableVCMap; +@property (nonatomic) NSMutableDictionary *usingVCMap; + +@property (nonatomic) NSInteger currentIndex; +@property (nonatomic, weak) UIViewController *currentVc; + +@end + +@implementation ZBWSegmentViewController + +- (void)reloadSegmentView +{ + // 设置segmentView + if (self.dataSource && [self.dataSource respondsToSelector:@selector(segmentItems:)]) { + NSArray *items = [self.dataSource segmentItems:self]; + self.segmentControl.items = items; + self.count = items.count; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width * self.count, self.scrollView.bounds.size.height); + self.segmentControl.selectedIndex = self.currentIndex; + } +} + +- (void)reloadData +{ + // 加入到复用 + [self.usingVCMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + [self addToReusableMap:obj]; + }]; + + // 设置segmentView + if (self.dataSource && [self.dataSource respondsToSelector:@selector(segmentItems:)]) { + NSArray *items = [self.dataSource segmentItems:self]; + self.segmentControl.items = items; + self.count = items.count; + self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width * self.count, self.scrollView.bounds.size.height); + self.segmentControl.selectedIndex = self.currentIndex; + } + + // 加载VC + if (self.count > 0 && self.currentIndex >=0 && self.currentIndex < self.count && self.dataSource && [self.dataSource respondsToSelector:@selector(segmentVC:vcForIndex:)]) { + UIViewController *vc = [self.dataSource segmentVC:self vcForIndex:self.currentIndex]; + [self setViewController:vc atIndex:self.currentIndex]; + self.currentVc = vc; + } +} + + +- (UIViewController *)dequeueReusableVCWithIdentifier:(NSString *)identifier +{ + if (!identifier) { + return nil; + } + NSLog(@"获取复用VC, identify [ %@ ]", identifier); + return [[self reusableVCSet:identifier] anyObject]; +} + +- (void)showViewControllerAtIndex:(NSInteger)index { + if (index >= self.count) { + return; + } + self.currentIndex = index; + + CGFloat width = CGRectGetWidth(self.scrollView.bounds); + self.scrollView.contentOffset = CGPointMake(index*width, 0); +} + +- (void)showViewControllerAtIndex:(NSInteger)index animation:(BOOL)animation { + if (index >= self.count) { + return; + } + CGFloat width = CGRectGetWidth(self.scrollView.bounds); + [self.scrollView scrollRectToVisible:CGRectMake(index*width, 0, self.scrollView.width, self.scrollView.height) animated:animation]; +} + +#pragma mark- 缓存 +- (NSMutableSet *)reusableVCSet:(NSString *)identify +{ + NSMutableSet *set = self.reusableVCMap[identify]; + if (!set) { + set = [NSMutableSet setWithCapacity:2]; + self.reusableVCMap[identify] = set; + } + return set; +} + +#pragma mark 载入载出 +- (void)setViewController:(UIViewController *)vc atIndex:(NSInteger)index +{ + NSLog(@"添加vc到UI, index: [ %ld ], identify: [ %@ ]", (long)index, vc.zbw_segmentIdentify); + if (!vc.parentViewController) { + [self addChildViewController:vc]; + [self.scrollView addSubview:vc.view]; + + [vc didMoveToParentViewController:self]; + vc.zbw_segmentIndex = index; + +// vc.view.backgroundColor = [UIColor colorWithRed:(random()%255)/255.0 green:(random()%255)/255.0 blue:(random()%255)/255.0 alpha:1.0]; + } + CGRect rect = self.scrollView.frame; + vc.view.frame = CGRectMake(CGRectGetWidth(rect) * index, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)); + + if ([self.dataSource respondsToSelector:@selector(segmentVC:willDisplayVC:forIndex:)]) { + [self.dataSource segmentVC:self willDisplayVC:vc forIndex:index]; + } + [self addToUsingMap:vc]; +} + +- (void)removeViewController:(UIViewController *)vc +{ + if (vc.parentViewController) { + [vc willMoveToParentViewController:nil]; + [vc.view removeFromSuperview]; + [vc removeFromParentViewController]; + } +} + +#pragma mark- life cycle + +- (instancetype)init +{ + if (self = [super init]) { + _currentIndex = -1; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // 添加一个空的view,解决iOS7后,scrollview 偏移 + [self.view addSubview:[[UIView alloc] init]]; + [self.view addSubview:self.segmentControl]; + [self.view insertSubview:self.scrollView belowSubview:self.segmentControl]; + self.currentIndex = 0; + [self reloadData]; +} + +- (void)viewDidLayoutSubviews +{ + [super viewDidLayoutSubviews]; + [self updateUI]; +} + +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; +} + +- (void)setOffsetY:(float)offsetY animation:(BOOL)animation { + self.offsetY = offsetY; + + __weakSelf + if (animation) { + [UIView animateWithDuration:.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ + [__weakedSelf updateUI]; + } completion:nil]; + } else { + [self updateUI]; + } +} + +- (void)updateUI { + self.segmentControl.frame = CGRectMake(0, kTX_Segment_Y + self.offsetY, CGRectGetWidth(self.view.bounds), self.heightOfSegmentView); + UIView *lineView = [self.segmentControl viewWithTag:1234]; + if (lineView) { + CGRect rect = lineView.frame; + rect = CGRectMake(0, self.heightOfSegmentView - rect.size.height, CGRectGetWidth(self.view.bounds), rect.size.height); + lineView.frame = rect; + } + + self.scrollView.frame = CGRectMake(0, + kTX_Segment_Y + self.offsetY + (self.segmentControl.hidden ? 0 : self.heightOfSegmentView), + CGRectGetWidth(self.view.bounds), + CGRectGetHeight(self.view.bounds) - kTX_Segment_Y - self.offsetY - (self.segmentControl.hidden ? 0 : self.heightOfSegmentView)); + + [self.usingVCMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + UIViewController *vc = obj; + CGRect rect = vc.view.frame; + rect.size.height = CGRectGetHeight(self.scrollView.bounds); + vc.view.frame = rect; + }]; + self.scrollView.contentSize = CGSizeMake(self.count * CGRectGetWidth(self.scrollView.bounds), CGRectGetHeight(self.scrollView.bounds)); +} + +- (void)setSegmentViewHidden:(BOOL)hidden animated:(BOOL)animated { + self.segmentControl.hidden = hidden; + + if (animated) { + [UIView animateWithDuration:.5 animations:^{ + [self updateUI]; + } completion:^(BOOL finished) { + + }]; + } + else { + [self updateUI]; + } +} + +- (UIViewController *)vcAtIndex:(NSInteger)index +{ + NSLog(@"获取VC, index [ %ld ]", (long)index); + UIViewController *vc = self.usingVCMap[@(index)]; + if (!vc) { + vc = [self.dataSource segmentVC:self vcForIndex:index]; + vc.zbw_segmentIndex = index; + NSAssert(vc, @"segmentVC:vcForIndex: 不能返回nil"); + self.usingVCMap[@(index)] = vc; + } + return vc; +} + +- (void)addToReusableMap:(UIViewController *)vc +{ + // 添加到“复用”缓存中 + NSString *identify = vc.zbw_segmentIdentify; + NSLog(@"加入到 复用 Map中,index [ %ld ] identify [ %@ ]", (long)vc.zbw_segmentIndex, identify); + if (identify) { + [[self reusableVCSet:identify] addObject:vc]; + } + // 从“正在使用”中删除 + [self.usingVCMap removeObjectForKey:@(vc.zbw_segmentIndex)]; + + if ([self.dataSource respondsToSelector:@selector(segmentVC:didEndDisplayingVC:forIndex:)]) { + [self.dataSource segmentVC:self didEndDisplayingVC:vc forIndex:vc.zbw_segmentIndex]; + } + + if (!identify) { + [self removeViewController:vc]; + } +} + +- (void)addToUsingMap:(UIViewController *)vc +{ + NSString *identify = vc.zbw_segmentIdentify; + NSLog(@"加入到using Map中,index [ %ld ] identify [ %@ ]", (long)vc.zbw_segmentIndex, identify); + // 添加的到“正在使用” + self.usingVCMap[@(vc.zbw_segmentIndex)] = vc; + // 从“复用”中删除 + if (identify) { + [[self reusableVCSet:identify] removeObject:vc]; + } +} + +- (void)showIndexs:(NSArray *)indexs +{ + NSLog(@"showIndexs : %@", indexs); + if (!self.dontCleanOtherVC) { + // 清理正在显示的VC + [self.usingVCMap enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + // 不需要显示, 加入到复用 + if (![indexs containsObject:key]) { + [self addToReusableMap:obj]; + } + }]; + } + + [indexs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSNumber *indexNum = obj; + // 不存在 + if (!self.usingVCMap[indexNum] && indexNum.integerValue < self.count && indexNum.integerValue >= 0) { + UIViewController *vc = [self vcAtIndex:indexNum.integerValue]; + [self setViewController:vc atIndex:indexNum.integerValue]; + } + }]; +} + +#pragma mark- Getter 属性 +- (NSMutableDictionary *)reusableVCMap +{ + if (!_reusableVCMap) { + _reusableVCMap = [NSMutableDictionary dictionaryWithCapacity:2]; + } + return _reusableVCMap; +} + +- (NSMutableDictionary *)usingVCMap +{ + if (!_usingVCMap) { + _usingVCMap = [NSMutableDictionary dictionaryWithCapacity:2]; + } + return _usingVCMap; +} + +- (ZBWSegmentView *)segmentControl +{ + if (!_segmentControl) { + _segmentControl = [[ZBWSegmentView alloc] initWithFrame:CGRectMake(0, kTX_Segment_Y + self.offsetY, CGRectGetWidth(self.view.bounds), self.heightOfSegmentView)]; + _segmentControl.backgroundColor = self.bgColorOfSegmentView ? : [UIColor whiteColor]; + _segmentControl.selectionIndicatorColor = self.selectionIndicatorColor; + _segmentControl.displayType = self.segmentItemDisplayType; + + // 添加阴影遮罩 + CGFloat height = 1; + UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, self.heightOfSegmentView - height, CGRectGetWidth(self.segmentControl.frame), height)]; + view.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:.2]; + view.tag = 1234; + [_segmentControl addSubview:view]; + + __weak typeof(self) _self = self; + [_segmentControl setIndexChangeBlock:^(NSInteger index) { +// _self.currentIndex = index; + + CGFloat width = CGRectGetWidth(_self.scrollView.bounds); +// CGRect rect = CGRectMake(index*width, 0, width, CGRectGetHeight(_self.scrollView.bounds)); +// [self.scrollView scrollRectToVisible:rect animated:YES]; + _self.scrollView.contentOffset = CGPointMake(index*width, 0); + + }]; +// if (self.titles.count <= 1) { +// _segmentControl.hidden = YES; +// } + } + return _segmentControl; +} + +- (UIScrollView *)scrollView +{ + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, kTX_Segment_Y + self.offsetY + (self.segmentControl.hidden ? 0 : self.heightOfSegmentView), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - kTX_Segment_Y - self.offsetY - self.heightOfSegmentView)]; +// _scrollView.contentSize = CGSizeMake(self.viewControllers.count * CGRectGetWidth(self.view.bounds), 0); + _scrollView.pagingEnabled = YES; + _scrollView.bounces = NO; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.delegate = self; + } + return _scrollView; +} + +- (float)heightOfSegmentView +{ + return _heightOfSegmentView == 0 ? kTX_SegmentHeight : _heightOfSegmentView; +} + +#pragma mark- UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil]; + CGFloat offsetX = scrollView.contentOffset.x; + CGFloat width = scrollView.bounds.size.width; + + NSMutableArray *showIndexArray = [NSMutableArray arrayWithCapacity:2]; + NSInteger index = offsetX / width; + CGFloat x = offsetX - index * width; + + [showIndexArray addObject:@(index)]; + if (x > 0) { + [showIndexArray addObject:@(index + 1)]; + } + + [self showIndexs:showIndexArray]; + + self.currentIndex = MAX(MIN((offsetX + width/2) /width, self.count), 0); +} + +//- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView +//{ +// CGFloat offsetX = scrollView.contentOffset.x; +// float x = offsetX/scrollView.bounds.size.width; +// self.currentIndex = ceilf(x); +//} + +- (void)setCurrentIndex:(NSInteger)currentIndex +{ + self.currentVc = self.usingVCMap[@(currentIndex)]; + if (_currentIndex == currentIndex) { + return; + } + _currentIndex = currentIndex; + [self.segmentControl setSelectedIndex:_currentIndex]; +} + +@end diff --git a/ZBWUIKit/ZBWUIKit-prefix.pch b/ZBWUIKit/ZBWUIKit-prefix.pch new file mode 100644 index 0000000..5fb3e19 --- /dev/null +++ b/ZBWUIKit/ZBWUIKit-prefix.pch @@ -0,0 +1,18 @@ +// +// ZBWUIKit-prefix.pch +// ZBWUIKit +// +// Created by 朱博文 on 2019/1/14. +// Copyright © 2019年 朱博文. All rights reserved. +// + +#ifndef ZBWUIKit_prefix_h +#define ZBWUIKit_prefix_h + +#import +#import +#import +#import "ZBWUIKit.h" + + +#endif /* ZBWUIKit_prefix_h */ diff --git a/ZBWUIKit/ZBWUIKit.h b/ZBWUIKit/ZBWUIKit.h new file mode 100644 index 0000000..fbb2ea5 --- /dev/null +++ b/ZBWUIKit/ZBWUIKit.h @@ -0,0 +1,26 @@ +// +// ZBWUIKit.h +// ZBWUIKit +// +// Created by 朱博文 on 16/8/29. +// Copyright © 2016年 朱博文. All rights reserved. +// + +#import + +//! Project version number for ZBWUIKit. +FOUNDATION_EXPORT double ZBWUIKitVersionNumber; + +//! Project version string for ZBWUIKit. +FOUNDATION_EXPORT const unsigned char ZBWUIKitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + +#import +#import +#import +#import + +#import "ZBWUIKit+Category.h" +#import "ZBWCustomViews.h"