From 93216d4a3b9fc65b8231989529fe156263b484c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=8D=9A=E6=96=87?= <> Date: Fri, 25 Feb 2022 16:53:19 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=88=B0GitHub=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Podfile | 17 + Podfile.lock | 90 ++++ ZBWUIKit.podspec | 89 ++++ ZBWUIKit.xcodeproj/project.pbxproj | 503 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 5217 bytes .../xcschemes/xcschememanagement.plist | 14 + ZBWUIKit.xcworkspace/contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../IDEFindNavigatorScopes.plist | 5 + .../UserInterfaceState.xcuserstate | Bin 0 -> 52636 bytes .../UIKit+Category/UIResponder+ZBWStack.h | 54 ++ .../UIKit+Category/UIResponder+ZBWStack.m | 231 ++++++++ .../UIKit+Category/ZBWUIKit+Category.h | 15 + ZBWUIKit/CustomViews/GridView/ZBWGridCell.h | 71 +++ ZBWUIKit/CustomViews/GridView/ZBWGridCell.m | 159 ++++++ .../CustomViews/GridView/ZBWGridCellButton.h | 34 ++ .../CustomViews/GridView/ZBWGridCellButton.m | 44 ++ ZBWUIKit/CustomViews/GridView/ZBWGridView.h | 72 +++ ZBWUIKit/CustomViews/GridView/ZBWGridView.m | 244 +++++++++ .../GridView/ZBWPageableGridView.h | 40 ++ .../GridView/ZBWPageableGridView.m | 252 +++++++++ .../CustomViews/TagView/ZBWImageTagItemView.h | 24 + .../CustomViews/TagView/ZBWImageTagItemView.m | 112 ++++ ZBWUIKit/CustomViews/TagView/ZBWTagItemView.h | 75 +++ ZBWUIKit/CustomViews/TagView/ZBWTagItemView.m | 359 +++++++++++++ ZBWUIKit/CustomViews/TagView/ZBWTagView.h | 79 +++ ZBWUIKit/CustomViews/TagView/ZBWTagView.m | 272 ++++++++++ .../CustomViews/UITableView+ZBWAddition.h | 40 ++ .../CustomViews/UITableView+ZBWAddition.m | 143 +++++ ZBWUIKit/CustomViews/UIView+ZBWLoadingView.h | 36 ++ ZBWUIKit/CustomViews/UIView+ZBWLoadingView.m | 232 ++++++++ ZBWUIKit/CustomViews/ZBWBannerView.h | 27 + ZBWUIKit/CustomViews/ZBWBannerView.m | 253 +++++++++ ZBWUIKit/CustomViews/ZBWCustomViews.h | 17 + ZBWUIKit/CustomViews/ZBWLoadingView.h | 80 +++ ZBWUIKit/CustomViews/ZBWLoadingView.m | 310 +++++++++++ ZBWUIKit/CustomViews/ZBWPageControlView.h | 23 + ZBWUIKit/CustomViews/ZBWPageControlView.m | 77 +++ ZBWUIKit/CustomViews/ZBWPhoneNumTextField.h | 24 + ZBWUIKit/CustomViews/ZBWPhoneNumTextField.m | 422 +++++++++++++++ ZBWUIKit/CustomViews/ZBWSegmentView.h | 64 +++ ZBWUIKit/CustomViews/ZBWSegmentView.m | 368 +++++++++++++ .../ZBWSegmentViewController.h | 65 +++ .../ZBWSegmentViewController.m | 427 +++++++++++++++ ZBWUIKit/ZBWUIKit-prefix.pch | 18 + ZBWUIKit/ZBWUIKit.h | 26 + 48 files changed, 5540 insertions(+) create mode 100644 Podfile create mode 100644 Podfile.lock create mode 100644 ZBWUIKit.podspec create mode 100644 ZBWUIKit.xcodeproj/project.pbxproj create mode 100644 ZBWUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ZBWUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ZBWUIKit.xcodeproj/project.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ZBWUIKit.xcodeproj/xcuserdata/zhubowen.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ZBWUIKit.xcworkspace/contents.xcworkspacedata create mode 100644 ZBWUIKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/IDEFindNavigatorScopes.plist create mode 100644 ZBWUIKit.xcworkspace/xcuserdata/zhubowen.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.h create mode 100644 ZBWUIKit/Category/UIKit+Category/UIResponder+ZBWStack.m create mode 100644 ZBWUIKit/Category/UIKit+Category/ZBWUIKit+Category.h create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridCell.h create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridCell.m create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.h create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridCellButton.m create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridView.h create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWGridView.m create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.h create mode 100644 ZBWUIKit/CustomViews/GridView/ZBWPageableGridView.m create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.h create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWImageTagItemView.m create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWTagItemView.h create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWTagItemView.m create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWTagView.h create mode 100644 ZBWUIKit/CustomViews/TagView/ZBWTagView.m create mode 100644 ZBWUIKit/CustomViews/UITableView+ZBWAddition.h create mode 100644 ZBWUIKit/CustomViews/UITableView+ZBWAddition.m create mode 100644 ZBWUIKit/CustomViews/UIView+ZBWLoadingView.h create mode 100644 ZBWUIKit/CustomViews/UIView+ZBWLoadingView.m create mode 100644 ZBWUIKit/CustomViews/ZBWBannerView.h create mode 100644 ZBWUIKit/CustomViews/ZBWBannerView.m create mode 100644 ZBWUIKit/CustomViews/ZBWCustomViews.h create mode 100644 ZBWUIKit/CustomViews/ZBWLoadingView.h create mode 100644 ZBWUIKit/CustomViews/ZBWLoadingView.m create mode 100644 ZBWUIKit/CustomViews/ZBWPageControlView.h create mode 100644 ZBWUIKit/CustomViews/ZBWPageControlView.m create mode 100644 ZBWUIKit/CustomViews/ZBWPhoneNumTextField.h create mode 100644 ZBWUIKit/CustomViews/ZBWPhoneNumTextField.m create mode 100644 ZBWUIKit/CustomViews/ZBWSegmentView.h create mode 100644 ZBWUIKit/CustomViews/ZBWSegmentView.m create mode 100644 ZBWUIKit/ViewControllers/ZBWSegmentViewController.h create mode 100644 ZBWUIKit/ViewControllers/ZBWSegmentViewController.m create mode 100644 ZBWUIKit/ZBWUIKit-prefix.pch create mode 100644 ZBWUIKit/ZBWUIKit.h 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 0000000000000000000000000000000000000000..3c7ebaf386c2a6eabf78d0f8a23ff69f910501e2 GIT binary patch literal 5217 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 + + + + 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 0000000000000000000000000000000000000000..62a4ef0011844fec5acec58c1e6af45a7bb8016a GIT binary patch literal 52636 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 literal 0 HcmV?d00001 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"