├── README.md ├── Screenshots ├── datePicker_code.png ├── datePicker_screenshots.png ├── inputView_code.png ├── inputView_screenshots.png ├── timePicker_code.png └── timePicker_screenshots.png ├── TZPopInputView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── tanzhen.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── tanzhen.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── TZPopInputView.xcscheme │ └── xcschememanagement.plist ├── TZPopInputView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── disabled_left.imageset │ │ ├── Contents.json │ │ ├── def_left.png │ │ ├── def_left@2x.png │ │ └── def_left@3x.png │ ├── disabled_right.imageset │ │ ├── Contents.json │ │ ├── def_right.png │ │ ├── def_right@2x.png │ │ └── def_right@3x.png │ ├── enable_left.imageset │ │ ├── Contents.json │ │ ├── sel_right.png │ │ ├── sel_right@2x.png │ │ └── sel_right@3x.png │ └── enable_right.imageset │ │ ├── Contents.json │ │ ├── sel_left.png │ │ ├── sel_left@2x.png │ │ └── sel_left@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── TZDatePicker │ ├── TZDatePickerView.h │ ├── TZDatePickerView.m │ └── TZDatePickerView.xib ├── TZPopInputView │ ├── TZPopInputView.h │ ├── TZPopInputView.m │ └── TZPopInputView.xib ├── TZTimePicker │ ├── TZTimePickerView.h │ ├── TZTimePickerView.m │ └── TZTimePickerView.xib ├── ViewController.h ├── ViewController.m └── main.m ├── TZPopInputViewTests ├── Info.plist └── TZPopInputViewTests.m └── TZPopInputViewUITests ├── Info.plist └── TZPopInputViewUITests.m /README.md: -------------------------------------------------------------------------------- 1 | # SomeGoodCustomView 2 | 3 | 里面目前共三个自定义控件,封装性较好,使用方法较友好。也欢迎大家把自己封装的好控件拿出来,一起分享和学习。详见Demo,欢迎批评指正。 4 | 5 | ## 一. 时间选择器 6 | 7 | * 代码。先调用show方法,再定义回调block。 8 | 9 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/timePicker_code.png) 10 | 11 | * 截图。控件内部加入了时间过滤(截图时间12-09 09:55)并记忆了上次的选择。 12 | 13 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/timePicker_screenshots.png) 14 | 15 | ## 二. 多行输入框 16 | 17 | * 代码。设置数据,调用show方法,定义回调block。 18 | 19 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/inputView_code.png) 20 | 21 | * 截图。控件内部加入了手机号、邮箱检测方法,提示方式也较合适,无耦合。 22 | 23 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/inputView_screenshots.png) 24 | 25 | ## 三. 日期选择器 26 | 27 | * 代码。先调用show方法,再定义回调block。 28 | 29 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/datePicker_code.png) 30 | 31 | * 截图。控件内部加入了简单的时间判断和非法选择时的提示,把合法的时间str传出去。 32 | 33 | ![image](https://github.com/banchichen/SomeGoodCustomView/blob/master/Screenshots/datePicker_screenshots.png) 34 | 35 | * 更多信息请见博客:[我的博客](http://www.cnblogs.com/tanzhenblog/ "半尺尘 - 博客园") 36 | 37 | -------------------------------------------------------------------------------- /Screenshots/datePicker_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/datePicker_code.png -------------------------------------------------------------------------------- /Screenshots/datePicker_screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/datePicker_screenshots.png -------------------------------------------------------------------------------- /Screenshots/inputView_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/inputView_code.png -------------------------------------------------------------------------------- /Screenshots/inputView_screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/inputView_screenshots.png -------------------------------------------------------------------------------- /Screenshots/timePicker_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/timePicker_code.png -------------------------------------------------------------------------------- /Screenshots/timePicker_screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/Screenshots/timePicker_screenshots.png -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 90D7E3A51C16BBAD000997A1 /* TZTimePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90D7E3A31C16BBAD000997A1 /* TZTimePickerView.m */; }; 11 | 90D7E3A61C16BBAD000997A1 /* TZTimePickerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 90D7E3A41C16BBAD000997A1 /* TZTimePickerView.xib */; }; 12 | 90DEFEE91C071CFC00A61971 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFEE81C071CFC00A61971 /* main.m */; }; 13 | 90DEFEEC1C071CFC00A61971 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFEEB1C071CFC00A61971 /* AppDelegate.m */; }; 14 | 90DEFEEF1C071CFC00A61971 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFEEE1C071CFC00A61971 /* ViewController.m */; }; 15 | 90DEFEF21C071CFC00A61971 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DEFEF01C071CFC00A61971 /* Main.storyboard */; }; 16 | 90DEFEF41C071CFC00A61971 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90DEFEF31C071CFC00A61971 /* Assets.xcassets */; }; 17 | 90DEFEF71C071CFC00A61971 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 90DEFEF51C071CFC00A61971 /* LaunchScreen.storyboard */; }; 18 | 90DEFF021C071CFD00A61971 /* TZPopInputViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFF011C071CFD00A61971 /* TZPopInputViewTests.m */; }; 19 | 90DEFF0D1C071CFD00A61971 /* TZPopInputViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFF0C1C071CFD00A61971 /* TZPopInputViewUITests.m */; }; 20 | 90DEFF251C071D5C00A61971 /* TZPopInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DEFF231C071D5C00A61971 /* TZPopInputView.m */; }; 21 | 90DEFF261C071D5C00A61971 /* TZPopInputView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 90DEFF241C071D5C00A61971 /* TZPopInputView.xib */; }; 22 | 90E9D97F1C1174420077C92D /* TZDatePickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90E9D97D1C1174420077C92D /* TZDatePickerView.m */; }; 23 | 90E9D9801C1174420077C92D /* TZDatePickerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 90E9D97E1C1174420077C92D /* TZDatePickerView.xib */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 90DEFEFE1C071CFD00A61971 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 90DEFEDC1C071CFC00A61971 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 90DEFEE31C071CFC00A61971; 32 | remoteInfo = TZPopInputView; 33 | }; 34 | 90DEFF091C071CFD00A61971 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 90DEFEDC1C071CFC00A61971 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 90DEFEE31C071CFC00A61971; 39 | remoteInfo = TZPopInputView; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 90D7E3A21C16BBAD000997A1 /* TZTimePickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZTimePickerView.h; sourceTree = ""; }; 45 | 90D7E3A31C16BBAD000997A1 /* TZTimePickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZTimePickerView.m; sourceTree = ""; }; 46 | 90D7E3A41C16BBAD000997A1 /* TZTimePickerView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TZTimePickerView.xib; sourceTree = ""; }; 47 | 90DEFEE41C071CFC00A61971 /* TZPopInputView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TZPopInputView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 90DEFEE81C071CFC00A61971 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | 90DEFEEA1C071CFC00A61971 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 90DEFEEB1C071CFC00A61971 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 90DEFEED1C071CFC00A61971 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 52 | 90DEFEEE1C071CFC00A61971 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 53 | 90DEFEF11C071CFC00A61971 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 90DEFEF31C071CFC00A61971 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 90DEFEF61C071CFC00A61971 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 90DEFEF81C071CFC00A61971 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 90DEFEFD1C071CFD00A61971 /* TZPopInputViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZPopInputViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 90DEFF011C071CFD00A61971 /* TZPopInputViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZPopInputViewTests.m; sourceTree = ""; }; 59 | 90DEFF031C071CFD00A61971 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 90DEFF081C071CFD00A61971 /* TZPopInputViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TZPopInputViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 90DEFF0C1C071CFD00A61971 /* TZPopInputViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TZPopInputViewUITests.m; sourceTree = ""; }; 62 | 90DEFF0E1C071CFD00A61971 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 90DEFF221C071D5C00A61971 /* TZPopInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPopInputView.h; sourceTree = ""; }; 64 | 90DEFF231C071D5C00A61971 /* TZPopInputView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPopInputView.m; sourceTree = ""; }; 65 | 90DEFF241C071D5C00A61971 /* TZPopInputView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TZPopInputView.xib; sourceTree = ""; }; 66 | 90E9D97C1C1174420077C92D /* TZDatePickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZDatePickerView.h; sourceTree = ""; }; 67 | 90E9D97D1C1174420077C92D /* TZDatePickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZDatePickerView.m; sourceTree = ""; }; 68 | 90E9D97E1C1174420077C92D /* TZDatePickerView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TZDatePickerView.xib; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | 90DEFEE11C071CFC00A61971 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 90DEFEFA1C071CFD00A61971 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | 90DEFF051C071CFD00A61971 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | 90D7E3A11C16BBAD000997A1 /* TZTimePicker */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 90D7E3A21C16BBAD000997A1 /* TZTimePickerView.h */, 100 | 90D7E3A31C16BBAD000997A1 /* TZTimePickerView.m */, 101 | 90D7E3A41C16BBAD000997A1 /* TZTimePickerView.xib */, 102 | ); 103 | path = TZTimePicker; 104 | sourceTree = ""; 105 | }; 106 | 90DEFEDB1C071CFC00A61971 = { 107 | isa = PBXGroup; 108 | children = ( 109 | 90DEFEE61C071CFC00A61971 /* TZPopInputView */, 110 | 90DEFF001C071CFD00A61971 /* TZPopInputViewTests */, 111 | 90DEFF0B1C071CFD00A61971 /* TZPopInputViewUITests */, 112 | 90DEFEE51C071CFC00A61971 /* Products */, 113 | ); 114 | sourceTree = ""; 115 | }; 116 | 90DEFEE51C071CFC00A61971 /* Products */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 90DEFEE41C071CFC00A61971 /* TZPopInputView.app */, 120 | 90DEFEFD1C071CFD00A61971 /* TZPopInputViewTests.xctest */, 121 | 90DEFF081C071CFD00A61971 /* TZPopInputViewUITests.xctest */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | 90DEFEE61C071CFC00A61971 /* TZPopInputView */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 90D7E3A11C16BBAD000997A1 /* TZTimePicker */, 130 | 90E9D97B1C1174420077C92D /* TZDatePicker */, 131 | 90DEFF211C071D5C00A61971 /* TZPopInputView */, 132 | 90DEFEEA1C071CFC00A61971 /* AppDelegate.h */, 133 | 90DEFEEB1C071CFC00A61971 /* AppDelegate.m */, 134 | 90DEFEED1C071CFC00A61971 /* ViewController.h */, 135 | 90DEFEEE1C071CFC00A61971 /* ViewController.m */, 136 | 90DEFEF01C071CFC00A61971 /* Main.storyboard */, 137 | 90DEFEF31C071CFC00A61971 /* Assets.xcassets */, 138 | 90DEFEF51C071CFC00A61971 /* LaunchScreen.storyboard */, 139 | 90DEFEF81C071CFC00A61971 /* Info.plist */, 140 | 90DEFEE71C071CFC00A61971 /* Supporting Files */, 141 | ); 142 | path = TZPopInputView; 143 | sourceTree = ""; 144 | }; 145 | 90DEFEE71C071CFC00A61971 /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 90DEFEE81C071CFC00A61971 /* main.m */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | 90DEFF001C071CFD00A61971 /* TZPopInputViewTests */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 90DEFF011C071CFD00A61971 /* TZPopInputViewTests.m */, 157 | 90DEFF031C071CFD00A61971 /* Info.plist */, 158 | ); 159 | path = TZPopInputViewTests; 160 | sourceTree = ""; 161 | }; 162 | 90DEFF0B1C071CFD00A61971 /* TZPopInputViewUITests */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 90DEFF0C1C071CFD00A61971 /* TZPopInputViewUITests.m */, 166 | 90DEFF0E1C071CFD00A61971 /* Info.plist */, 167 | ); 168 | path = TZPopInputViewUITests; 169 | sourceTree = ""; 170 | }; 171 | 90DEFF211C071D5C00A61971 /* TZPopInputView */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 90DEFF221C071D5C00A61971 /* TZPopInputView.h */, 175 | 90DEFF231C071D5C00A61971 /* TZPopInputView.m */, 176 | 90DEFF241C071D5C00A61971 /* TZPopInputView.xib */, 177 | ); 178 | path = TZPopInputView; 179 | sourceTree = ""; 180 | }; 181 | 90E9D97B1C1174420077C92D /* TZDatePicker */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 90E9D97C1C1174420077C92D /* TZDatePickerView.h */, 185 | 90E9D97D1C1174420077C92D /* TZDatePickerView.m */, 186 | 90E9D97E1C1174420077C92D /* TZDatePickerView.xib */, 187 | ); 188 | path = TZDatePicker; 189 | sourceTree = ""; 190 | }; 191 | /* End PBXGroup section */ 192 | 193 | /* Begin PBXNativeTarget section */ 194 | 90DEFEE31C071CFC00A61971 /* TZPopInputView */ = { 195 | isa = PBXNativeTarget; 196 | buildConfigurationList = 90DEFF111C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputView" */; 197 | buildPhases = ( 198 | 90DEFEE01C071CFC00A61971 /* Sources */, 199 | 90DEFEE11C071CFC00A61971 /* Frameworks */, 200 | 90DEFEE21C071CFC00A61971 /* Resources */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | ); 206 | name = TZPopInputView; 207 | productName = TZPopInputView; 208 | productReference = 90DEFEE41C071CFC00A61971 /* TZPopInputView.app */; 209 | productType = "com.apple.product-type.application"; 210 | }; 211 | 90DEFEFC1C071CFD00A61971 /* TZPopInputViewTests */ = { 212 | isa = PBXNativeTarget; 213 | buildConfigurationList = 90DEFF141C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputViewTests" */; 214 | buildPhases = ( 215 | 90DEFEF91C071CFD00A61971 /* Sources */, 216 | 90DEFEFA1C071CFD00A61971 /* Frameworks */, 217 | 90DEFEFB1C071CFD00A61971 /* Resources */, 218 | ); 219 | buildRules = ( 220 | ); 221 | dependencies = ( 222 | 90DEFEFF1C071CFD00A61971 /* PBXTargetDependency */, 223 | ); 224 | name = TZPopInputViewTests; 225 | productName = TZPopInputViewTests; 226 | productReference = 90DEFEFD1C071CFD00A61971 /* TZPopInputViewTests.xctest */; 227 | productType = "com.apple.product-type.bundle.unit-test"; 228 | }; 229 | 90DEFF071C071CFD00A61971 /* TZPopInputViewUITests */ = { 230 | isa = PBXNativeTarget; 231 | buildConfigurationList = 90DEFF171C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputViewUITests" */; 232 | buildPhases = ( 233 | 90DEFF041C071CFD00A61971 /* Sources */, 234 | 90DEFF051C071CFD00A61971 /* Frameworks */, 235 | 90DEFF061C071CFD00A61971 /* Resources */, 236 | ); 237 | buildRules = ( 238 | ); 239 | dependencies = ( 240 | 90DEFF0A1C071CFD00A61971 /* PBXTargetDependency */, 241 | ); 242 | name = TZPopInputViewUITests; 243 | productName = TZPopInputViewUITests; 244 | productReference = 90DEFF081C071CFD00A61971 /* TZPopInputViewUITests.xctest */; 245 | productType = "com.apple.product-type.bundle.ui-testing"; 246 | }; 247 | /* End PBXNativeTarget section */ 248 | 249 | /* Begin PBXProject section */ 250 | 90DEFEDC1C071CFC00A61971 /* Project object */ = { 251 | isa = PBXProject; 252 | attributes = { 253 | LastUpgradeCheck = 0710; 254 | ORGANIZATIONNAME = "谭真"; 255 | TargetAttributes = { 256 | 90DEFEE31C071CFC00A61971 = { 257 | CreatedOnToolsVersion = 7.1; 258 | }; 259 | 90DEFEFC1C071CFD00A61971 = { 260 | CreatedOnToolsVersion = 7.1; 261 | TestTargetID = 90DEFEE31C071CFC00A61971; 262 | }; 263 | 90DEFF071C071CFD00A61971 = { 264 | CreatedOnToolsVersion = 7.1; 265 | TestTargetID = 90DEFEE31C071CFC00A61971; 266 | }; 267 | }; 268 | }; 269 | buildConfigurationList = 90DEFEDF1C071CFC00A61971 /* Build configuration list for PBXProject "TZPopInputView" */; 270 | compatibilityVersion = "Xcode 3.2"; 271 | developmentRegion = English; 272 | hasScannedForEncodings = 0; 273 | knownRegions = ( 274 | en, 275 | Base, 276 | ); 277 | mainGroup = 90DEFEDB1C071CFC00A61971; 278 | productRefGroup = 90DEFEE51C071CFC00A61971 /* Products */; 279 | projectDirPath = ""; 280 | projectRoot = ""; 281 | targets = ( 282 | 90DEFEE31C071CFC00A61971 /* TZPopInputView */, 283 | 90DEFEFC1C071CFD00A61971 /* TZPopInputViewTests */, 284 | 90DEFF071C071CFD00A61971 /* TZPopInputViewUITests */, 285 | ); 286 | }; 287 | /* End PBXProject section */ 288 | 289 | /* Begin PBXResourcesBuildPhase section */ 290 | 90DEFEE21C071CFC00A61971 /* Resources */ = { 291 | isa = PBXResourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 90DEFF261C071D5C00A61971 /* TZPopInputView.xib in Resources */, 295 | 90DEFEF71C071CFC00A61971 /* LaunchScreen.storyboard in Resources */, 296 | 90DEFEF41C071CFC00A61971 /* Assets.xcassets in Resources */, 297 | 90DEFEF21C071CFC00A61971 /* Main.storyboard in Resources */, 298 | 90D7E3A61C16BBAD000997A1 /* TZTimePickerView.xib in Resources */, 299 | 90E9D9801C1174420077C92D /* TZDatePickerView.xib in Resources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | 90DEFEFB1C071CFD00A61971 /* Resources */ = { 304 | isa = PBXResourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | 90DEFF061C071CFD00A61971 /* Resources */ = { 311 | isa = PBXResourcesBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | /* End PBXResourcesBuildPhase section */ 318 | 319 | /* Begin PBXSourcesBuildPhase section */ 320 | 90DEFEE01C071CFC00A61971 /* Sources */ = { 321 | isa = PBXSourcesBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | 90D7E3A51C16BBAD000997A1 /* TZTimePickerView.m in Sources */, 325 | 90E9D97F1C1174420077C92D /* TZDatePickerView.m in Sources */, 326 | 90DEFF251C071D5C00A61971 /* TZPopInputView.m in Sources */, 327 | 90DEFEEF1C071CFC00A61971 /* ViewController.m in Sources */, 328 | 90DEFEEC1C071CFC00A61971 /* AppDelegate.m in Sources */, 329 | 90DEFEE91C071CFC00A61971 /* main.m in Sources */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | 90DEFEF91C071CFD00A61971 /* Sources */ = { 334 | isa = PBXSourcesBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | 90DEFF021C071CFD00A61971 /* TZPopInputViewTests.m in Sources */, 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | 90DEFF041C071CFD00A61971 /* Sources */ = { 342 | isa = PBXSourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | 90DEFF0D1C071CFD00A61971 /* TZPopInputViewUITests.m in Sources */, 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | }; 349 | /* End PBXSourcesBuildPhase section */ 350 | 351 | /* Begin PBXTargetDependency section */ 352 | 90DEFEFF1C071CFD00A61971 /* PBXTargetDependency */ = { 353 | isa = PBXTargetDependency; 354 | target = 90DEFEE31C071CFC00A61971 /* TZPopInputView */; 355 | targetProxy = 90DEFEFE1C071CFD00A61971 /* PBXContainerItemProxy */; 356 | }; 357 | 90DEFF0A1C071CFD00A61971 /* PBXTargetDependency */ = { 358 | isa = PBXTargetDependency; 359 | target = 90DEFEE31C071CFC00A61971 /* TZPopInputView */; 360 | targetProxy = 90DEFF091C071CFD00A61971 /* PBXContainerItemProxy */; 361 | }; 362 | /* End PBXTargetDependency section */ 363 | 364 | /* Begin PBXVariantGroup section */ 365 | 90DEFEF01C071CFC00A61971 /* Main.storyboard */ = { 366 | isa = PBXVariantGroup; 367 | children = ( 368 | 90DEFEF11C071CFC00A61971 /* Base */, 369 | ); 370 | name = Main.storyboard; 371 | sourceTree = ""; 372 | }; 373 | 90DEFEF51C071CFC00A61971 /* LaunchScreen.storyboard */ = { 374 | isa = PBXVariantGroup; 375 | children = ( 376 | 90DEFEF61C071CFC00A61971 /* Base */, 377 | ); 378 | name = LaunchScreen.storyboard; 379 | sourceTree = ""; 380 | }; 381 | /* End PBXVariantGroup section */ 382 | 383 | /* Begin XCBuildConfiguration section */ 384 | 90DEFF0F1C071CFD00A61971 /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | ALWAYS_SEARCH_USER_PATHS = NO; 388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 389 | CLANG_CXX_LIBRARY = "libc++"; 390 | CLANG_ENABLE_MODULES = YES; 391 | CLANG_ENABLE_OBJC_ARC = YES; 392 | CLANG_WARN_BOOL_CONVERSION = YES; 393 | CLANG_WARN_CONSTANT_CONVERSION = YES; 394 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 395 | CLANG_WARN_EMPTY_BODY = YES; 396 | CLANG_WARN_ENUM_CONVERSION = YES; 397 | CLANG_WARN_INT_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN_UNREACHABLE_CODE = YES; 400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 401 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 402 | COPY_PHASE_STRIP = NO; 403 | DEBUG_INFORMATION_FORMAT = dwarf; 404 | ENABLE_STRICT_OBJC_MSGSEND = YES; 405 | ENABLE_TESTABILITY = YES; 406 | GCC_C_LANGUAGE_STANDARD = gnu99; 407 | GCC_DYNAMIC_NO_PIC = NO; 408 | GCC_NO_COMMON_BLOCKS = YES; 409 | GCC_OPTIMIZATION_LEVEL = 0; 410 | GCC_PREPROCESSOR_DEFINITIONS = ( 411 | "DEBUG=1", 412 | "$(inherited)", 413 | ); 414 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 415 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 416 | GCC_WARN_UNDECLARED_SELECTOR = YES; 417 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 418 | GCC_WARN_UNUSED_FUNCTION = YES; 419 | GCC_WARN_UNUSED_VARIABLE = YES; 420 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 421 | MTL_ENABLE_DEBUG_INFO = YES; 422 | ONLY_ACTIVE_ARCH = YES; 423 | SDKROOT = iphoneos; 424 | }; 425 | name = Debug; 426 | }; 427 | 90DEFF101C071CFD00A61971 /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 432 | CLANG_CXX_LIBRARY = "libc++"; 433 | CLANG_ENABLE_MODULES = YES; 434 | CLANG_ENABLE_OBJC_ARC = YES; 435 | CLANG_WARN_BOOL_CONVERSION = YES; 436 | CLANG_WARN_CONSTANT_CONVERSION = YES; 437 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 438 | CLANG_WARN_EMPTY_BODY = YES; 439 | CLANG_WARN_ENUM_CONVERSION = YES; 440 | CLANG_WARN_INT_CONVERSION = YES; 441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 442 | CLANG_WARN_UNREACHABLE_CODE = YES; 443 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 445 | COPY_PHASE_STRIP = NO; 446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 447 | ENABLE_NS_ASSERTIONS = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | GCC_C_LANGUAGE_STANDARD = gnu99; 450 | GCC_NO_COMMON_BLOCKS = YES; 451 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 452 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 453 | GCC_WARN_UNDECLARED_SELECTOR = YES; 454 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 455 | GCC_WARN_UNUSED_FUNCTION = YES; 456 | GCC_WARN_UNUSED_VARIABLE = YES; 457 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 458 | MTL_ENABLE_DEBUG_INFO = NO; 459 | SDKROOT = iphoneos; 460 | VALIDATE_PRODUCT = YES; 461 | }; 462 | name = Release; 463 | }; 464 | 90DEFF121C071CFD00A61971 /* Debug */ = { 465 | isa = XCBuildConfiguration; 466 | buildSettings = { 467 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 468 | INFOPLIST_FILE = TZPopInputView/Info.plist; 469 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 470 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputView; 471 | PRODUCT_NAME = "$(TARGET_NAME)"; 472 | }; 473 | name = Debug; 474 | }; 475 | 90DEFF131C071CFD00A61971 /* Release */ = { 476 | isa = XCBuildConfiguration; 477 | buildSettings = { 478 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 479 | INFOPLIST_FILE = TZPopInputView/Info.plist; 480 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 481 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputView; 482 | PRODUCT_NAME = "$(TARGET_NAME)"; 483 | }; 484 | name = Release; 485 | }; 486 | 90DEFF151C071CFD00A61971 /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | BUNDLE_LOADER = "$(TEST_HOST)"; 490 | INFOPLIST_FILE = TZPopInputViewTests/Info.plist; 491 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 492 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputViewTests; 493 | PRODUCT_NAME = "$(TARGET_NAME)"; 494 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TZPopInputView.app/TZPopInputView"; 495 | }; 496 | name = Debug; 497 | }; 498 | 90DEFF161C071CFD00A61971 /* Release */ = { 499 | isa = XCBuildConfiguration; 500 | buildSettings = { 501 | BUNDLE_LOADER = "$(TEST_HOST)"; 502 | INFOPLIST_FILE = TZPopInputViewTests/Info.plist; 503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 504 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputViewTests; 505 | PRODUCT_NAME = "$(TARGET_NAME)"; 506 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TZPopInputView.app/TZPopInputView"; 507 | }; 508 | name = Release; 509 | }; 510 | 90DEFF181C071CFD00A61971 /* Debug */ = { 511 | isa = XCBuildConfiguration; 512 | buildSettings = { 513 | INFOPLIST_FILE = TZPopInputViewUITests/Info.plist; 514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 515 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputViewUITests; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | TEST_TARGET_NAME = TZPopInputView; 518 | USES_XCTRUNNER = YES; 519 | }; 520 | name = Debug; 521 | }; 522 | 90DEFF191C071CFD00A61971 /* Release */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | INFOPLIST_FILE = TZPopInputViewUITests/Info.plist; 526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 527 | PRODUCT_BUNDLE_IDENTIFIER = tanzhen.TZPopInputViewUITests; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | TEST_TARGET_NAME = TZPopInputView; 530 | USES_XCTRUNNER = YES; 531 | }; 532 | name = Release; 533 | }; 534 | /* End XCBuildConfiguration section */ 535 | 536 | /* Begin XCConfigurationList section */ 537 | 90DEFEDF1C071CFC00A61971 /* Build configuration list for PBXProject "TZPopInputView" */ = { 538 | isa = XCConfigurationList; 539 | buildConfigurations = ( 540 | 90DEFF0F1C071CFD00A61971 /* Debug */, 541 | 90DEFF101C071CFD00A61971 /* Release */, 542 | ); 543 | defaultConfigurationIsVisible = 0; 544 | defaultConfigurationName = Release; 545 | }; 546 | 90DEFF111C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputView" */ = { 547 | isa = XCConfigurationList; 548 | buildConfigurations = ( 549 | 90DEFF121C071CFD00A61971 /* Debug */, 550 | 90DEFF131C071CFD00A61971 /* Release */, 551 | ); 552 | defaultConfigurationIsVisible = 0; 553 | defaultConfigurationName = Release; 554 | }; 555 | 90DEFF141C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputViewTests" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | 90DEFF151C071CFD00A61971 /* Debug */, 559 | 90DEFF161C071CFD00A61971 /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | 90DEFF171C071CFD00A61971 /* Build configuration list for PBXNativeTarget "TZPopInputViewUITests" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | 90DEFF181C071CFD00A61971 /* Debug */, 568 | 90DEFF191C071CFD00A61971 /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | /* End XCConfigurationList section */ 574 | }; 575 | rootObject = 90DEFEDC1C071CFC00A61971 /* Project object */; 576 | } 577 | -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/project.xcworkspace/xcuserdata/tanzhen.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView.xcodeproj/project.xcworkspace/xcuserdata/tanzhen.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/xcuserdata/tanzhen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/xcuserdata/tanzhen.xcuserdatad/xcschemes/TZPopInputView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /TZPopInputView.xcodeproj/xcuserdata/tanzhen.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TZPopInputView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 90DEFEE31C071CFC00A61971 16 | 17 | primary 18 | 19 | 20 | 90DEFEFC1C071CFD00A61971 21 | 22 | primary 23 | 24 | 25 | 90DEFF071C071CFD00A61971 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /TZPopInputView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TZPopInputView 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /TZPopInputView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TZPopInputView 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_left.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "def_left.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "def_left@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "def_left@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left@2x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_left.imageset/def_left@3x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_right.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "def_right.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "def_right@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "def_right@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right@2x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/disabled_right.imageset/def_right@3x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_left.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "sel_right.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "sel_right@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "sel_right@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right@2x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_left.imageset/sel_right@3x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_right.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "sel_left.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "sel_left@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "sel_left@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left@2x.png -------------------------------------------------------------------------------- /TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/banchichen/SomeGoodCustomView/680ba1a98db5f0c298244769b7f2e28ee1061d32/TZPopInputView/Assets.xcassets/enable_right.imageset/sel_left@3x.png -------------------------------------------------------------------------------- /TZPopInputView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /TZPopInputView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TZPopInputView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /TZPopInputView/TZDatePicker/TZDatePickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TZDatePickerView.h 3 | // ZM_MiniSupply 4 | // 5 | // Created by 谭真 on 15/11/21. 6 | // Copyright © 2015年 上海千叶网络科技有限公司. All rights reserved. 7 | // 时间选择器(开始时间和结束时间) 8 | 9 | #import 10 | 11 | @interface TZDatePickerView : UIView 12 | 13 | /** 显示 */ 14 | - (void)show; 15 | /** 隐藏 */ 16 | - (void)hide; 17 | 18 | /** 返回用户选择的开始时间和结束时间 */ 19 | @property (nonatomic, copy) void(^gotoSrceenOrderBlock)(NSString *,NSString *); 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /TZPopInputView/TZDatePicker/TZDatePickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TZDatePickerView.m 3 | // ZM_MiniSupply 4 | // 5 | // Created by 谭真 on 15/11/21. 6 | // Copyright © 2015年 上海千叶网络科技有限公司. All rights reserved. 7 | // 时间选择器(开始时间和结束时间) 8 | 9 | /* 写该控件时的应用场景是:用户选择起始时间去筛选订单,故一些命名与筛选订单有关 */ 10 | 11 | #import "TZDatePickerView.h" 12 | 13 | #define mScreenWidth ([UIScreen mainScreen].bounds.size.width) 14 | #define mScreenHeight ([UIScreen mainScreen].bounds.size.height) 15 | #define mBlueColor [UIColor colorWithRed:50.0/255.0 green:162.0/255.0 blue:248.0/255.0 alpha:1.0] 16 | #define mGrayColor [UIColor colorWithRed:165/255.0 green:165/255.0 blue:165/255.0 alpha:1.0] 17 | 18 | @interface TZDatePickerView () 19 | @property (nonatomic, strong) UIView *bgView; 20 | 21 | /** 时间按钮和文本 */ 22 | @property (weak, nonatomic) IBOutlet UIButton *beginDateBtn; 23 | @property (weak, nonatomic) IBOutlet UILabel *beginDateLable; 24 | @property (weak, nonatomic) IBOutlet UIButton *endDateBtn; 25 | @property (weak, nonatomic) IBOutlet UILabel *endDateLable; 26 | 27 | /** 提示lable */ 28 | @property (weak, nonatomic) IBOutlet UILabel *tipLable; 29 | /** datePicker */ 30 | @property (weak, nonatomic) IBOutlet UIDatePicker *datePicker; 31 | /** 时间格式转换器 */ 32 | @property (nonatomic, strong) NSDateFormatter *formatter; 33 | /** 去筛选订单按钮 */ 34 | @property (weak, nonatomic) IBOutlet UIButton *okBtnToSrceenOrder; 35 | 36 | @end 37 | 38 | @implementation TZDatePickerView 39 | 40 | #pragma mark 配置视图 41 | 42 | - (instancetype)init { 43 | self = [super init]; 44 | if (self) { 45 | self = [[[NSBundle mainBundle] loadNibNamed:@"TZDatePickerView" owner:self options:nil] lastObject]; 46 | // 初始化设置 47 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 48 | self.frame = CGRectMake(0, mScreenHeight, mScreenWidth, 350); 49 | [window addSubview:self.bgView]; 50 | [window addSubview:self]; 51 | } 52 | return self; 53 | } 54 | 55 | - (UIView *)bgView { 56 | if (_bgView == nil) { 57 | _bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 58 | _bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3]; 59 | _bgView.hidden = YES; 60 | 61 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; 62 | [_bgView addGestureRecognizer:tap]; 63 | } 64 | return _bgView; 65 | } 66 | 67 | - (void)awakeFromNib { 68 | // 开始时间和结束时间按钮的UI 69 | self.beginDateBtn.layer.cornerRadius = self.beginDateBtn.frame.size.height * 0.5; 70 | self.beginDateBtn.clipsToBounds = YES; 71 | self.endDateBtn.layer.cornerRadius = self.endDateBtn.frame.size.height * 0.5; 72 | self.endDateBtn.clipsToBounds = YES; 73 | 74 | [self.beginDateBtn setBackgroundImage:[self createImageWithColor:[UIColor whiteColor]] forState:UIControlStateNormal]; 75 | [self.endDateBtn setBackgroundImage:[self createImageWithColor:[UIColor whiteColor]] forState:UIControlStateNormal]; 76 | [self.beginDateBtn setBackgroundImage:[self createImageWithColor:mBlueColor] forState:UIControlStateSelected]; 77 | [self.endDateBtn setBackgroundImage:[self createImageWithColor:mBlueColor] forState:UIControlStateSelected]; 78 | 79 | self.beginDateBtn.layer.borderWidth = 1; 80 | self.beginDateBtn.layer.borderColor = mBlueColor.CGColor; 81 | self.endDateBtn.layer.borderWidth = 1; 82 | self.endDateBtn.layer.borderColor = mBlueColor.CGColor; 83 | 84 | // 设置时间格式转换器 85 | self.formatter = [[NSDateFormatter alloc] init]; 86 | self.formatter.dateFormat = @"yyyy-MM-dd"; 87 | 88 | // 选中开始时间按钮 89 | [self beginDateBtnClick:self.beginDateBtn]; 90 | 91 | // 配置DatePicker 92 | self.datePicker.maximumDate = [NSDate date]; 93 | CGRect newFrame = self.datePicker.frame; 94 | newFrame.size.width = 375; 95 | self.datePicker.frame = newFrame; 96 | 97 | // 确定筛选按钮 98 | self.okBtnToSrceenOrder.backgroundColor = mBlueColor; 99 | [self.okBtnToSrceenOrder setBackgroundImage:[self createImageWithColor:[UIColor lightGrayColor]] forState:UIControlStateDisabled]; 100 | self.okBtnToSrceenOrder.titleLabel.font = [UIFont systemFontOfSize:15]; 101 | self.okBtnToSrceenOrder.enabled = NO; 102 | self.okBtnToSrceenOrder.layer.cornerRadius = 3; 103 | self.okBtnToSrceenOrder.clipsToBounds = YES; 104 | } 105 | 106 | /** 选择开始时间 */ 107 | - (IBAction)beginDateBtnClick:(id)sender { 108 | self.beginDateBtn.selected = YES; 109 | self.endDateBtn.selected = NO; 110 | 111 | self.tipLable.text = @"选择开始时间"; 112 | [self.beginDateBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 113 | [self.endDateBtn setTitleColor:mBlueColor forState:UIControlStateNormal]; 114 | 115 | if (![self.beginDateLable.text isEqualToString:@"请选择"]) { 116 | [self.datePicker setDate:[self.formatter dateFromString:self.beginDateLable.text] animated:YES]; 117 | } 118 | 119 | [self refreshOkBtnEnableStatus]; 120 | } 121 | 122 | /** 选择结束时间 */ 123 | - (IBAction)endDateBtnClick:(UIButton *)sender { 124 | self.endDateBtn.selected = YES; 125 | self.beginDateBtn.selected = NO; 126 | 127 | self.tipLable.text = @"选择结束时间"; 128 | [self.endDateBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 129 | [self.beginDateBtn setTitleColor:mBlueColor forState:UIControlStateNormal]; 130 | 131 | if (![self.endDateLable.text isEqualToString:@"请选择"]) { 132 | [self.datePicker setDate:[self.formatter dateFromString:self.endDateLable.text] animated:YES]; 133 | } 134 | 135 | [self refreshOkBtnEnableStatus]; 136 | } 137 | 138 | /** 确定选择该时间 */ 139 | - (IBAction)okButtonClick:(UIButton *)sender { 140 | if (self.beginDateBtn.selected) { 141 | self.beginDateLable.text = [self.formatter stringFromDate:self.datePicker.date]; 142 | // 选择了开始时间,去选择结束时间 143 | [self endDateBtnClick:self.endDateBtn]; 144 | } else { 145 | self.endDateLable.text = [self.formatter stringFromDate:self.datePicker.date]; 146 | // 选择了结束时间,去选择开始时间 147 | [self beginDateBtnClick:self.beginDateBtn]; 148 | } 149 | 150 | [self refreshOkBtnEnableStatus]; 151 | } 152 | 153 | /** 去筛选订单 */ 154 | - (IBAction)gotoSrceenOrderClick:(id)sender { 155 | [self hide]; 156 | if (self.gotoSrceenOrderBlock) { 157 | self.gotoSrceenOrderBlock(self.beginDateLable.text,self.endDateLable.text); 158 | } 159 | } 160 | 161 | #pragma mark 功能方法 162 | 163 | /** 显示 */ 164 | - (void)show { 165 | // 默认让先选择开始时间 166 | [self beginDateBtnClick:self.beginDateBtn]; 167 | 168 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 169 | self.bgView.hidden = NO; 170 | 171 | CGRect newFrame = self.frame; 172 | newFrame.origin.y = mScreenHeight - self.frame.size.height; 173 | self.frame = newFrame; 174 | } completion:nil]; 175 | } 176 | 177 | /** 隐藏 */ 178 | - (void)hide { 179 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.5 options:0 animations:^{ 180 | self.bgView.hidden = YES; 181 | 182 | CGRect newFrame = self.frame; 183 | newFrame.origin.y = mScreenHeight; 184 | self.frame = newFrame; 185 | } completion:nil]; 186 | } 187 | 188 | #pragma mark 私有方法 189 | 190 | /** 检查确定按钮是否可被点击*/ 191 | - (void)refreshOkBtnEnableStatus { 192 | 193 | self.okBtnToSrceenOrder.enabled = (![self.beginDateLable.text isEqualToString:@"请选择"] && ![self.endDateLable.text isEqualToString:@"请选择"]); 194 | 195 | // 检查数据 196 | if (self.okBtnToSrceenOrder.enabled) { 197 | NSString *beginDateStr = [self.beginDateLable.text stringByReplacingOccurrencesOfString:@"-" withString:@""]; 198 | NSString *endDateStr = [self.endDateLable.text stringByReplacingOccurrencesOfString:@"-" withString:@""]; 199 | 200 | if (beginDateStr.integerValue > endDateStr.integerValue) { 201 | [self.okBtnToSrceenOrder setTitle:@"开始时间须小于结束时间" forState:UIControlStateDisabled]; 202 | self.okBtnToSrceenOrder.enabled = NO; 203 | } else { 204 | [self.okBtnToSrceenOrder setTitle:@"确定" forState:UIControlStateDisabled]; 205 | } 206 | } 207 | } 208 | 209 | /** 用颜色生成一张图片 */ 210 | - (UIImage *)createImageWithColor:(UIColor *)color { 211 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 212 | UIGraphicsBeginImageContext(rect.size); 213 | CGContextRef context = UIGraphicsGetCurrentContext(); 214 | CGContextSetFillColorWithColor(context, [color CGColor]); 215 | CGContextFillRect(context, rect); 216 | 217 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 218 | UIGraphicsEndImageContext(); 219 | return theImage; 220 | } 221 | 222 | @end 223 | -------------------------------------------------------------------------------- /TZPopInputView/TZDatePicker/TZDatePickerView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ZhaimiMedium- 11 | ZhaimiMedium- 12 | ZhaimiMedium- 13 | ZhaimiMedium- 14 | ZhaimiMedium- 15 | ZhaimiMedium- 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 70 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 114 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /TZPopInputView/TZPopInputView/TZPopInputView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TZPopInputView.h 3 | // ZM_MiniSupply 4 | // 5 | // Created by 谭真 on 15/11/19. 6 | // Copyright © 2015年 上海千叶网络科技有限公司. All rights reserved. 7 | // 自定义输入框 8 | 9 | #import 10 | 11 | @interface TZPopInputView : UIView 12 | 13 | /** 显示 */ 14 | - (void)show; 15 | /** 隐藏 */ 16 | - (void)hide; 17 | 18 | /** 三个textFiled 放在.h里,方便从外界更改键盘样式 */ 19 | @property (weak, nonatomic) IBOutlet UITextField *textFiled1; 20 | @property (weak, nonatomic) IBOutlet UITextField *textFiled2; 21 | @property (weak, nonatomic) IBOutlet UITextField *textFiled3; 22 | /** 确认按钮 也放在.h里,方便从外界做特殊的数据判读处理,限制用户的输入 */ 23 | @property (weak, nonatomic) IBOutlet UIButton *okButton; 24 | 25 | /** 标题文本 */ 26 | @property (weak, nonatomic) IBOutlet UILabel *titleLable; 27 | /** 输入框的提示文本 输入框的个数,由items数组的个数动态确定 */ 28 | @property (nonatomic, copy) NSArray *items; 29 | /** 输入框的预设文本 */ 30 | @property (nonatomic, copy) NSArray *textFieldItems; 31 | /** 输入框的占位文本 */ 32 | @property (nonatomic, copy) NSArray *placeholderItems; 33 | 34 | /** 确认按钮点击的block */ 35 | @property (nonatomic, copy) void(^okButtonClickBolck)(NSMutableArray *items); 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /TZPopInputView/TZPopInputView/TZPopInputView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TZPopInputView.m 3 | // ZM_MiniSupply 4 | // 5 | // Created by 谭真 on 15/11/19. 6 | // Copyright © 2015年 上海千叶网络科技有限公司. All rights reserved. 7 | // 自定义输入框 8 | 9 | #import "TZPopInputView.h" 10 | 11 | #define mScreenWidth ([UIScreen mainScreen].bounds.size.width) 12 | #define mScreenHeight ([UIScreen mainScreen].bounds.size.height) 13 | #define mBlueColor [UIColor colorWithRed:50.0/255.0 green:162.0/255.0 blue:248.0/255.0 alpha:1.0] 14 | #define mGrayColor [UIColor colorWithRed:165/255.0 green:165/255.0 blue:165/255.0 alpha:1.0] 15 | 16 | @interface TZPopInputView () 17 | @property (nonatomic, strong) UIView *bgView; 18 | 19 | /** 标题背景View */ 20 | @property (weak, nonatomic) IBOutlet UIView *titleView; 21 | 22 | /** 第一个输入View */ 23 | @property (weak, nonatomic) IBOutlet UIView *view1; 24 | @property (weak, nonatomic) IBOutlet UILabel *lable1; 25 | /** 第二个输入View */ 26 | @property (weak, nonatomic) IBOutlet UIView *view2; 27 | @property (weak, nonatomic) IBOutlet UILabel *lable2; 28 | /** 第三个输入View */ 29 | @property (weak, nonatomic) IBOutlet UIView *view3; 30 | @property (weak, nonatomic) IBOutlet UILabel *lable3; 31 | 32 | @end 33 | 34 | @implementation TZPopInputView 35 | 36 | #pragma mark 配置视图 37 | 38 | - (instancetype)init { 39 | self = [super init]; 40 | if (self) { 41 | self = [[[NSBundle mainBundle] loadNibNamed:@"TZPopInputView" owner:self options:nil] lastObject]; 42 | // 初始化设置 43 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 44 | self.frame = CGRectMake(20 + mScreenWidth, 100, mScreenWidth - 40, 320); 45 | [window addSubview:self.bgView]; 46 | [window addSubview:self]; 47 | 48 | // 监听键盘改变的通知 49 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; 50 | // 监听文本框输入改变的通知 51 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkTextFieldText) name:UITextFieldTextDidChangeNotification object:nil]; 52 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkTextFieldText) name:UITextFieldTextDidBeginEditingNotification object:nil]; 53 | } 54 | return self; 55 | } 56 | 57 | - (void)awakeFromNib { 58 | // 一次性的设置 59 | self.titleView.backgroundColor = mBlueColor; 60 | [self.okButton setBackgroundColor:mBlueColor]; 61 | 62 | self.okButton.layer.cornerRadius = 2; 63 | self.okButton.clipsToBounds = YES; 64 | 65 | self.layer.cornerRadius = 4; 66 | self.clipsToBounds = YES; 67 | 68 | self.textFiled1.delegate = self; 69 | self.textFiled2.delegate = self; 70 | self.textFiled3.delegate = self; 71 | 72 | [self.okButton setBackgroundImage:[self createImageWithColor:mGrayColor] forState:UIControlStateDisabled]; 73 | self.okButton.enabled = NO; 74 | } 75 | 76 | - (UIView *)bgView { 77 | if (_bgView == nil) { 78 | _bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 79 | _bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3]; 80 | _bgView.hidden = YES; 81 | 82 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; 83 | [_bgView addGestureRecognizer:tap]; 84 | } 85 | return _bgView; 86 | } 87 | 88 | /** 设置三个提示lable的值 */ 89 | - (void)setItems:(NSArray *)items { 90 | _items = items; 91 | if (items.count > 0) { self.lable1.text = items[0]; } 92 | if (items.count > 1) { self.lable2.text = items[1]; } 93 | if (items.count > 2) { self.lable3.text = items[2]; } 94 | 95 | self.view2.hidden = items.count > 1 ? NO : YES; 96 | self.view3.hidden = items.count > 2 ? NO : YES; 97 | 98 | self.textFiled1.returnKeyType = items.count <= 1 ? UIReturnKeyDone : UIReturnKeyNext; 99 | self.textFiled2.returnKeyType = items.count <= 2 ? UIReturnKeyDone : UIReturnKeyNext; 100 | 101 | // 根据传进来items的个数,来设定frame 102 | CGRect frame = self.frame; 103 | frame.size.height = 110 + 70 * items.count; 104 | self.frame = frame; 105 | 106 | CGPoint center = self.center; 107 | center.y = mScreenHeight / 2; 108 | self.center = center; 109 | } 110 | 111 | /** 三个textFiled的lable */ 112 | - (void)setTextFieldItems:(NSArray *)textFieldItems { 113 | _textFieldItems = textFieldItems; 114 | // 延迟0.2秒,等View显示出来后,再激活键盘 115 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 116 | if (textFieldItems.count > 0) { self.textFiled1.text = textFieldItems[0]; [self.textFiled2 becomeFirstResponder]; } 117 | if (textFieldItems.count > 1) { self.textFiled2.text = textFieldItems[1]; } 118 | if (textFieldItems.count > 2) { self.textFiled3.text = textFieldItems[2]; } 119 | }); 120 | } 121 | 122 | /** 三个textFiled的遮罩文本 */ 123 | - (void)setPlaceholderItems:(NSArray *)placeholderItems { 124 | _placeholderItems = placeholderItems; 125 | 126 | // 防止设置被重置,延迟0.2秒再设置 127 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 128 | if (placeholderItems.count > 0) { self.textFiled1.placeholder = placeholderItems[0]; } 129 | if (placeholderItems.count > 1) { self.textFiled2.placeholder = placeholderItems[1]; } 130 | if (placeholderItems.count > 2) { self.textFiled3.placeholder = placeholderItems[2]; } 131 | }); 132 | } 133 | 134 | #pragma mark 功能方法 135 | 136 | /** 显示 */ 137 | - (void)show { 138 | // 重置输入框 139 | [self resetTextFiled]; 140 | 141 | // 在这里可以 根据标题的不同 加入一些特殊设置。比如:修改支付宝情况下,textFiled1不可编辑。 142 | self.textFiled1.enabled = [self.titleLable.text containsString:@"修改支付宝"] ? NO : YES; 143 | 144 | // 延迟0.2秒,等View显示出来后,再激活键盘 145 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 146 | [self.textFiled1 becomeFirstResponder]; 147 | }); 148 | 149 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 150 | self.bgView.hidden = NO; 151 | self.bgView.userInteractionEnabled = NO; 152 | 153 | CGPoint center = self.center; 154 | center.x = mScreenWidth / 2; 155 | self.center = center; 156 | } completion:^(BOOL finished) { 157 | self.bgView.userInteractionEnabled = YES; 158 | }]; 159 | } 160 | 161 | /** 隐藏 */ 162 | - (void)hide { 163 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.5 options:0 animations:^{ 164 | CGPoint center = self.center; 165 | center.x = mScreenWidth / 2 + mScreenWidth; 166 | self.center = center; 167 | } completion:^(BOOL finished) { 168 | self.bgView.hidden = YES; 169 | }]; 170 | [self endEditing:YES]; 171 | } 172 | 173 | /** 确认修改 */ 174 | - (IBAction)okButtonClick:(UIButton *)sender { 175 | // 检查数据 176 | if ([self checkTextFiledData] == NO) return; 177 | 178 | [self endEditing:YES]; 179 | 180 | // 返回用户输入的数据 181 | if (self.okButtonClickBolck) { 182 | NSMutableArray *arr = [NSMutableArray array]; 183 | if (self.textFiled1.text.length > 0) { [arr addObject:self.textFiled1.text];} 184 | if (self.textFiled2.text.length > 0) { [arr addObject:self.textFiled2.text];} 185 | if (self.textFiled3.text.length > 0) { [arr addObject:self.textFiled3.text];} 186 | 187 | self.okButtonClickBolck(arr); 188 | } 189 | } 190 | 191 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 192 | [self endEditing:YES]; 193 | } 194 | 195 | #pragma mark UITextFieldDelegate 196 | 197 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 198 | if (textField == self.textFiled1) { 199 | if (textField.returnKeyType == UIReturnKeyNext) { 200 | [self.textFiled2 becomeFirstResponder]; 201 | } else { 202 | [self endEditing:YES]; 203 | } 204 | } else if (textField == self.textFiled2) { 205 | if (textField.returnKeyType == UIReturnKeyNext) { 206 | [self.textFiled3 becomeFirstResponder]; 207 | } else { 208 | [self endEditing:YES]; 209 | } 210 | } else { 211 | [self endEditing:YES]; 212 | } 213 | return YES; 214 | } 215 | 216 | - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 217 | [self checkTextFieldText]; 218 | return YES; 219 | } 220 | 221 | #pragma mark 通知方法 222 | 223 | /** 键盘frame即将改变的通知 */ 224 | - (void)keyboardWillChangeFrame:(NSNotification *)notification { 225 | NSDictionary *userInfo = notification.userInfo; 226 | double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 227 | CGRect keyboardF = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 228 | 229 | [UIView animateWithDuration:duration animations:^{ 230 | // 键盘下去了 231 | if (keyboardF.origin.y >= mScreenHeight) { 232 | CGPoint center = self.center; 233 | center.y = mScreenHeight / 2; 234 | self.center = center; 235 | // 键盘上来了 236 | } else { 237 | CGRect frame = self.frame; 238 | frame.origin.y = keyboardF.origin.y - frame.size.height - 2; // 2是输入框和键盘的间隙,自己调.. 239 | self.frame = frame; 240 | } 241 | }]; 242 | } 243 | 244 | /** 监听文本框输入改变/开始输入的通知 刷新确认按钮的enable状态 */ 245 | - (void)checkTextFieldText { 246 | BOOL isOkButtonEnable = YES; 247 | 248 | // 输入文本的最小长度限制 249 | NSInteger length1 = 0,length2 = 0,length3 = 0; 250 | if ([self.titleLable.text containsString:@"修改密码"]) { 251 | length2 = length3 = 7; 252 | } else if ([self.titleLable.text containsString:@"修改手机号"]) { 253 | length1 = 10; 254 | } 255 | 256 | // 确认按钮的enable状态 257 | if (self.textFiled1.text.length <= length1) { isOkButtonEnable = NO; } 258 | if (self.textFiled2.text.length <= length2 && !self.view2.hidden) { isOkButtonEnable = NO; } 259 | if (self.textFiled3.text.length <= length3 && !self.view3.hidden) { isOkButtonEnable = NO; } 260 | 261 | [self.okButton setTitle:@"确认修改" forState:UIControlStateDisabled]; 262 | self.okButton.enabled = isOkButtonEnable; 263 | } 264 | 265 | #pragma mark 私有方法 266 | 267 | /** 重置textFiled */ 268 | - (void)resetTextFiled { 269 | self.textFiled1.text = @""; 270 | self.textFiled2.text = @""; 271 | self.textFiled3.text = @""; 272 | 273 | self.textFiled1.placeholder = @""; 274 | self.textFiled2.placeholder = @""; 275 | self.textFiled3.placeholder = @""; 276 | 277 | self.textFiled1.keyboardType = UIKeyboardTypeDefault; 278 | self.textFiled2.keyboardType = UIKeyboardTypeDefault; 279 | self.textFiled3.keyboardType = UIKeyboardTypeDefault; 280 | } 281 | 282 | /** 检查用户的输入 */ 283 | - (BOOL)checkTextFiledData { 284 | // 根据标题的不同,分别做不同的数据检查 用按钮的title做用户提示 285 | if ([self.titleLable.text isEqualToString:@"修改密码"]) { 286 | // 检测两次密码是否输入正确 287 | if (![self.textFiled2.text isEqualToString:self.textFiled3.text]) { 288 | [self.okButton setTitle:@"两次密码输入不一致" forState:UIControlStateDisabled]; 289 | self.okButton.enabled = NO; 290 | return NO; 291 | } 292 | } else if ([self.titleLable.text isEqualToString:@"修改支付宝账号"]) { 293 | // 检测是否是邮箱或手机号 294 | if (![self isEmail:self.textFiled2.text] && ![self isPhoneNumber:self.textFiled2.text]) { 295 | [self.okButton setTitle:@"支付宝账号格式不正确" forState:UIControlStateDisabled]; 296 | self.okButton.enabled = NO; 297 | return NO; 298 | } 299 | } else if ([self.titleLable.text isEqualToString:@"修改手机号"]) { 300 | // 检测是否是手机号 301 | if (![self isPhoneNumber:self.textFiled1.text]) { 302 | [self.okButton setTitle:@"手机号格式不正确" forState:UIControlStateDisabled]; 303 | self.okButton.enabled = NO; 304 | return NO; 305 | } 306 | } 307 | return YES; 308 | } 309 | 310 | /** 该字符串是否是邮箱 */ 311 | - (BOOL)isEmail:(NSString *)str { 312 | NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; 313 | NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex]; 314 | return [emailTest evaluateWithObject:str]; 315 | } 316 | 317 | /** 该字符串是否是手机号 */ 318 | - (BOOL)isPhoneNumber:(NSString *)str { 319 | NSString * MOBILE = @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$"; 320 | NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$"; 321 | NSString * CU = @"^1(3[0-2]|5[256]|8[156])\\d{8}$"; 322 | NSString * CT = @"^1((33|53|8|7[09])[0-9]|349)\\d{7}$"; 323 | 324 | NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; 325 | NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM]; 326 | NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU]; 327 | NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT]; 328 | BOOL res1 = [regextestmobile evaluateWithObject:str]; 329 | BOOL res2 = [regextestcm evaluateWithObject:str]; 330 | BOOL res3 = [regextestcu evaluateWithObject:str]; 331 | BOOL res4 = [regextestct evaluateWithObject:str]; 332 | 333 | if (res1 || res2 || res3 || res4 ) { 334 | return YES; 335 | } else { 336 | return NO; 337 | } 338 | } 339 | 340 | /** 用颜色生成一张图片 */ 341 | - (UIImage *)createImageWithColor:(UIColor *)color { 342 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 343 | UIGraphicsBeginImageContext(rect.size); 344 | CGContextRef context = UIGraphicsGetCurrentContext(); 345 | CGContextSetFillColorWithColor(context, [color CGColor]); 346 | CGContextFillRect(context, rect); 347 | 348 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 349 | UIGraphicsEndImageContext(); 350 | return theImage; 351 | } 352 | 353 | @end 354 | 355 | -------------------------------------------------------------------------------- /TZPopInputView/TZPopInputView/TZPopInputView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ZhaimiMedium- 10 | ZhaimiMedium- 11 | ZhaimiMedium- 12 | ZhaimiMedium- 13 | ZhaimiMedium- 14 | ZhaimiMedium- 15 | ZhaimiMedium- 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 140 | 141 | 142 | 143 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /TZPopInputView/TZTimePicker/TZTimePickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TZTimePickerView.h 3 | // 4 | // Created by 谭真 on 15/11/4. 5 | // Copyright © 2015年 memberwine. All rights reserved. 6 | // 时间选择器(选择某个时间段) 7 | 8 | #import 9 | 10 | @interface TZTimePickerView : UIView 11 | 12 | /** 显示 */ 13 | - (void)show; 14 | /** 隐藏 */ 15 | - (void)hide; 16 | 17 | /** 选择好时间后的 回调block */ 18 | @property (nonatomic, copy) void (^okBtnClickBlock)(NSString *,NSString *); 19 | /** 所有天数里 时间段是否可预约的大数组 */ 20 | @property (nonatomic, copy) NSMutableArray *allDaysArr; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TZPopInputView/TZTimePicker/TZTimePickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TZTimePickerView.m 3 | // 4 | // Created by 谭真 on 15/11/4. 5 | // Copyright © 2015年 memberwine. All rights reserved. 6 | // 时间选择器(选择某个时间段) 7 | 8 | #import "TZTimePickerView.h" 9 | 10 | @interface TZTimePickerView () 11 | 12 | #define mScreenWidth ([UIScreen mainScreen].bounds.size.width) 13 | #define mScreenHeight ([UIScreen mainScreen].bounds.size.height) 14 | #define mTitleColorDisabled [UIColor colorWithRed:181/255.0 green:181/255.0 blue:181/255.0 alpha:1.0] 15 | #define mBgColorDisabled [UIColor colorWithRed:244/255.0 green:244/255.0 blue:244/255.0 alpha:1.0] 16 | 17 | /** 背景cover */ 18 | @property (nonatomic, strong) UIView *bgView; 19 | /** 上部工具bar */ 20 | @property (weak, nonatomic) IBOutlet UIButton *lastDayBtn; 21 | @property (weak, nonatomic) IBOutlet UIButton *nextDayBtn; 22 | @property (weak, nonatomic) IBOutlet UILabel *titleLable; 23 | /** 时间格子button */ 24 | @property (weak, nonatomic) IBOutlet UIButton *btn1; 25 | @property (weak, nonatomic) IBOutlet UIButton *btn2; 26 | @property (weak, nonatomic) IBOutlet UIButton *btn3; 27 | @property (weak, nonatomic) IBOutlet UIButton *btn4; 28 | @property (weak, nonatomic) IBOutlet UIButton *btn5; 29 | @property (weak, nonatomic) IBOutlet UIButton *btn6; 30 | @property (weak, nonatomic) IBOutlet UIButton *btn7; 31 | @property (weak, nonatomic) IBOutlet UIButton *btn8; 32 | @property (weak, nonatomic) IBOutlet UIButton *btn9; 33 | @property (weak, nonatomic) IBOutlet UIButton *btn10; 34 | @property (weak, nonatomic) IBOutlet UIButton *btn11; 35 | @property (weak, nonatomic) IBOutlet UIButton *btn12; 36 | @property (nonatomic, strong) NSArray *btnArr; // 按钮数组 37 | /** 当天是否可预约的时间数据 */ 38 | @property (nonatomic, copy) NSArray *isShowingArr; // 当前日期的各个时间点是否可预约的数组,直接和界面进行交互 39 | /** 下标 */ 40 | @property (nonatomic, assign) NSInteger index; 41 | /** 当前展示的日期 */ 42 | @property (nonatomic, copy) NSString *currentDateStr; 43 | /** 时间格式转换器 yyyy-MM-dd */ 44 | @property (nonatomic, copy) NSDateFormatter *formatter; 45 | /** 用户当前选择的时间点 */ 46 | @property (nonatomic, assign) NSInteger selectedIndex; 47 | @property (nonatomic, weak) UIButton *selectedButton; 48 | 49 | @end 50 | 51 | @implementation TZTimePickerView 52 | 53 | #pragma mark 配置界面 54 | 55 | /* 每一个自定义控件,都需要一定的数据,这个数据一般由控制器传过来,控件根据数据的不同进行不同的展示。之后若将该控件移植到其他项目中,由新的控制器给它数据就行 */ 56 | 57 | /* 58 | 关于数据的设计: 59 | 60 | 假设这个控件应用在这样的场景:用户预约医生进行视频一对一咨询,用户选择未来7天内的某个时间点。那么这个控件需要什么数据呢? 61 | 62 | 我们需要知道 用户选择的某个时间点里 专家是否有空,从而展示在界面上的效果是,这个按钮能否被点击。 63 | 64 | 这个控件一共有12个按钮,7天的可选择日期。 65 | 思考1:每一天里,这12个按钮的enable状态,需要一个有12个元素的数组,也就是这里的 _isShowingArr。 66 | 思考2:这里一共7天,那么需要7个这样的数组,就是一个有7个子数组元素的大数组,也就是这里的 _allDaysArr。 67 | 68 | tip1: _allDaysArr是一个大数组,装着可选择日期范围内,每个时间点是否可预约的数据,_allDaysArr的count是可选择的范围大小。 69 | 它的每个元素又是一个有12个元素的小数组,代表一天中共12个时间点是否可预约。 70 | "1" : 表示该时间点专家有空,可以预约; 71 | "0" : 表示该时间点专家没空,不可预约。 72 | tip2: 总的大数组数据原本要结合服务器返回的 [哪些时间段已被预定] 的数据进行更新的 73 | 这里由于条件限制,暂只和当前时间点对比,只能选择以后的时间 74 | 75 | 用户点击 上一天/下一天 按钮时,只要改变_isShowingArr就行,这12个按钮的enable状态总是由_isShowingArr决定。先改变数据,再刷新界面。所以代码如下: 76 | 77 | */ 78 | 79 | - (NSArray *)allDaysArr { 80 | if (_allDaysArr == nil) { 81 | NSMutableArray *allDaysArr = [NSMutableArray array]; 82 | // 允许用户选择未来7天内的时间 83 | for (NSInteger i = 0; i < 7; i++) { 84 | NSArray *array = @[@"1",@"1",@"1",@"1",@"1",@"1",@"1",@"1",@"1",@"1",@"1",@"1"]; 85 | [allDaysArr addObject:array]; 86 | } 87 | _allDaysArr = allDaysArr; 88 | } 89 | return _allDaysArr; 90 | } 91 | 92 | - (instancetype)init { 93 | self = [super init]; 94 | if (self) { 95 | self = [[[NSBundle mainBundle] loadNibNamed:@"TZTimePickerView" owner:self options:nil] lastObject]; 96 | // 初始化设置 97 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 98 | self.frame = CGRectMake(20 + mScreenWidth, (mScreenHeight - 240) / 2, mScreenWidth - 40, 240); 99 | [window addSubview:self.bgView]; 100 | [window addSubview:self]; 101 | } 102 | return self; 103 | } 104 | 105 | - (UIView *)bgView { 106 | if (_bgView == nil) { 107 | _bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 108 | _bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3]; 109 | _bgView.hidden = YES; 110 | 111 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; 112 | [_bgView addGestureRecognizer:tap]; 113 | } 114 | return _bgView; 115 | } 116 | 117 | - (void)awakeFromNib { 118 | // 一次性的设置 119 | self.layer.cornerRadius = 8; 120 | self.layer.borderWidth = 0.5; 121 | CGFloat rgb = 188 / 255.0; 122 | UIColor *borderColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; 123 | self.layer.borderColor = borderColor.CGColor; 124 | self.clipsToBounds = YES; 125 | 126 | // 当前日期相关 127 | _currentDateStr = nil; 128 | _formatter = [[NSDateFormatter alloc] init]; 129 | _formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"]; 130 | [_formatter setDateFormat:@"yyyy-MM-dd"]; 131 | 132 | // 获取当天可选时间段数据 133 | [self refreshAllDaysArr]; 134 | 135 | // 初始化界面 136 | _btnArr = @[_btn1,_btn2,_btn3,_btn4,_btn5,_btn6,_btn7,_btn8,_btn9,_btn10,_btn11,_btn12]; 137 | [self setTimeBtnUI]; 138 | [self refreshTimeBtnEnable]; 139 | [self refrshLastAndNextBtnEnable]; 140 | [self refreshTitleLable]; 141 | 142 | } 143 | 144 | /** 设置每个按钮Disabled状态的标题颜色和背景图片 */ 145 | - (void)setTimeBtnUI { 146 | for (UIButton *btn in _btnArr) { 147 | [btn setTitleColor:mTitleColorDisabled forState:UIControlStateDisabled]; 148 | [btn setBackgroundImage:[self createImageWithColor:mBgColorDisabled] forState:UIControlStateDisabled]; 149 | } 150 | } 151 | 152 | /** 获取当天可选时间段数据 */ 153 | - (void)refreshAllDaysArr { 154 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 155 | formatter.dateFormat = @"HHmm"; 156 | NSString *dateStr = [formatter stringFromDate:[NSDate date]]; 157 | 158 | // 获取当天可选时间段数据 159 | NSInteger timeInt = dateStr.integerValue; 160 | NSMutableArray *arr = [NSMutableArray array]; 161 | if (timeInt >= 830) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 162 | if (timeInt >= 900) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 163 | if (timeInt >= 930) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 164 | if (timeInt >= 1000) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 165 | if (timeInt >= 1030) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 166 | if (timeInt >= 1200) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 167 | 168 | if (timeInt >= 1230) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 169 | if (timeInt >= 1330) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 170 | if (timeInt >= 1430) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 171 | if (timeInt >= 1530) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 172 | if (timeInt >= 1630) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 173 | if (timeInt >= 1830) { [arr addObject:@"0"]; } else { [arr addObject:@"1"]; }; 174 | 175 | // 替换数据 176 | self.allDaysArr[0] = arr; 177 | self.isShowingArr = self.allDaysArr[0]; 178 | } 179 | 180 | #pragma mark 功能方法 181 | 182 | /** 显示 */ 183 | - (void)show { 184 | [self checkSelectedButton]; 185 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 186 | self.bgView.hidden = NO; 187 | 188 | CGPoint center = self.center; 189 | center.x = mScreenWidth / 2; 190 | self.center = center; 191 | } completion:nil]; 192 | } 193 | 194 | /** 隐藏 */ 195 | - (void)hide { 196 | [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:0.5 options:0 animations:^{ 197 | self.bgView.hidden = YES; 198 | 199 | CGPoint center = self.center; 200 | center.x = mScreenWidth / 2 + mScreenWidth; 201 | self.center = center; 202 | } completion:nil]; 203 | } 204 | 205 | #pragma mark 点击事件 206 | 207 | /** tip: MVC思想 1、数据决定界面的展示内容 2、如果要刷新界面,必须先修改数据,再调用刷新界面的方法。 */ 208 | 209 | /** 上一天 */ 210 | - (IBAction)lastDay:(id)sender { 211 | // 1、改变数据 212 | self.index --; 213 | self.isShowingArr = self.allDaysArr[self.index]; 214 | // 2、刷新界面 215 | [self refreshTimeBtnEnable]; 216 | [self refrshLastAndNextBtnEnable]; 217 | [self refreshTitleLable]; 218 | } 219 | 220 | /** 下一天 */ 221 | - (IBAction)nextDay:(id)sender { 222 | // 1、改变数据 223 | self.index ++; 224 | self.isShowingArr = self.allDaysArr[self.index]; 225 | // 2、刷新界面 226 | [self refreshTimeBtnEnable]; 227 | [self refrshLastAndNextBtnEnable]; 228 | [self refreshTitleLable]; 229 | } 230 | 231 | /** 时间按钮点击时间 */ 232 | - (IBAction)timeButtonClick:(UIButton *)sender { 233 | // 重置上一次选择的按钮的UI 234 | if (_selectedButton) { 235 | [_selectedButton setBackgroundImage:[self createImageWithColor:[UIColor whiteColor]] forState:UIControlStateNormal]; 236 | [_selectedButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 237 | } 238 | // 记录用户选择的数据,再次选择时特殊显示 239 | _selectedIndex = _index; 240 | _selectedButton = sender; 241 | 242 | if (self.okBtnClickBlock) { // 返回 时间 和 日期 243 | self.okBtnClickBlock(sender.titleLabel.text,self.titleLable.text); 244 | } 245 | } 246 | 247 | #pragma mark 私有方法 248 | 249 | /** 刷新标题Lable */ 250 | - (void)refreshTitleLable { 251 | self.currentDateStr = [_formatter stringFromDate:[self getCurrentDate]]; 252 | self.titleLable.text = [NSString stringWithFormat:@"%@ %@",self.currentDateStr,[self getCurrentWeekDay]]; 253 | } 254 | 255 | /** 刷新 上一天/下一天 按钮的enable状态 */ 256 | - (void)refrshLastAndNextBtnEnable { 257 | self.lastDayBtn.enabled = self.index > 0 ? YES : NO; 258 | self.nextDayBtn.enabled = self.index < (self.allDaysArr.count - 1) ? YES : NO; 259 | } 260 | 261 | /** 刷新每个按钮的enable状态 */ 262 | - (void)refreshTimeBtnEnable { 263 | UIButton *btn; 264 | for (NSInteger i = 0; i < _btnArr.count; i++) { 265 | btn = _btnArr[i]; 266 | btn.enabled = [self.isShowingArr[i] isEqualToString:@"1"] ? YES : NO; 267 | } 268 | [self checkSelectedButton]; 269 | } 270 | 271 | /** 检测是否有选中过的按钮,有则特殊显示出来 */ 272 | - (void)checkSelectedButton { 273 | if (_selectedButton) { 274 | if ( _selectedIndex == _index) { 275 | UIColor *bgColor = [UIColor colorWithRed:92 / 255.0 green:217 / 255.0 blue:95 / 255.0 alpha:1.0]; 276 | [_selectedButton setBackgroundImage:[self createImageWithColor:bgColor] forState:UIControlStateNormal]; 277 | [_selectedButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 278 | } else { 279 | [_selectedButton setBackgroundImage:[self createImageWithColor:[UIColor whiteColor]] forState:UIControlStateNormal]; 280 | [_selectedButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 281 | } 282 | } 283 | } 284 | 285 | /** 根据当前的时间currentDateStr,计算星期几 */ 286 | - (NSString *)getCurrentWeekDay { 287 | NSCalendar *calendar = [NSCalendar currentCalendar]; 288 | NSDateComponents *weekComp = [calendar components:NSCalendarUnitWeekday fromDate:[self getCurrentDate]]; 289 | NSInteger weekDayEnum = [weekComp weekday]; 290 | 291 | NSString *weekDays = nil; 292 | switch (weekDayEnum) { 293 | case 1: weekDays = @"星期日"; break; 294 | case 2: weekDays = @"星期一"; break; 295 | case 3: weekDays = @"星期二"; break; 296 | case 4: weekDays = @"星期三"; break; 297 | case 5: weekDays = @"星期四"; break; 298 | case 6: weekDays = @"星期五"; break; 299 | case 7: weekDays = @"星期六"; break; 300 | default: break; 301 | } 302 | return weekDays; 303 | } 304 | 305 | /** 根据index,计算当前需要展示的日期 */ 306 | - (NSDate *)getCurrentDate { 307 | return [NSDate dateWithTimeInterval:((60*60*24) * self.index) sinceDate:[NSDate date]]; 308 | } 309 | 310 | /** 用颜色生成一张图片 */ 311 | - (UIImage *)createImageWithColor:(UIColor *)color { 312 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 313 | UIGraphicsBeginImageContext(rect.size); 314 | CGContextRef context = UIGraphicsGetCurrentContext(); 315 | CGContextSetFillColorWithColor(context, [color CGColor]); 316 | CGContextFillRect(context, rect); 317 | 318 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 319 | UIGraphicsEndImageContext(); 320 | return theImage; 321 | } 322 | 323 | 324 | /** tip: 带去使用时,记得拿走Assets.xcassets里的四张图片 */ 325 | 326 | @end 327 | -------------------------------------------------------------------------------- /TZPopInputView/TZTimePicker/TZTimePickerView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 27 | 39 | 51 | 52 | 53 | 54 | 66 | 78 | 90 | 102 | 114 | 126 | 138 | 150 | 162 | 174 | 186 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | -------------------------------------------------------------------------------- /TZPopInputView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TZPopInputView 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /TZPopInputView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TZPopInputView 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "TZPopInputView.h" 11 | #import "TZDatePickerView.h" 12 | #import "TZTimePickerView.h" 13 | 14 | #define mScreenWidth ([UIScreen mainScreen].bounds.size.width) 15 | #define mScreenHeight ([UIScreen mainScreen].bounds.size.height) 16 | 17 | @interface ViewController () 18 | @property (nonatomic, strong) TZPopInputView *inputView; // 输入框 19 | @property (nonatomic, strong) TZDatePickerView *datePicker; // 日期选择器 20 | @property (nonatomic, strong) TZTimePickerView *timePicker; // 时间选择器 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | 28 | // 创建三个button + 一个button + 一个button 29 | [self createButtonWithY:100 title:@"1.1 一行输入框 手机号" tag:0]; 30 | [self createButtonWithY:160 title:@"1.2 两行输入框 测试的" tag:1]; 31 | [self createButtonWithY:220 title:@"1.3 三行输入框 支付宝" tag:2]; 32 | 33 | [self createButtonWithY:320 title:@"2. 日期选择器 选日期" tag:3]; 34 | 35 | [self createButtonWithY:420 title:@"3. 时间选择器 选时间" tag:4]; 36 | } 37 | 38 | /* 39 | 之前是用懒加载的方式初始化inputView和datePicker,发现会有一定时间的延迟,约60ms,故将初始化方法在这里调用,这样则一点击按钮控件就能弹出来。 40 | */ 41 | - (void)viewDidAppear:(BOOL)animated { 42 | [super viewDidAppear:animated]; 43 | if (!_inputView) self.inputView = [[TZPopInputView alloc] init]; 44 | if (!_datePicker) self.datePicker = [[TZDatePickerView alloc] init]; 45 | if (!_timePicker) self.timePicker = [[TZTimePickerView alloc] init]; 46 | } 47 | 48 | /** 一定要记得在这里移除,因为是加在window上的,否则会造成内存泄露 */ 49 | - (void)viewWillDisappear:(BOOL)animated { 50 | [super viewWillDisappear:animated]; 51 | if (_inputView) [self.inputView removeFromSuperview]; 52 | if (_datePicker) [self.datePicker removeFromSuperview]; 53 | if (_timePicker) [self.timePicker removeFromSuperview]; 54 | } 55 | 56 | /** 创建button的方法 */ 57 | - (void)createButtonWithY:(CGFloat)y title:(NSString *)title tag:(NSInteger)tag{ 58 | UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 59 | button.frame = CGRectMake(50, y, mScreenWidth - 100, 60); 60 | [button setTitle:title forState:UIControlStateNormal]; 61 | [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside]; 62 | button.tag = tag; 63 | [self.view addSubview:button]; 64 | } 65 | 66 | #pragma mark 点击事件 67 | 68 | /** button的点击事件 */ 69 | - (void)buttonClick:(UIButton *)button { 70 | switch (button.tag) { 71 | case 0: // 一行输入框 72 | [self showInputViewType1]; 73 | break; 74 | case 1: // 两行输入框 75 | [self showInputViewType2]; 76 | break; 77 | case 2: // 三行输入框 78 | [self showInputViewType3]; 79 | break; 80 | case 3: // 日期选择器 81 | [self showDatePicker]; 82 | break; 83 | case 4: // 时间选择器 84 | [self showTimePicker]; 85 | break; 86 | default: 87 | break; 88 | } 89 | } 90 | 91 | #pragma mark inputView相关 92 | 93 | /* 94 | tips: 95 | 1. 传进去的items数组的元素个数,决定inputView的输入框的个数 96 | 2. 自定义键盘的代码需要在show之后,因为show的时候,键盘会设置一次。 97 | 3. inputView的回调block,返回的数组,分别是三个输入框的文本值。如果有一个输入框没有值,那么返回的数组元素个数也少一个。 98 | */ 99 | 100 | /** 一行输入框 */ 101 | - (void)showInputViewType1 { 102 | // 1. 设置数据 103 | self.inputView.titleLable.text = @"修改手机号"; 104 | [self.inputView setItems:@[@"输入新的手机号"]]; 105 | // 2. show 显示 106 | [self.inputView show]; 107 | // 3. 自定义键盘 108 | self.inputView.textFiled1.keyboardType = UIKeyboardTypeNumberPad; 109 | // 4. 定义回调block 110 | __weak typeof(self) weakSelf = self; 111 | self.inputView.okButtonClickBolck = ^(NSMutableArray *arr){ 112 | [weakSelf.inputView hide]; 113 | }; 114 | } 115 | 116 | /** 两行输入框 */ 117 | - (void)showInputViewType2 { 118 | self.inputView.titleLable.text = @"修改XXX"; 119 | [self.inputView setItems:@[@"测试一下",@"第二个输入框"]]; 120 | [self.inputView show]; 121 | 122 | __weak typeof(self) weakSelf = self; 123 | self.inputView.okButtonClickBolck = ^(NSMutableArray *arr){ 124 | [weakSelf.inputView hide]; 125 | }; 126 | } 127 | 128 | /** 三行输入框 */ 129 | - (void)showInputViewType3 { 130 | self.inputView.titleLable.text = @"修改支付宝账号"; 131 | [self.inputView setItems:@[@"原支付宝信息",@"新支付宝账号",@"新收款人姓名"]]; 132 | [self.inputView setTextFieldItems:@[[NSString stringWithFormat:@"%@ %@",@"alipayAccount",@"name"]]]; 133 | [self.inputView setPlaceholderItems:@[@"",@"手机号或邮箱",@""]]; 134 | [self.inputView show]; 135 | self.inputView.textFiled2.keyboardType = UIKeyboardTypeEmailAddress; 136 | 137 | __weak typeof(self) weakSelf = self; 138 | self.inputView.okButtonClickBolck = ^(NSMutableArray *arr){ 139 | [weakSelf.inputView hide]; 140 | }; 141 | } 142 | 143 | #pragma mark datePicker相关 144 | 145 | /* tip: datePicker的回调block,返回的数据,分别是用户选择的开始时间、结束时间。*/ 146 | 147 | /** 显示时间选择器 */ 148 | - (void)showDatePicker { 149 | [self.datePicker show]; 150 | 151 | __weak typeof(self) weakSelf = self; 152 | self.datePicker.gotoSrceenOrderBlock = ^(NSString *beginDateStr,NSString *endDateStr){ 153 | [weakSelf.datePicker hide]; 154 | }; 155 | } 156 | 157 | #pragma mark timePicker相关 158 | 159 | /* tip: timePicker的回调block,返回的数据,分别是用户选择的日期string、时间string。*/ 160 | 161 | /** 显示时间选择器 */ 162 | - (void)showTimePicker { 163 | [self.timePicker show]; 164 | 165 | __weak typeof(self) weakSelf = self; 166 | self.timePicker.okBtnClickBlock = ^(NSString *dateStr,NSString *timeStr){ 167 | [weakSelf.timePicker hide]; 168 | }; 169 | } 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /TZPopInputView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TZPopInputView 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TZPopInputViewTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /TZPopInputViewTests/TZPopInputViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TZPopInputViewTests.m 3 | // TZPopInputViewTests 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TZPopInputViewTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TZPopInputViewTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TZPopInputViewUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /TZPopInputViewUITests/TZPopInputViewUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TZPopInputViewUITests.m 3 | // TZPopInputViewUITests 4 | // 5 | // Created by 谭真 on 15/11/26. 6 | // Copyright © 2015年 谭真. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TZPopInputViewUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TZPopInputViewUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------