├── KeyBoardTextView ├── 11111111 │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Color │ │ ├── Color.h │ │ └── Color.m │ ├── Images │ │ ├── button_send@2x.png │ │ ├── button_send@3x.png │ │ ├── button_send_noshuru@2x.png │ │ └── button_send_noshuru@3x.png │ ├── Info.plist │ ├── KeyBoardTextView │ │ ├── GrowingTextView.h │ │ ├── GrowingTextView.m │ │ ├── TextViewInternal.h │ │ ├── TextViewInternal.m │ │ ├── keyboardTextView.h │ │ └── keyboardTextView.m │ ├── ViewController.h │ ├── ViewController.m │ ├── keyboardTextView.gif │ ├── main.m │ ├── testVC.h │ └── testVC.m ├── 11111111.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── MMMz.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── MMMz.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── 11111111.xcscheme │ │ └── xcschememanagement.plist ├── 11111111Tests │ ├── Info.plist │ └── _1111111Tests.m └── 11111111UITests │ ├── Info.plist │ └── _1111111UITests.m └── README.md /KeyBoardTextView/11111111.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 31B34C4D1DE05E62004921C6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C4C1DE05E62004921C6 /* main.m */; }; 11 | 31B34C501DE05E62004921C6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C4F1DE05E62004921C6 /* AppDelegate.m */; }; 12 | 31B34C531DE05E62004921C6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C521DE05E62004921C6 /* ViewController.m */; }; 13 | 31B34C561DE05E62004921C6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 31B34C541DE05E62004921C6 /* Main.storyboard */; }; 14 | 31B34C581DE05E62004921C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 31B34C571DE05E62004921C6 /* Assets.xcassets */; }; 15 | 31B34C5B1DE05E62004921C6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 31B34C591DE05E62004921C6 /* LaunchScreen.storyboard */; }; 16 | 31B34C661DE05E62004921C6 /* _1111111Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C651DE05E62004921C6 /* _1111111Tests.m */; }; 17 | 31B34C711DE05E62004921C6 /* _1111111UITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C701DE05E62004921C6 /* _1111111UITests.m */; }; 18 | 31B34C901DE1AF81004921C6 /* testVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34C8F1DE1AF81004921C6 /* testVC.m */; }; 19 | 31B34CAE1DE2C849004921C6 /* button_send@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 31B34CA31DE2C849004921C6 /* button_send@2x.png */; }; 20 | 31B34CAF1DE2C849004921C6 /* button_send@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 31B34CA41DE2C849004921C6 /* button_send@3x.png */; }; 21 | 31B34CB01DE2C849004921C6 /* button_send_noshuru@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 31B34CA51DE2C849004921C6 /* button_send_noshuru@2x.png */; }; 22 | 31B34CB11DE2C849004921C6 /* button_send_noshuru@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 31B34CA61DE2C849004921C6 /* button_send_noshuru@3x.png */; }; 23 | 31B34CB21DE2C849004921C6 /* GrowingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34CA91DE2C849004921C6 /* GrowingTextView.m */; }; 24 | 31B34CB31DE2C849004921C6 /* TextViewInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34CAB1DE2C849004921C6 /* TextViewInternal.m */; }; 25 | 31B34CB41DE2C849004921C6 /* keyboardTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34CAD1DE2C849004921C6 /* keyboardTextView.m */; }; 26 | 31B34CB81DE2C85F004921C6 /* Color.m in Sources */ = {isa = PBXBuildFile; fileRef = 31B34CB71DE2C85F004921C6 /* Color.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 31B34C621DE05E62004921C6 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 31B34C401DE05E62004921C6 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 31B34C471DE05E62004921C6; 35 | remoteInfo = 11111111; 36 | }; 37 | 31B34C6D1DE05E62004921C6 /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = 31B34C401DE05E62004921C6 /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = 31B34C471DE05E62004921C6; 42 | remoteInfo = 11111111; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 31B34C481DE05E62004921C6 /* 11111111.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 11111111.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 31B34C4C1DE05E62004921C6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | 31B34C4E1DE05E62004921C6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 50 | 31B34C4F1DE05E62004921C6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 51 | 31B34C511DE05E62004921C6 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 52 | 31B34C521DE05E62004921C6 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 53 | 31B34C551DE05E62004921C6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 31B34C571DE05E62004921C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 31B34C5A1DE05E62004921C6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 31B34C5C1DE05E62004921C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 31B34C611DE05E62004921C6 /* 11111111Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = 11111111Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 31B34C651DE05E62004921C6 /* _1111111Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = _1111111Tests.m; sourceTree = ""; }; 59 | 31B34C671DE05E62004921C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 31B34C6C1DE05E62004921C6 /* 11111111UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = 11111111UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 31B34C701DE05E62004921C6 /* _1111111UITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = _1111111UITests.m; sourceTree = ""; }; 62 | 31B34C721DE05E62004921C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 31B34C8E1DE1AF81004921C6 /* testVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testVC.h; sourceTree = ""; }; 64 | 31B34C8F1DE1AF81004921C6 /* testVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = testVC.m; sourceTree = ""; }; 65 | 31B34CA31DE2C849004921C6 /* button_send@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button_send@2x.png"; sourceTree = ""; }; 66 | 31B34CA41DE2C849004921C6 /* button_send@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button_send@3x.png"; sourceTree = ""; }; 67 | 31B34CA51DE2C849004921C6 /* button_send_noshuru@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button_send_noshuru@2x.png"; sourceTree = ""; }; 68 | 31B34CA61DE2C849004921C6 /* button_send_noshuru@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button_send_noshuru@3x.png"; sourceTree = ""; }; 69 | 31B34CA81DE2C849004921C6 /* GrowingTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GrowingTextView.h; sourceTree = ""; }; 70 | 31B34CA91DE2C849004921C6 /* GrowingTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GrowingTextView.m; sourceTree = ""; }; 71 | 31B34CAA1DE2C849004921C6 /* TextViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextViewInternal.h; sourceTree = ""; }; 72 | 31B34CAB1DE2C849004921C6 /* TextViewInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextViewInternal.m; sourceTree = ""; }; 73 | 31B34CAC1DE2C849004921C6 /* keyboardTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyboardTextView.h; sourceTree = ""; }; 74 | 31B34CAD1DE2C849004921C6 /* keyboardTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = keyboardTextView.m; sourceTree = ""; }; 75 | 31B34CB61DE2C85F004921C6 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = ""; }; 76 | 31B34CB71DE2C85F004921C6 /* Color.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Color.m; sourceTree = ""; }; 77 | /* End PBXFileReference section */ 78 | 79 | /* Begin PBXFrameworksBuildPhase section */ 80 | 31B34C451DE05E62004921C6 /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 31B34C5E1DE05E62004921C6 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | 31B34C691DE05E62004921C6 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | /* End PBXFrameworksBuildPhase section */ 102 | 103 | /* Begin PBXGroup section */ 104 | 31B34C3F1DE05E62004921C6 = { 105 | isa = PBXGroup; 106 | children = ( 107 | 31B34C4A1DE05E62004921C6 /* 11111111 */, 108 | 31B34C641DE05E62004921C6 /* 11111111Tests */, 109 | 31B34C6F1DE05E62004921C6 /* 11111111UITests */, 110 | 31B34C491DE05E62004921C6 /* Products */, 111 | ); 112 | sourceTree = ""; 113 | }; 114 | 31B34C491DE05E62004921C6 /* Products */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 31B34C481DE05E62004921C6 /* 11111111.app */, 118 | 31B34C611DE05E62004921C6 /* 11111111Tests.xctest */, 119 | 31B34C6C1DE05E62004921C6 /* 11111111UITests.xctest */, 120 | ); 121 | name = Products; 122 | sourceTree = ""; 123 | }; 124 | 31B34C4A1DE05E62004921C6 /* 11111111 */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 31B34CB51DE2C85F004921C6 /* Color */, 128 | 31B34CA21DE2C849004921C6 /* Images */, 129 | 31B34CA71DE2C849004921C6 /* KeyBoardTextView */, 130 | 31B34C4E1DE05E62004921C6 /* AppDelegate.h */, 131 | 31B34C4F1DE05E62004921C6 /* AppDelegate.m */, 132 | 31B34C511DE05E62004921C6 /* ViewController.h */, 133 | 31B34C521DE05E62004921C6 /* ViewController.m */, 134 | 31B34C8E1DE1AF81004921C6 /* testVC.h */, 135 | 31B34C8F1DE1AF81004921C6 /* testVC.m */, 136 | 31B34C541DE05E62004921C6 /* Main.storyboard */, 137 | 31B34C571DE05E62004921C6 /* Assets.xcassets */, 138 | 31B34C591DE05E62004921C6 /* LaunchScreen.storyboard */, 139 | 31B34C5C1DE05E62004921C6 /* Info.plist */, 140 | 31B34C4B1DE05E62004921C6 /* Supporting Files */, 141 | ); 142 | path = 11111111; 143 | sourceTree = ""; 144 | }; 145 | 31B34C4B1DE05E62004921C6 /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 31B34C4C1DE05E62004921C6 /* main.m */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | 31B34C641DE05E62004921C6 /* 11111111Tests */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 31B34C651DE05E62004921C6 /* _1111111Tests.m */, 157 | 31B34C671DE05E62004921C6 /* Info.plist */, 158 | ); 159 | path = 11111111Tests; 160 | sourceTree = ""; 161 | }; 162 | 31B34C6F1DE05E62004921C6 /* 11111111UITests */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 31B34C701DE05E62004921C6 /* _1111111UITests.m */, 166 | 31B34C721DE05E62004921C6 /* Info.plist */, 167 | ); 168 | path = 11111111UITests; 169 | sourceTree = ""; 170 | }; 171 | 31B34CA21DE2C849004921C6 /* Images */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 31B34CA31DE2C849004921C6 /* button_send@2x.png */, 175 | 31B34CA41DE2C849004921C6 /* button_send@3x.png */, 176 | 31B34CA51DE2C849004921C6 /* button_send_noshuru@2x.png */, 177 | 31B34CA61DE2C849004921C6 /* button_send_noshuru@3x.png */, 178 | ); 179 | path = Images; 180 | sourceTree = ""; 181 | }; 182 | 31B34CA71DE2C849004921C6 /* KeyBoardTextView */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 31B34CA81DE2C849004921C6 /* GrowingTextView.h */, 186 | 31B34CA91DE2C849004921C6 /* GrowingTextView.m */, 187 | 31B34CAA1DE2C849004921C6 /* TextViewInternal.h */, 188 | 31B34CAB1DE2C849004921C6 /* TextViewInternal.m */, 189 | 31B34CAC1DE2C849004921C6 /* keyboardTextView.h */, 190 | 31B34CAD1DE2C849004921C6 /* keyboardTextView.m */, 191 | ); 192 | path = KeyBoardTextView; 193 | sourceTree = ""; 194 | }; 195 | 31B34CB51DE2C85F004921C6 /* Color */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 31B34CB61DE2C85F004921C6 /* Color.h */, 199 | 31B34CB71DE2C85F004921C6 /* Color.m */, 200 | ); 201 | path = Color; 202 | sourceTree = ""; 203 | }; 204 | /* End PBXGroup section */ 205 | 206 | /* Begin PBXNativeTarget section */ 207 | 31B34C471DE05E62004921C6 /* 11111111 */ = { 208 | isa = PBXNativeTarget; 209 | buildConfigurationList = 31B34C751DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111" */; 210 | buildPhases = ( 211 | 31B34C441DE05E62004921C6 /* Sources */, 212 | 31B34C451DE05E62004921C6 /* Frameworks */, 213 | 31B34C461DE05E62004921C6 /* Resources */, 214 | ); 215 | buildRules = ( 216 | ); 217 | dependencies = ( 218 | ); 219 | name = 11111111; 220 | productName = 11111111; 221 | productReference = 31B34C481DE05E62004921C6 /* 11111111.app */; 222 | productType = "com.apple.product-type.application"; 223 | }; 224 | 31B34C601DE05E62004921C6 /* 11111111Tests */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 31B34C781DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111Tests" */; 227 | buildPhases = ( 228 | 31B34C5D1DE05E62004921C6 /* Sources */, 229 | 31B34C5E1DE05E62004921C6 /* Frameworks */, 230 | 31B34C5F1DE05E62004921C6 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | 31B34C631DE05E62004921C6 /* PBXTargetDependency */, 236 | ); 237 | name = 11111111Tests; 238 | productName = 11111111Tests; 239 | productReference = 31B34C611DE05E62004921C6 /* 11111111Tests.xctest */; 240 | productType = "com.apple.product-type.bundle.unit-test"; 241 | }; 242 | 31B34C6B1DE05E62004921C6 /* 11111111UITests */ = { 243 | isa = PBXNativeTarget; 244 | buildConfigurationList = 31B34C7B1DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111UITests" */; 245 | buildPhases = ( 246 | 31B34C681DE05E62004921C6 /* Sources */, 247 | 31B34C691DE05E62004921C6 /* Frameworks */, 248 | 31B34C6A1DE05E62004921C6 /* Resources */, 249 | ); 250 | buildRules = ( 251 | ); 252 | dependencies = ( 253 | 31B34C6E1DE05E62004921C6 /* PBXTargetDependency */, 254 | ); 255 | name = 11111111UITests; 256 | productName = 11111111UITests; 257 | productReference = 31B34C6C1DE05E62004921C6 /* 11111111UITests.xctest */; 258 | productType = "com.apple.product-type.bundle.ui-testing"; 259 | }; 260 | /* End PBXNativeTarget section */ 261 | 262 | /* Begin PBXProject section */ 263 | 31B34C401DE05E62004921C6 /* Project object */ = { 264 | isa = PBXProject; 265 | attributes = { 266 | LastUpgradeCheck = 0810; 267 | ORGANIZATIONNAME = Laomeng; 268 | TargetAttributes = { 269 | 31B34C471DE05E62004921C6 = { 270 | CreatedOnToolsVersion = 8.1; 271 | DevelopmentTeam = 2F8XJLGA49; 272 | ProvisioningStyle = Automatic; 273 | }; 274 | 31B34C601DE05E62004921C6 = { 275 | CreatedOnToolsVersion = 8.1; 276 | DevelopmentTeam = 2F8XJLGA49; 277 | ProvisioningStyle = Automatic; 278 | TestTargetID = 31B34C471DE05E62004921C6; 279 | }; 280 | 31B34C6B1DE05E62004921C6 = { 281 | CreatedOnToolsVersion = 8.1; 282 | DevelopmentTeam = 2F8XJLGA49; 283 | ProvisioningStyle = Automatic; 284 | TestTargetID = 31B34C471DE05E62004921C6; 285 | }; 286 | }; 287 | }; 288 | buildConfigurationList = 31B34C431DE05E62004921C6 /* Build configuration list for PBXProject "11111111" */; 289 | compatibilityVersion = "Xcode 3.2"; 290 | developmentRegion = English; 291 | hasScannedForEncodings = 0; 292 | knownRegions = ( 293 | en, 294 | Base, 295 | ); 296 | mainGroup = 31B34C3F1DE05E62004921C6; 297 | productRefGroup = 31B34C491DE05E62004921C6 /* Products */; 298 | projectDirPath = ""; 299 | projectRoot = ""; 300 | targets = ( 301 | 31B34C471DE05E62004921C6 /* 11111111 */, 302 | 31B34C601DE05E62004921C6 /* 11111111Tests */, 303 | 31B34C6B1DE05E62004921C6 /* 11111111UITests */, 304 | ); 305 | }; 306 | /* End PBXProject section */ 307 | 308 | /* Begin PBXResourcesBuildPhase section */ 309 | 31B34C461DE05E62004921C6 /* Resources */ = { 310 | isa = PBXResourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | 31B34CAF1DE2C849004921C6 /* button_send@3x.png in Resources */, 314 | 31B34CB01DE2C849004921C6 /* button_send_noshuru@2x.png in Resources */, 315 | 31B34CAE1DE2C849004921C6 /* button_send@2x.png in Resources */, 316 | 31B34C5B1DE05E62004921C6 /* LaunchScreen.storyboard in Resources */, 317 | 31B34CB11DE2C849004921C6 /* button_send_noshuru@3x.png in Resources */, 318 | 31B34C581DE05E62004921C6 /* Assets.xcassets in Resources */, 319 | 31B34C561DE05E62004921C6 /* Main.storyboard in Resources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | 31B34C5F1DE05E62004921C6 /* Resources */ = { 324 | isa = PBXResourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | }; 330 | 31B34C6A1DE05E62004921C6 /* Resources */ = { 331 | isa = PBXResourcesBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXResourcesBuildPhase section */ 338 | 339 | /* Begin PBXSourcesBuildPhase section */ 340 | 31B34C441DE05E62004921C6 /* Sources */ = { 341 | isa = PBXSourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | 31B34C531DE05E62004921C6 /* ViewController.m in Sources */, 345 | 31B34CB81DE2C85F004921C6 /* Color.m in Sources */, 346 | 31B34C501DE05E62004921C6 /* AppDelegate.m in Sources */, 347 | 31B34CB21DE2C849004921C6 /* GrowingTextView.m in Sources */, 348 | 31B34C4D1DE05E62004921C6 /* main.m in Sources */, 349 | 31B34C901DE1AF81004921C6 /* testVC.m in Sources */, 350 | 31B34CB41DE2C849004921C6 /* keyboardTextView.m in Sources */, 351 | 31B34CB31DE2C849004921C6 /* TextViewInternal.m in Sources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | 31B34C5D1DE05E62004921C6 /* Sources */ = { 356 | isa = PBXSourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | 31B34C661DE05E62004921C6 /* _1111111Tests.m in Sources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | 31B34C681DE05E62004921C6 /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 31B34C711DE05E62004921C6 /* _1111111UITests.m in Sources */, 368 | ); 369 | runOnlyForDeploymentPostprocessing = 0; 370 | }; 371 | /* End PBXSourcesBuildPhase section */ 372 | 373 | /* Begin PBXTargetDependency section */ 374 | 31B34C631DE05E62004921C6 /* PBXTargetDependency */ = { 375 | isa = PBXTargetDependency; 376 | target = 31B34C471DE05E62004921C6 /* 11111111 */; 377 | targetProxy = 31B34C621DE05E62004921C6 /* PBXContainerItemProxy */; 378 | }; 379 | 31B34C6E1DE05E62004921C6 /* PBXTargetDependency */ = { 380 | isa = PBXTargetDependency; 381 | target = 31B34C471DE05E62004921C6 /* 11111111 */; 382 | targetProxy = 31B34C6D1DE05E62004921C6 /* PBXContainerItemProxy */; 383 | }; 384 | /* End PBXTargetDependency section */ 385 | 386 | /* Begin PBXVariantGroup section */ 387 | 31B34C541DE05E62004921C6 /* Main.storyboard */ = { 388 | isa = PBXVariantGroup; 389 | children = ( 390 | 31B34C551DE05E62004921C6 /* Base */, 391 | ); 392 | name = Main.storyboard; 393 | sourceTree = ""; 394 | }; 395 | 31B34C591DE05E62004921C6 /* LaunchScreen.storyboard */ = { 396 | isa = PBXVariantGroup; 397 | children = ( 398 | 31B34C5A1DE05E62004921C6 /* Base */, 399 | ); 400 | name = LaunchScreen.storyboard; 401 | sourceTree = ""; 402 | }; 403 | /* End PBXVariantGroup section */ 404 | 405 | /* Begin XCBuildConfiguration section */ 406 | 31B34C731DE05E62004921C6 /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | ALWAYS_SEARCH_USER_PATHS = NO; 410 | CLANG_ANALYZER_NONNULL = YES; 411 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 412 | CLANG_CXX_LIBRARY = "libc++"; 413 | CLANG_ENABLE_MODULES = YES; 414 | CLANG_ENABLE_OBJC_ARC = YES; 415 | CLANG_WARN_BOOL_CONVERSION = YES; 416 | CLANG_WARN_CONSTANT_CONVERSION = YES; 417 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 418 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 419 | CLANG_WARN_EMPTY_BODY = YES; 420 | CLANG_WARN_ENUM_CONVERSION = YES; 421 | CLANG_WARN_INFINITE_RECURSION = YES; 422 | CLANG_WARN_INT_CONVERSION = YES; 423 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 424 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 425 | CLANG_WARN_UNREACHABLE_CODE = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 428 | COPY_PHASE_STRIP = NO; 429 | DEBUG_INFORMATION_FORMAT = dwarf; 430 | ENABLE_STRICT_OBJC_MSGSEND = YES; 431 | ENABLE_TESTABILITY = YES; 432 | GCC_C_LANGUAGE_STANDARD = gnu99; 433 | GCC_DYNAMIC_NO_PIC = NO; 434 | GCC_NO_COMMON_BLOCKS = YES; 435 | GCC_OPTIMIZATION_LEVEL = 0; 436 | GCC_PREPROCESSOR_DEFINITIONS = ( 437 | "DEBUG=1", 438 | "$(inherited)", 439 | ); 440 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 441 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 442 | GCC_WARN_UNDECLARED_SELECTOR = YES; 443 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 444 | GCC_WARN_UNUSED_FUNCTION = YES; 445 | GCC_WARN_UNUSED_VARIABLE = YES; 446 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 447 | MTL_ENABLE_DEBUG_INFO = YES; 448 | ONLY_ACTIVE_ARCH = YES; 449 | SDKROOT = iphoneos; 450 | }; 451 | name = Debug; 452 | }; 453 | 31B34C741DE05E62004921C6 /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | ALWAYS_SEARCH_USER_PATHS = NO; 457 | CLANG_ANALYZER_NONNULL = YES; 458 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 459 | CLANG_CXX_LIBRARY = "libc++"; 460 | CLANG_ENABLE_MODULES = YES; 461 | CLANG_ENABLE_OBJC_ARC = YES; 462 | CLANG_WARN_BOOL_CONVERSION = YES; 463 | CLANG_WARN_CONSTANT_CONVERSION = YES; 464 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 465 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 466 | CLANG_WARN_EMPTY_BODY = YES; 467 | CLANG_WARN_ENUM_CONVERSION = YES; 468 | CLANG_WARN_INFINITE_RECURSION = YES; 469 | CLANG_WARN_INT_CONVERSION = YES; 470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 471 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 472 | CLANG_WARN_UNREACHABLE_CODE = YES; 473 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 474 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 475 | COPY_PHASE_STRIP = NO; 476 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 477 | ENABLE_NS_ASSERTIONS = NO; 478 | ENABLE_STRICT_OBJC_MSGSEND = YES; 479 | GCC_C_LANGUAGE_STANDARD = gnu99; 480 | GCC_NO_COMMON_BLOCKS = YES; 481 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 482 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 483 | GCC_WARN_UNDECLARED_SELECTOR = YES; 484 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 485 | GCC_WARN_UNUSED_FUNCTION = YES; 486 | GCC_WARN_UNUSED_VARIABLE = YES; 487 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 488 | MTL_ENABLE_DEBUG_INFO = NO; 489 | SDKROOT = iphoneos; 490 | VALIDATE_PRODUCT = YES; 491 | }; 492 | name = Release; 493 | }; 494 | 31B34C761DE05E62004921C6 /* Debug */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 498 | DEVELOPMENT_TEAM = 2F8XJLGA49; 499 | INFOPLIST_FILE = 11111111/Info.plist; 500 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 501 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111"; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | }; 504 | name = Debug; 505 | }; 506 | 31B34C771DE05E62004921C6 /* Release */ = { 507 | isa = XCBuildConfiguration; 508 | buildSettings = { 509 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 510 | DEVELOPMENT_TEAM = 2F8XJLGA49; 511 | INFOPLIST_FILE = 11111111/Info.plist; 512 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 513 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111"; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | }; 516 | name = Release; 517 | }; 518 | 31B34C791DE05E62004921C6 /* Debug */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | BUNDLE_LOADER = "$(TEST_HOST)"; 522 | DEVELOPMENT_TEAM = 2F8XJLGA49; 523 | INFOPLIST_FILE = 11111111Tests/Info.plist; 524 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 525 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111Tests"; 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/11111111.app/11111111"; 528 | }; 529 | name = Debug; 530 | }; 531 | 31B34C7A1DE05E62004921C6 /* Release */ = { 532 | isa = XCBuildConfiguration; 533 | buildSettings = { 534 | BUNDLE_LOADER = "$(TEST_HOST)"; 535 | DEVELOPMENT_TEAM = 2F8XJLGA49; 536 | INFOPLIST_FILE = 11111111Tests/Info.plist; 537 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 538 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111Tests"; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/11111111.app/11111111"; 541 | }; 542 | name = Release; 543 | }; 544 | 31B34C7C1DE05E62004921C6 /* Debug */ = { 545 | isa = XCBuildConfiguration; 546 | buildSettings = { 547 | DEVELOPMENT_TEAM = 2F8XJLGA49; 548 | INFOPLIST_FILE = 11111111UITests/Info.plist; 549 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 550 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111UITests"; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | TEST_TARGET_NAME = 11111111; 553 | }; 554 | name = Debug; 555 | }; 556 | 31B34C7D1DE05E62004921C6 /* Release */ = { 557 | isa = XCBuildConfiguration; 558 | buildSettings = { 559 | DEVELOPMENT_TEAM = 2F8XJLGA49; 560 | INFOPLIST_FILE = 11111111UITests/Info.plist; 561 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 562 | PRODUCT_BUNDLE_IDENTIFIER = "Laomeng.-1111111UITests"; 563 | PRODUCT_NAME = "$(TARGET_NAME)"; 564 | TEST_TARGET_NAME = 11111111; 565 | }; 566 | name = Release; 567 | }; 568 | /* End XCBuildConfiguration section */ 569 | 570 | /* Begin XCConfigurationList section */ 571 | 31B34C431DE05E62004921C6 /* Build configuration list for PBXProject "11111111" */ = { 572 | isa = XCConfigurationList; 573 | buildConfigurations = ( 574 | 31B34C731DE05E62004921C6 /* Debug */, 575 | 31B34C741DE05E62004921C6 /* Release */, 576 | ); 577 | defaultConfigurationIsVisible = 0; 578 | defaultConfigurationName = Release; 579 | }; 580 | 31B34C751DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111" */ = { 581 | isa = XCConfigurationList; 582 | buildConfigurations = ( 583 | 31B34C761DE05E62004921C6 /* Debug */, 584 | 31B34C771DE05E62004921C6 /* Release */, 585 | ); 586 | defaultConfigurationIsVisible = 0; 587 | }; 588 | 31B34C781DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111Tests" */ = { 589 | isa = XCConfigurationList; 590 | buildConfigurations = ( 591 | 31B34C791DE05E62004921C6 /* Debug */, 592 | 31B34C7A1DE05E62004921C6 /* Release */, 593 | ); 594 | defaultConfigurationIsVisible = 0; 595 | }; 596 | 31B34C7B1DE05E62004921C6 /* Build configuration list for PBXNativeTarget "11111111UITests" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 31B34C7C1DE05E62004921C6 /* Debug */, 600 | 31B34C7D1DE05E62004921C6 /* Release */, 601 | ); 602 | defaultConfigurationIsVisible = 0; 603 | }; 604 | /* End XCConfigurationList section */ 605 | }; 606 | rootObject = 31B34C401DE05E62004921C6 /* Project object */; 607 | } 608 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111.xcodeproj/project.xcworkspace/xcuserdata/MMMz.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111.xcodeproj/project.xcworkspace/xcuserdata/MMMz.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /KeyBoardTextView/11111111.xcodeproj/xcuserdata/MMMz.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111.xcodeproj/xcuserdata/MMMz.xcuserdatad/xcschemes/11111111.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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111.xcodeproj/xcuserdata/MMMz.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 11111111.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 31B34C471DE05E62004921C6 16 | 17 | primary 18 | 19 | 20 | 31B34C601DE05E62004921C6 21 | 22 | primary 23 | 24 | 25 | 31B34C6B1DE05E62004921C6 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. 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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/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 | } -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Color/Color.h: -------------------------------------------------------------------------------- 1 | // 2 | // Color.h 3 | // 4 | // Created by mac on 16/7/8. 5 | // Copyright © 2016年 Laomeng. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /** 11 | * 16进制颜色(字符串) 12 | */ 13 | @interface Color : NSObject 14 | 15 | + (UIColor *)colorWithHex:(NSString *)color; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Color/Color.m: -------------------------------------------------------------------------------- 1 | // 2 | // Color.m 3 | // 4 | // Created by mac on 16/7/8. 5 | // Copyright © 2016年 Laomeng. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "Color.h" 10 | 11 | @interface Color () 12 | 13 | @end 14 | 15 | @implementation Color 16 | 17 | + (UIColor *)colorWithHex:(NSString *)color 18 | { 19 | NSString *cString = [[color stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 20 | 21 | // String should be 6 or 8 characters 22 | if ([cString length] < 6) { 23 | return [UIColor clearColor]; 24 | } 25 | 26 | // strip 0X if it appears 27 | if ([cString hasPrefix:@"0X"]) 28 | cString = [cString substringFromIndex:2]; 29 | if ([cString hasPrefix:@"#"]) 30 | cString = [cString substringFromIndex:1]; 31 | if ([cString length] != 6) 32 | return [UIColor clearColor]; 33 | 34 | // Separate into r, g, b substrings 35 | NSRange range; 36 | range.location = 0; 37 | range.length = 2; 38 | 39 | //r 40 | NSString *rString = [cString substringWithRange:range]; 41 | 42 | //g 43 | range.location = 2; 44 | NSString *gString = [cString substringWithRange:range]; 45 | 46 | //b 47 | range.location = 4; 48 | NSString *bString = [cString substringWithRange:range]; 49 | 50 | // Scan values 51 | unsigned int r, g, b; 52 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 53 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 54 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 55 | 56 | return [UIColor colorWithRed:((float) r / 255.0f) green:((float) g / 255.0f) blue:((float) b / 255.0f) alpha:1.0f]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Images/button_send@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111/Images/button_send@2x.png -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Images/button_send@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111/Images/button_send@3x.png -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Images/button_send_noshuru@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111/Images/button_send_noshuru@2x.png -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/Images/button_send_noshuru@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111/Images/button_send_noshuru@3x.png -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/GrowingTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextView.h 3 | // 4 | // Created by Hans Pinckaers on 29-06-10. 5 | // 6 | // MIT License 7 | // 8 | // Copyright (c) 2011 Hans Pinckaers 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import 29 | 30 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000 31 | // UITextAlignment is deprecated in iOS 6.0+, use NSTextAlignment instead. 32 | // Reference: https://developer.apple.com/library/ios/documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html 33 | #define NSTextAlignment UITextAlignment 34 | #endif 35 | 36 | @class GrowingTextView; 37 | @class TextViewInternal; 38 | 39 | @protocol GrowingTextViewDelegate 40 | 41 | @optional 42 | - (BOOL)growingTextViewShouldBeginEditing:(GrowingTextView *)growingTextView; 43 | - (BOOL)growingTextViewShouldEndEditing:(GrowingTextView *)growingTextView; 44 | 45 | - (void)growingTextViewDidBeginEditing:(GrowingTextView *)growingTextView; 46 | - (void)growingTextViewDidEndEditing:(GrowingTextView *)growingTextView; 47 | 48 | - (BOOL)growingTextView:(GrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; 49 | - (void)growingTextViewDidChange:(GrowingTextView *)growingTextView; 50 | 51 | - (void)growingTextView:(GrowingTextView *)growingTextView willChangeHeight:(float)height; 52 | - (void)growingTextView:(GrowingTextView *)growingTextView didChangeHeight:(float)height; 53 | 54 | - (void)growingTextViewDidChangeSelection:(GrowingTextView *)growingTextView; 55 | - (BOOL)growingTextViewShouldReturn:(GrowingTextView *)growingTextView; 56 | @end 57 | 58 | @interface GrowingTextView : UIView { 59 | TextViewInternal *internalTextView; 60 | 61 | int minHeight; 62 | int maxHeight; 63 | 64 | //class properties 65 | int maxNumberOfLines; 66 | int minNumberOfLines; 67 | 68 | BOOL animateHeightChange; 69 | NSTimeInterval animationDuration; 70 | 71 | //uitextview properties 72 | NSObject *__unsafe_unretained delegate; 73 | NSTextAlignment textAlignment; 74 | NSRange selectedRange; 75 | BOOL editable; 76 | UIDataDetectorTypes dataDetectorTypes; 77 | UIReturnKeyType returnKeyType; 78 | UIKeyboardType keyboardType; 79 | 80 | UIEdgeInsets contentInset; 81 | } 82 | 83 | //real class properties 84 | @property int maxNumberOfLines; 85 | @property int minNumberOfLines; 86 | @property (nonatomic) int maxHeight; 87 | @property (nonatomic) int minHeight; 88 | @property BOOL animateHeightChange; 89 | @property NSTimeInterval animationDuration; 90 | @property (nonatomic, strong) NSString *placeholder; 91 | @property (nonatomic, strong) UIColor *placeholderColor; 92 | @property (nonatomic, strong) UITextView *internalTextView; 93 | 94 | 95 | //uitextview properties 96 | @property(unsafe_unretained) NSObject *delegate; 97 | @property(nonatomic,strong) NSString *text; 98 | @property(nonatomic,strong) UIFont *font; 99 | @property(nonatomic,strong) UIColor *textColor; 100 | @property(nonatomic) NSTextAlignment textAlignment; // default is NSTextAlignmentLeft 101 | @property(nonatomic) NSRange selectedRange; // only ranges of length 0 are supported 102 | @property(nonatomic,getter=isEditable) BOOL editable; 103 | @property(nonatomic) UIDataDetectorTypes dataDetectorTypes __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_3_0); 104 | @property (nonatomic) UIReturnKeyType returnKeyType; 105 | @property (nonatomic) UIKeyboardType keyboardType; 106 | @property (assign) UIEdgeInsets contentInset; 107 | @property (nonatomic) BOOL isScrollable; 108 | @property(nonatomic) BOOL enablesReturnKeyAutomatically; 109 | 110 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 111 | - (id)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer; 112 | #endif 113 | 114 | //uitextview methods 115 | //need others? use .internalTextView 116 | - (BOOL)becomeFirstResponder; 117 | - (BOOL)resignFirstResponder; 118 | - (BOOL)isFirstResponder; 119 | 120 | - (BOOL)hasText; 121 | - (void)scrollRangeToVisible:(NSRange)range; 122 | 123 | // call to force a height change (e.g. after you change max/min lines) 124 | - (void)refreshHeight; 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/GrowingTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextView.m 3 | // 4 | // Created by Hans Pinckaers on 29-06-10. 5 | // 6 | // MIT License 7 | // 8 | // Copyright (c) 2011 Hans Pinckaers 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import "GrowingTextView.h" 29 | #import "TextViewInternal.h" 30 | 31 | @interface GrowingTextView(private) 32 | -(void)commonInitialiser; 33 | -(void)resizeTextView:(NSInteger)newSizeH; 34 | -(void)growDidStop; 35 | @end 36 | 37 | @implementation GrowingTextView 38 | @synthesize internalTextView; 39 | @synthesize delegate; 40 | @synthesize maxHeight; 41 | @synthesize minHeight; 42 | @synthesize font; 43 | @synthesize textColor; 44 | @synthesize textAlignment; 45 | @synthesize selectedRange; 46 | @synthesize editable; 47 | @synthesize dataDetectorTypes; 48 | @synthesize animateHeightChange; 49 | @synthesize animationDuration; 50 | @synthesize returnKeyType; 51 | @dynamic placeholder; 52 | @dynamic placeholderColor; 53 | 54 | // having initwithcoder allows us to use GrowingTextView in a Nib. -- aob, 9/2011 55 | - (id)initWithCoder:(NSCoder *)aDecoder 56 | { 57 | if ((self = [super initWithCoder:aDecoder])) { 58 | [self commonInitialiser]; 59 | } 60 | return self; 61 | } 62 | 63 | - (id)initWithFrame:(CGRect)frame { 64 | if ((self = [super initWithFrame:frame])) { 65 | [self commonInitialiser]; 66 | } 67 | return self; 68 | } 69 | 70 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 71 | - (id)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer { 72 | if ((self = [super initWithFrame:frame])) { 73 | [self commonInitialiser:textContainer]; 74 | } 75 | return self; 76 | } 77 | 78 | -(void)commonInitialiser { 79 | [self commonInitialiser:nil]; 80 | } 81 | 82 | -(void)commonInitialiser:(NSTextContainer *)textContainer 83 | #else 84 | -(void)commonInitialiser 85 | #endif 86 | { 87 | // Initialization code 88 | CGRect r = self.frame; 89 | r.origin.y = 0; 90 | r.origin.x = 0; 91 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 92 | internalTextView = [[TextViewInternal alloc] initWithFrame:r textContainer:textContainer]; 93 | #else 94 | internalTextView = [[TextViewInternal alloc] initWithFrame:r]; 95 | #endif 96 | internalTextView.delegate = self; 97 | internalTextView.scrollEnabled = NO; 98 | internalTextView.font = [UIFont fontWithName:@"Helvetica" size:13]; 99 | internalTextView.contentInset = UIEdgeInsetsZero; 100 | internalTextView.showsHorizontalScrollIndicator = NO; 101 | internalTextView.text = @"-"; 102 | internalTextView.contentMode = UIViewContentModeRedraw; 103 | [self addSubview:internalTextView]; 104 | 105 | minHeight = internalTextView.frame.size.height; 106 | minNumberOfLines = 1; 107 | 108 | animateHeightChange = YES; 109 | animationDuration = 0.1f; 110 | 111 | internalTextView.text = @""; 112 | 113 | [self setMaxNumberOfLines:3]; 114 | 115 | [self setPlaceholderColor:[UIColor lightGrayColor]]; 116 | internalTextView.displayPlaceHolder = YES; 117 | } 118 | 119 | -(CGSize)sizeThatFits:(CGSize)size 120 | { 121 | if (self.text.length == 0) { 122 | size.height = minHeight; 123 | } 124 | return size; 125 | } 126 | 127 | -(void)layoutSubviews 128 | { 129 | [super layoutSubviews]; 130 | 131 | CGRect r = self.bounds; 132 | r.origin.y = 0; 133 | r.origin.x = contentInset.left; 134 | r.size.width -= contentInset.left + contentInset.right; 135 | 136 | internalTextView.frame = r; 137 | } 138 | 139 | -(void)setContentInset:(UIEdgeInsets)inset 140 | { 141 | contentInset = inset; 142 | 143 | CGRect r = self.frame; 144 | r.origin.y = inset.top - inset.bottom; 145 | r.origin.x = inset.left; 146 | r.size.width -= inset.left + inset.right; 147 | 148 | internalTextView.frame = r; 149 | 150 | [self setMaxNumberOfLines:maxNumberOfLines]; 151 | [self setMinNumberOfLines:minNumberOfLines]; 152 | } 153 | 154 | -(UIEdgeInsets)contentInset 155 | { 156 | return contentInset; 157 | } 158 | 159 | -(void)setMaxNumberOfLines:(int)n 160 | { 161 | if(n == 0 && maxHeight > 0) return; // the user specified a maxHeight themselves. 162 | 163 | // Use internalTextView for height calculations, thanks to Gwynne 164 | NSString *saveText = internalTextView.text, *newText = @"-"; 165 | 166 | internalTextView.delegate = nil; 167 | internalTextView.hidden = YES; 168 | 169 | for (int i = 1; i < n; ++i) 170 | newText = [newText stringByAppendingString:@"\n|W|"]; 171 | 172 | internalTextView.text = newText; 173 | 174 | maxHeight = [self measureHeight]; 175 | 176 | internalTextView.text = saveText; 177 | internalTextView.hidden = NO; 178 | internalTextView.delegate = self; 179 | 180 | [self sizeToFit]; 181 | 182 | maxNumberOfLines = n; 183 | } 184 | 185 | -(int)maxNumberOfLines 186 | { 187 | return maxNumberOfLines; 188 | } 189 | 190 | - (void)setMaxHeight:(int)height 191 | { 192 | maxHeight = height; 193 | maxNumberOfLines = 0; 194 | } 195 | 196 | -(void)setMinNumberOfLines:(int)m 197 | { 198 | if(m == 0 && minHeight > 0) return; // the user specified a minHeight themselves. 199 | 200 | // Use internalTextView for height calculations, thanks to Gwynne 201 | NSString *saveText = internalTextView.text, *newText = @"-"; 202 | 203 | internalTextView.delegate = nil; 204 | internalTextView.hidden = YES; 205 | 206 | for (int i = 1; i < m; ++i) 207 | newText = [newText stringByAppendingString:@"\n|W|"]; 208 | 209 | internalTextView.text = newText; 210 | 211 | minHeight = [self measureHeight]; 212 | 213 | internalTextView.text = saveText; 214 | internalTextView.hidden = NO; 215 | internalTextView.delegate = self; 216 | 217 | [self sizeToFit]; 218 | 219 | minNumberOfLines = m; 220 | } 221 | 222 | -(int)minNumberOfLines 223 | { 224 | return minNumberOfLines; 225 | } 226 | 227 | - (void)setMinHeight:(int)height 228 | { 229 | minHeight = height; 230 | minNumberOfLines = 0; 231 | } 232 | 233 | - (NSString *)placeholder 234 | { 235 | return internalTextView.placeholder; 236 | } 237 | 238 | - (void)setPlaceholder:(NSString *)placeholder 239 | { 240 | [internalTextView setPlaceholder:placeholder]; 241 | [internalTextView setNeedsDisplay]; 242 | } 243 | 244 | - (UIColor *)placeholderColor 245 | { 246 | return internalTextView.placeholderColor; 247 | } 248 | 249 | - (void)setPlaceholderColor:(UIColor *)placeholderColor 250 | { 251 | [internalTextView setPlaceholderColor:placeholderColor]; 252 | } 253 | 254 | - (void)textViewDidChange:(UITextView *)textView 255 | { 256 | [self refreshHeight]; 257 | } 258 | 259 | - (void)refreshHeight 260 | { 261 | //size of content, so we can set the frame of self 262 | NSInteger newSizeH = [self measureHeight]; 263 | if (newSizeH < minHeight || !internalTextView.hasText) { 264 | newSizeH = minHeight; //not smalles than minHeight 265 | } 266 | else if (maxHeight && newSizeH > maxHeight) { 267 | newSizeH = maxHeight; // not taller than maxHeight 268 | } 269 | 270 | if (internalTextView.frame.size.height != newSizeH) 271 | { 272 | // if our new height is greater than the maxHeight 273 | // sets not set the height or move things 274 | // around and enable scrolling 275 | if (newSizeH >= maxHeight) 276 | { 277 | if(!internalTextView.scrollEnabled){ 278 | internalTextView.scrollEnabled = YES; 279 | [internalTextView flashScrollIndicators]; 280 | } 281 | 282 | } else { 283 | internalTextView.scrollEnabled = NO; 284 | } 285 | 286 | // [fixed] Pasting too much text into the view failed to fire the height change, 287 | // thanks to Gwynne 288 | if (newSizeH <= maxHeight) 289 | { 290 | if(animateHeightChange) { 291 | 292 | if ([UIView resolveClassMethod:@selector(animateWithDuration:animations:)]) { 293 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 294 | [UIView animateWithDuration:animationDuration 295 | delay:0 296 | options:(UIViewAnimationOptionAllowUserInteraction| 297 | UIViewAnimationOptionBeginFromCurrentState) 298 | animations:^(void) { 299 | [self resizeTextView:newSizeH]; 300 | } 301 | completion:^(BOOL finished) { 302 | if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { 303 | [delegate growingTextView:self didChangeHeight:newSizeH]; 304 | } 305 | }]; 306 | #endif 307 | } else { 308 | [UIView beginAnimations:@"" context:nil]; 309 | [UIView setAnimationDuration:animationDuration]; 310 | [UIView setAnimationDelegate:self]; 311 | [UIView setAnimationDidStopSelector:@selector(growDidStop)]; 312 | [UIView setAnimationBeginsFromCurrentState:YES]; 313 | [self resizeTextView:newSizeH]; 314 | [UIView commitAnimations]; 315 | } 316 | } else { 317 | [self resizeTextView:newSizeH]; 318 | // [fixed] The growingTextView:didChangeHeight: delegate method was not called at all when not animating height changes. 319 | // thanks to Gwynne 320 | 321 | if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { 322 | [delegate growingTextView:self didChangeHeight:newSizeH]; 323 | } 324 | } 325 | } 326 | } 327 | // Display (or not) the placeholder string 328 | 329 | BOOL wasDisplayingPlaceholder = internalTextView.displayPlaceHolder; 330 | internalTextView.displayPlaceHolder = self.internalTextView.text.length == 0; 331 | 332 | if (wasDisplayingPlaceholder != internalTextView.displayPlaceHolder) { 333 | [internalTextView setNeedsDisplay]; 334 | } 335 | 336 | 337 | // scroll to caret (needed on iOS7) 338 | if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) 339 | { 340 | [self performSelector:@selector(resetScrollPositionForIOS7) withObject:nil afterDelay:0.1f]; 341 | } 342 | 343 | // Tell the delegate that the text view changed 344 | if ([delegate respondsToSelector:@selector(growingTextViewDidChange:)]) { 345 | [delegate growingTextViewDidChange:self]; 346 | } 347 | } 348 | 349 | // Code from apple developer forum - @Steve Krulewitz, @Mark Marszal, @Eric Silverberg 350 | - (CGFloat)measureHeight 351 | { 352 | if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) 353 | { 354 | return ceilf([self.internalTextView sizeThatFits:self.internalTextView.frame.size].height); 355 | } 356 | else { 357 | return self.internalTextView.contentSize.height; 358 | } 359 | } 360 | 361 | - (void)resetScrollPositionForIOS7 362 | { 363 | CGRect r = [internalTextView caretRectForPosition:internalTextView.selectedTextRange.end]; 364 | CGFloat caretY = MAX(r.origin.y - internalTextView.frame.size.height + r.size.height + 8, 0); 365 | if (internalTextView.contentOffset.y < caretY && r.origin.y != INFINITY) 366 | internalTextView.contentOffset = CGPointMake(0, caretY); 367 | } 368 | 369 | -(void)resizeTextView:(NSInteger)newSizeH 370 | { 371 | if ([delegate respondsToSelector:@selector(growingTextView:willChangeHeight:)]) { 372 | [delegate growingTextView:self willChangeHeight:newSizeH]; 373 | } 374 | 375 | CGRect internalTextViewFrame = self.frame; 376 | internalTextViewFrame.size.height = newSizeH; // + padding 377 | self.frame = internalTextViewFrame; 378 | 379 | internalTextViewFrame.origin.y = contentInset.top - contentInset.bottom; 380 | internalTextViewFrame.origin.x = contentInset.left; 381 | 382 | if(!CGRectEqualToRect(internalTextView.frame, internalTextViewFrame)) internalTextView.frame = internalTextViewFrame; 383 | } 384 | 385 | - (void)growDidStop 386 | { 387 | // scroll to caret (needed on iOS7) 388 | if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) 389 | { 390 | [self resetScrollPositionForIOS7]; 391 | } 392 | 393 | if ([delegate respondsToSelector:@selector(growingTextView:didChangeHeight:)]) { 394 | [delegate growingTextView:self didChangeHeight:self.frame.size.height]; 395 | } 396 | } 397 | 398 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 399 | { 400 | [internalTextView becomeFirstResponder]; 401 | } 402 | 403 | - (BOOL)becomeFirstResponder 404 | { 405 | [super becomeFirstResponder]; 406 | return [self.internalTextView becomeFirstResponder]; 407 | } 408 | 409 | -(BOOL)resignFirstResponder 410 | { 411 | [super resignFirstResponder]; 412 | return [internalTextView resignFirstResponder]; 413 | } 414 | 415 | -(BOOL)isFirstResponder 416 | { 417 | return [self.internalTextView isFirstResponder]; 418 | } 419 | 420 | 421 | 422 | /////////////////////////////////////////////////////////////////////////////////////////////////// 423 | #pragma mark UITextView properties 424 | /////////////////////////////////////////////////////////////////////////////////////////////////// 425 | 426 | -(void)setText:(NSString *)newText 427 | { 428 | internalTextView.text = newText; 429 | 430 | // include this line to analyze the height of the textview. 431 | // fix from Ankit Thakur 432 | [self performSelector:@selector(textViewDidChange:) withObject:internalTextView]; 433 | } 434 | 435 | -(NSString*) text 436 | { 437 | return internalTextView.text; 438 | } 439 | 440 | /////////////////////////////////////////////////////////////////////////////////////////////////// 441 | 442 | -(void)setFont:(UIFont *)afont 443 | { 444 | internalTextView.font= afont; 445 | 446 | [self setMaxNumberOfLines:maxNumberOfLines]; 447 | [self setMinNumberOfLines:minNumberOfLines]; 448 | } 449 | 450 | -(UIFont *)font 451 | { 452 | return internalTextView.font; 453 | } 454 | 455 | /////////////////////////////////////////////////////////////////////////////////////////////////// 456 | 457 | -(void)setTextColor:(UIColor *)color 458 | { 459 | internalTextView.textColor = color; 460 | } 461 | 462 | -(UIColor*)textColor{ 463 | return internalTextView.textColor; 464 | } 465 | 466 | /////////////////////////////////////////////////////////////////////////////////////////////////// 467 | 468 | -(void)setBackgroundColor:(UIColor *)backgroundColor 469 | { 470 | [super setBackgroundColor:backgroundColor]; 471 | internalTextView.backgroundColor = backgroundColor; 472 | } 473 | 474 | -(UIColor*)backgroundColor 475 | { 476 | return internalTextView.backgroundColor; 477 | } 478 | 479 | /////////////////////////////////////////////////////////////////////////////////////////////////// 480 | 481 | -(void)setTextAlignment:(NSTextAlignment)aligment 482 | { 483 | internalTextView.textAlignment = aligment; 484 | } 485 | 486 | -(NSTextAlignment)textAlignment 487 | { 488 | return internalTextView.textAlignment; 489 | } 490 | 491 | /////////////////////////////////////////////////////////////////////////////////////////////////// 492 | 493 | -(void)setSelectedRange:(NSRange)range 494 | { 495 | internalTextView.selectedRange = range; 496 | } 497 | 498 | -(NSRange)selectedRange 499 | { 500 | return internalTextView.selectedRange; 501 | } 502 | 503 | /////////////////////////////////////////////////////////////////////////////////////////////////// 504 | 505 | - (void)setIsScrollable:(BOOL)isScrollable 506 | { 507 | internalTextView.scrollEnabled = isScrollable; 508 | } 509 | 510 | - (BOOL)isScrollable 511 | { 512 | return internalTextView.scrollEnabled; 513 | } 514 | 515 | /////////////////////////////////////////////////////////////////////////////////////////////////// 516 | 517 | -(void)setEditable:(BOOL)beditable 518 | { 519 | internalTextView.editable = beditable; 520 | } 521 | 522 | -(BOOL)isEditable 523 | { 524 | return internalTextView.editable; 525 | } 526 | 527 | /////////////////////////////////////////////////////////////////////////////////////////////////// 528 | 529 | -(void)setReturnKeyType:(UIReturnKeyType)keyType 530 | { 531 | internalTextView.returnKeyType = keyType; 532 | } 533 | 534 | -(UIReturnKeyType)returnKeyType 535 | { 536 | return internalTextView.returnKeyType; 537 | } 538 | 539 | /////////////////////////////////////////////////////////////////////////////////////////////////// 540 | 541 | - (void)setKeyboardType:(UIKeyboardType)keyType 542 | { 543 | internalTextView.keyboardType = keyType; 544 | } 545 | 546 | - (UIKeyboardType)keyboardType 547 | { 548 | return internalTextView.keyboardType; 549 | } 550 | 551 | /////////////////////////////////////////////////////////////////////////////////////////////////// 552 | 553 | - (void)setEnablesReturnKeyAutomatically:(BOOL)enablesReturnKeyAutomatically 554 | { 555 | internalTextView.enablesReturnKeyAutomatically = enablesReturnKeyAutomatically; 556 | } 557 | 558 | - (BOOL)enablesReturnKeyAutomatically 559 | { 560 | return internalTextView.enablesReturnKeyAutomatically; 561 | } 562 | 563 | /////////////////////////////////////////////////////////////////////////////////////////////////// 564 | 565 | -(void)setDataDetectorTypes:(UIDataDetectorTypes)datadetector 566 | { 567 | internalTextView.dataDetectorTypes = datadetector; 568 | } 569 | 570 | -(UIDataDetectorTypes)dataDetectorTypes 571 | { 572 | return internalTextView.dataDetectorTypes; 573 | } 574 | 575 | /////////////////////////////////////////////////////////////////////////////////////////////////// 576 | 577 | - (BOOL)hasText{ 578 | return [internalTextView hasText]; 579 | } 580 | 581 | - (void)scrollRangeToVisible:(NSRange)range 582 | { 583 | [internalTextView scrollRangeToVisible:range]; 584 | } 585 | 586 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 587 | ///////////////////////////////////////////////////////////////////////////////////////////////////// 588 | #pragma mark - 589 | #pragma mark UITextViewDelegate 590 | 591 | 592 | /////////////////////////////////////////////////////////////////////////////////////////////////// 593 | - (BOOL)textViewShouldBeginEditing:(UITextView *)textView { 594 | if ([delegate respondsToSelector:@selector(growingTextViewShouldBeginEditing:)]) { 595 | return [delegate growingTextViewShouldBeginEditing:self]; 596 | 597 | } else { 598 | return YES; 599 | } 600 | } 601 | 602 | 603 | /////////////////////////////////////////////////////////////////////////////////////////////////// 604 | - (BOOL)textViewShouldEndEditing:(UITextView *)textView { 605 | if ([delegate respondsToSelector:@selector(growingTextViewShouldEndEditing:)]) { 606 | return [delegate growingTextViewShouldEndEditing:self]; 607 | 608 | } else { 609 | return YES; 610 | } 611 | } 612 | 613 | 614 | /////////////////////////////////////////////////////////////////////////////////////////////////// 615 | - (void)textViewDidBeginEditing:(UITextView *)textView { 616 | if ([delegate respondsToSelector:@selector(growingTextViewDidBeginEditing:)]) { 617 | [delegate growingTextViewDidBeginEditing:self]; 618 | } 619 | } 620 | 621 | 622 | /////////////////////////////////////////////////////////////////////////////////////////////////// 623 | - (void)textViewDidEndEditing:(UITextView *)textView { 624 | if ([delegate respondsToSelector:@selector(growingTextViewDidEndEditing:)]) { 625 | [delegate growingTextViewDidEndEditing:self]; 626 | } 627 | } 628 | 629 | 630 | /////////////////////////////////////////////////////////////////////////////////////////////////// 631 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 632 | replacementText:(NSString *)atext { 633 | 634 | //weird 1 pixel bug when clicking backspace when textView is empty 635 | if(![textView hasText] && [atext isEqualToString:@""]) return NO; 636 | 637 | //Added by bretdabaker: sometimes we want to handle this ourselves 638 | if ([delegate respondsToSelector:@selector(growingTextView:shouldChangeTextInRange:replacementText:)]) 639 | return [delegate growingTextView:self shouldChangeTextInRange:range replacementText:atext]; 640 | 641 | if ([atext isEqualToString:@"\n"]) { 642 | if ([delegate respondsToSelector:@selector(growingTextViewShouldReturn:)]) { 643 | if (![delegate performSelector:@selector(growingTextViewShouldReturn:) withObject:self]) { 644 | return YES; 645 | } else { 646 | [textView resignFirstResponder]; 647 | return NO; 648 | } 649 | } 650 | } 651 | 652 | return YES; 653 | 654 | 655 | } 656 | 657 | /////////////////////////////////////////////////////////////////////////////////////////////////// 658 | - (void)textViewDidChangeSelection:(UITextView *)textView { 659 | if ([delegate respondsToSelector:@selector(growingTextViewDidChangeSelection:)]) { 660 | [delegate growingTextViewDidChangeSelection:self]; 661 | } 662 | } 663 | 664 | 665 | 666 | @end 667 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/TextViewInternal.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextViewInternal.h 3 | // 4 | // Created by Hans Pinckaers on 29-06-10. 5 | // 6 | // MIT License 7 | // 8 | // Copyright (c) 2011 Hans Pinckaers 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import 29 | 30 | 31 | @interface TextViewInternal : UITextView 32 | 33 | @property (nonatomic, strong) NSString *placeholder; 34 | @property (nonatomic, strong) UIColor *placeholderColor; 35 | @property (nonatomic) BOOL displayPlaceHolder; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/TextViewInternal.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextViewInternal.m 3 | // 4 | // Created by Hans Pinckaers on 29-06-10. 5 | // 6 | // MIT License 7 | // 8 | // Copyright (c) 2011 Hans Pinckaers 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | 28 | #import "TextViewInternal.h" 29 | 30 | 31 | @implementation TextViewInternal 32 | 33 | -(void)setText:(NSString *)text 34 | { 35 | BOOL originalValue = self.scrollEnabled; 36 | //If one of GrowingTextView's superviews is a scrollView, and self.scrollEnabled == NO, 37 | //setting the text programatically will cause UIKit to search upwards until it finds a scrollView with scrollEnabled==yes 38 | //then scroll it erratically. Setting scrollEnabled temporarily to YES prevents this. 39 | [self setScrollEnabled:YES]; 40 | [super setText:text]; 41 | [self setScrollEnabled:originalValue]; 42 | } 43 | 44 | - (void)setScrollable:(BOOL)isScrollable 45 | { 46 | [super setScrollEnabled:isScrollable]; 47 | } 48 | 49 | -(void)setContentOffset:(CGPoint)s 50 | { 51 | if(self.tracking || self.decelerating){ 52 | //initiated by user... 53 | 54 | UIEdgeInsets insets = self.contentInset; 55 | insets.bottom = 0; 56 | insets.top = 0; 57 | self.contentInset = insets; 58 | 59 | } else { 60 | 61 | float bottomOffset = (self.contentSize.height - self.frame.size.height + self.contentInset.bottom); 62 | if(s.y < bottomOffset && self.scrollEnabled){ 63 | UIEdgeInsets insets = self.contentInset; 64 | insets.bottom = 8; 65 | insets.top = 0; 66 | self.contentInset = insets; 67 | } 68 | } 69 | 70 | // Fix "overscrolling" bug 71 | if (s.y > self.contentSize.height - self.frame.size.height && !self.decelerating && !self.tracking && !self.dragging) 72 | s = CGPointMake(s.x, self.contentSize.height - self.frame.size.height); 73 | 74 | [super setContentOffset:s]; 75 | } 76 | 77 | -(void)setContentInset:(UIEdgeInsets)s 78 | { 79 | UIEdgeInsets insets = s; 80 | 81 | if(s.bottom>8) insets.bottom = 0; 82 | insets.top = 0; 83 | 84 | [super setContentInset:insets]; 85 | } 86 | 87 | -(void)setContentSize:(CGSize)contentSize 88 | { 89 | // is this an iOS5 bug? Need testing! 90 | if(self.contentSize.height > contentSize.height) 91 | { 92 | UIEdgeInsets insets = self.contentInset; 93 | insets.bottom = 0; 94 | insets.top = 0; 95 | self.contentInset = insets; 96 | } 97 | 98 | [super setContentSize:contentSize]; 99 | } 100 | 101 | - (void)drawRect:(CGRect)rect 102 | { 103 | [super drawRect:rect]; 104 | if (self.displayPlaceHolder && self.placeholder && self.placeholderColor) 105 | { 106 | if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) 107 | { 108 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 109 | paragraphStyle.alignment = self.textAlignment; 110 | [self.placeholder drawInRect:CGRectMake(5, 8 + self.contentInset.top, self.frame.size.width-self.contentInset.left, self.frame.size.height- self.contentInset.top) withAttributes:@{NSFontAttributeName:self.font, NSForegroundColorAttributeName:self.placeholderColor, NSParagraphStyleAttributeName:paragraphStyle}]; 111 | } 112 | else { 113 | [self.placeholderColor set]; 114 | [self.placeholder drawInRect:CGRectMake(8.0f, 8.0f, self.frame.size.width - 16.0f, self.frame.size.height - 16.0f) withFont:self.font]; 115 | } 116 | } 117 | } 118 | 119 | -(void)setPlaceholder:(NSString *)placeholder 120 | { 121 | _placeholder = placeholder; 122 | 123 | [self setNeedsDisplay]; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/keyboardTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // keyboardTextView.h 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/20. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface keyboardTextView : UIView 12 | - (instancetype)initWithTextViewFrame:(CGRect)frame; 13 | @property (nonatomic, copy) void (^SendMesButtonClickedBlock)(NSString *text); 14 | @end 15 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/KeyBoardTextView/keyboardTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // keyboardTextView.m 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/20. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import "keyboardTextView.h" 10 | #import "GrowingTextView.h" 11 | #import "Color.h" 12 | 13 | @interface keyboardTextView () 14 | { 15 | GrowingTextView *textView; 16 | CGRect defaultRect; 17 | CGRect keyboardBounds; 18 | CGFloat textViewDefaultHeight; 19 | NSLayoutConstraint *bgViewBottomC; 20 | NSLayoutConstraint *bgViewHeightC; 21 | } 22 | @property (nonatomic, strong) UIView *coverView; 23 | @property (nonatomic, strong) UIView *textViewBgView; 24 | @property (nonatomic, strong) UIButton *sendBtn; 25 | @end 26 | 27 | @implementation keyboardTextView 28 | 29 | - (instancetype)initWithTextViewFrame:(CGRect)frame 30 | { 31 | if (self = [super init]) { 32 | defaultRect = frame; 33 | self.frame = [UIScreen mainScreen].bounds; 34 | [self setup]; 35 | [self addKeyBoardNotification]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)setup 41 | { 42 | self.textViewBgView = [UIView new]; 43 | self.textViewBgView.translatesAutoresizingMaskIntoConstraints = NO; 44 | self.textViewBgView.backgroundColor = [Color colorWithHex:@"#EFEFEF"]; 45 | [self addSubview:self.textViewBgView]; 46 | NSLayoutConstraint *bgViewLeftC = [NSLayoutConstraint constraintWithItem:self.textViewBgView 47 | attribute:NSLayoutAttributeLeft 48 | relatedBy:NSLayoutRelationEqual 49 | toItem:self 50 | attribute:NSLayoutAttributeLeft 51 | multiplier:1.f 52 | constant:0.f]; 53 | bgViewBottomC = [NSLayoutConstraint constraintWithItem:self.textViewBgView 54 | attribute:NSLayoutAttributeBottom 55 | relatedBy:NSLayoutRelationEqual 56 | toItem:self 57 | attribute:NSLayoutAttributeBottom 58 | multiplier:1.f 59 | constant:0.f]; 60 | NSLayoutConstraint *bgViewWidthC = [NSLayoutConstraint constraintWithItem:self.textViewBgView 61 | attribute:NSLayoutAttributeWidth 62 | relatedBy:NSLayoutRelationEqual 63 | toItem:nil 64 | attribute:NSLayoutAttributeNotAnAttribute 65 | multiplier:1.f 66 | constant:[UIScreen mainScreen].bounds.size.width]; 67 | bgViewHeightC = [NSLayoutConstraint constraintWithItem:self.textViewBgView 68 | attribute:NSLayoutAttributeHeight 69 | relatedBy:NSLayoutRelationEqual 70 | toItem:nil 71 | attribute:NSLayoutAttributeNotAnAttribute 72 | multiplier:1.f 73 | constant:defaultRect.size.height]; 74 | [self addConstraints:@[bgViewLeftC, bgViewBottomC]]; 75 | [self.textViewBgView addConstraints:@[bgViewWidthC, bgViewHeightC]]; 76 | 77 | self.sendBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 78 | self.sendBtn.translatesAutoresizingMaskIntoConstraints = NO; 79 | self.sendBtn.enabled = NO; 80 | self.sendBtn.adjustsImageWhenDisabled = NO; 81 | [self.sendBtn setBackgroundImage:[UIImage imageNamed:@"button_send_noshuru"] forState:UIControlStateNormal]; 82 | [self.sendBtn addTarget:self action:@selector(sendMesAcition:) forControlEvents:UIControlEventTouchUpInside]; 83 | [self.textViewBgView addSubview:self.sendBtn]; 84 | NSLayoutConstraint *sendBtnRightC = [NSLayoutConstraint constraintWithItem:self.sendBtn 85 | attribute:NSLayoutAttributeRight 86 | relatedBy:NSLayoutRelationEqual 87 | toItem:self.textViewBgView 88 | attribute:NSLayoutAttributeRight 89 | multiplier:1.f 90 | constant:-14.f]; 91 | NSLayoutConstraint *sendBtnBottomC = [NSLayoutConstraint constraintWithItem:self.sendBtn 92 | attribute:NSLayoutAttributeBottom 93 | relatedBy:NSLayoutRelationEqual 94 | toItem:self.textViewBgView 95 | attribute:NSLayoutAttributeBottom 96 | multiplier:1.f 97 | constant:-7.f]; 98 | NSLayoutConstraint *sendBtnWidthC = [NSLayoutConstraint constraintWithItem:self.sendBtn 99 | attribute:NSLayoutAttributeWidth 100 | relatedBy:NSLayoutRelationEqual 101 | toItem:nil 102 | attribute:NSLayoutAttributeNotAnAttribute 103 | multiplier:1.f 104 | constant:47.f]; 105 | NSLayoutConstraint *sendBtnHeightC = [NSLayoutConstraint constraintWithItem:self.sendBtn 106 | attribute:NSLayoutAttributeHeight 107 | relatedBy:NSLayoutRelationEqual 108 | toItem:nil 109 | attribute:NSLayoutAttributeNotAnAttribute 110 | multiplier:1.f 111 | constant:35]; 112 | [self.textViewBgView addConstraints:@[sendBtnRightC, sendBtnBottomC]]; 113 | [self.sendBtn addConstraints:@[sendBtnWidthC, sendBtnHeightC]]; 114 | 115 | textView = [GrowingTextView new]; 116 | textView.translatesAutoresizingMaskIntoConstraints = NO; 117 | textView.isScrollable = NO; 118 | textView.contentInset = UIEdgeInsetsMake(0, 5, 0, 5); 119 | textView.minNumberOfLines = 1; 120 | textView.maxHeight = 90.f; 121 | textView.animateHeightChange = NO; 122 | textView.returnKeyType = UIReturnKeySend; 123 | textView.font = [UIFont systemFontOfSize:15.0f]; 124 | textView.textColor = [Color colorWithHex:@"#2C2C2C"]; 125 | textView.delegate = self; 126 | textView.internalTextView.scrollIndicatorInsets = UIEdgeInsetsMake(5, 0, 5, 0); 127 | textView.backgroundColor = [Color colorWithHex:@"#EFEFEF"]; 128 | textView.layer.borderWidth = 1.f; 129 | textView.layer.borderColor = [Color colorWithHex:@"#2C2C2C"].CGColor; 130 | textView.layer.cornerRadius = 5.f; 131 | textView.layer.masksToBounds = YES; 132 | textView.internalTextView.tintColor = [UIColor blackColor]; 133 | textView.placeholder = @"说点什么吧"; 134 | [self.textViewBgView addSubview:textView]; 135 | NSLayoutConstraint *topC1 = [NSLayoutConstraint constraintWithItem:textView 136 | attribute:NSLayoutAttributeTop 137 | relatedBy:NSLayoutRelationEqual 138 | toItem:self.textViewBgView 139 | attribute:NSLayoutAttributeTop 140 | multiplier:1.f 141 | constant:7.5f]; 142 | NSLayoutConstraint *leftC1 = [NSLayoutConstraint constraintWithItem:textView 143 | attribute:NSLayoutAttributeLeft 144 | relatedBy:NSLayoutRelationEqual 145 | toItem:self.textViewBgView 146 | attribute:NSLayoutAttributeLeft 147 | multiplier:1.f 148 | constant:14.f]; 149 | NSLayoutConstraint *bottomC1 = [NSLayoutConstraint constraintWithItem:textView 150 | attribute:NSLayoutAttributeBottom 151 | relatedBy:NSLayoutRelationEqual 152 | toItem:self.textViewBgView 153 | attribute:NSLayoutAttributeBottom 154 | multiplier:1.f 155 | constant:-7.5f]; 156 | NSLayoutConstraint *rightC1 = [NSLayoutConstraint constraintWithItem:self.sendBtn 157 | attribute:NSLayoutAttributeLeft 158 | relatedBy:NSLayoutRelationEqual 159 | toItem:textView 160 | attribute:NSLayoutAttributeRight 161 | multiplier:1.f 162 | constant:7.f]; 163 | [self.textViewBgView addConstraints:@[topC1, leftC1, bottomC1, rightC1]]; 164 | textViewDefaultHeight = textView.frame.size.height; 165 | 166 | self.coverView = [UIView new]; 167 | self.coverView.backgroundColor = [UIColor blackColor]; 168 | self.coverView.alpha = .5f; 169 | self.coverView.translatesAutoresizingMaskIntoConstraints = NO; 170 | self.coverView.userInteractionEnabled = YES; 171 | UITapGestureRecognizer *tapG = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(coverViewClick)]; 172 | [self.coverView addGestureRecognizer:tapG]; 173 | self.coverView.hidden = YES; 174 | [self addSubview:self.coverView]; 175 | NSLayoutConstraint *coverHeight = [NSLayoutConstraint constraintWithItem:self.coverView 176 | attribute:NSLayoutAttributeHeight 177 | relatedBy:NSLayoutRelationEqual 178 | toItem:nil 179 | attribute:NSLayoutAttributeNotAnAttribute 180 | multiplier:1.f 181 | constant:1000.f]; 182 | NSLayoutConstraint *coverLeft = [NSLayoutConstraint constraintWithItem:self.coverView 183 | attribute:NSLayoutAttributeLeft 184 | relatedBy:NSLayoutRelationEqual 185 | toItem:self.textViewBgView 186 | attribute:NSLayoutAttributeLeft 187 | multiplier:1.f 188 | constant:0]; 189 | NSLayoutConstraint *coverRight = [NSLayoutConstraint constraintWithItem:self.coverView 190 | attribute:NSLayoutAttributeRight 191 | relatedBy:NSLayoutRelationEqual 192 | toItem:self.textViewBgView 193 | attribute:NSLayoutAttributeRight 194 | multiplier:1.f 195 | constant:0]; 196 | NSLayoutConstraint *coverrBottom = [NSLayoutConstraint constraintWithItem:self.textViewBgView 197 | attribute:NSLayoutAttributeTop 198 | relatedBy:NSLayoutRelationEqual 199 | toItem:self.coverView 200 | attribute:NSLayoutAttributeBottom 201 | multiplier:1.f 202 | constant:0]; 203 | [self addConstraints:@[coverHeight, coverLeft, coverRight, coverrBottom]]; 204 | } 205 | 206 | - (void)addKeyBoardNotification 207 | { 208 | [[NSNotificationCenter defaultCenter] addObserver:self 209 | selector:@selector(keyboardWillShow:) 210 | name:UIKeyboardWillShowNotification 211 | object:nil]; 212 | 213 | [[NSNotificationCenter defaultCenter] addObserver:self 214 | selector:@selector(keyboardWillHide:) 215 | name:UIKeyboardWillHideNotification 216 | object:nil]; 217 | } 218 | 219 | -(void)keyboardWillShow:(NSNotification *)note{ 220 | [[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds]; 221 | NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; 222 | 223 | bgViewBottomC.constant = -keyboardBounds.size.height; 224 | [UIView animateWithDuration:duration.floatValue animations:^{ 225 | [self layoutIfNeeded]; 226 | self.coverView.hidden = NO; 227 | }]; 228 | } 229 | 230 | -(void)keyboardWillHide:(NSNotification *)note{ 231 | NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; 232 | bgViewBottomC.constant = 0.f; 233 | [UIView animateWithDuration:duration.floatValue animations:^{ 234 | [self layoutIfNeeded]; 235 | self.coverView.hidden = YES; 236 | }]; 237 | } 238 | 239 | - (void)growingTextView:(GrowingTextView *)growingTextView willChangeHeight:(float)height 240 | { 241 | bgViewHeightC.constant = height + 15.f; 242 | [self layoutIfNeeded]; 243 | } 244 | 245 | - (BOOL)growingTextView:(GrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 246 | { 247 | if ((growingTextView.internalTextView.text.length > 1 && text.length == 0) ||( text.length != 0)) { 248 | [self.sendBtn setBackgroundImage:[UIImage imageNamed:@"button_send"] forState:UIControlStateNormal]; 249 | self.sendBtn.enabled = YES; 250 | }else { 251 | [self.sendBtn setBackgroundImage:[UIImage imageNamed:@"button_send_noshuru"] forState:UIControlStateNormal]; 252 | self.sendBtn.enabled = NO; 253 | } 254 | return YES; 255 | } 256 | 257 | - (BOOL)growingTextViewShouldReturn:(GrowingTextView *)growingTextView 258 | { 259 | if (textView.text.length > 0) { 260 | self.SendMesButtonClickedBlock(textView.text); 261 | textView.text = @""; 262 | } 263 | if (textView.internalTextView.isFirstResponder) { 264 | [textView.internalTextView endEditing:YES]; 265 | } 266 | return YES; 267 | } 268 | 269 | - (void)coverViewClick 270 | { 271 | if (textView.internalTextView.isFirstResponder) { 272 | [textView.internalTextView endEditing:YES]; 273 | } 274 | } 275 | 276 | - (void)sendMesAcition:(UIButton *)sender 277 | { 278 | if (textView.text.length > 0) { 279 | self.SendMesButtonClickedBlock(textView.text); 280 | textView.text = @""; 281 | } 282 | if (textView.internalTextView.isFirstResponder) { 283 | [textView.internalTextView endEditing:YES]; 284 | } 285 | } 286 | 287 | /* 288 | // Only override drawRect: if you perform custom drawing. 289 | // An empty implementation adversely affects performance during animation. 290 | - (void)drawRect:(CGRect)rect { 291 | // Drawing code 292 | } 293 | */ 294 | 295 | @end 296 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "testVC.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view, typically from a nib. 21 | 22 | UIButton *btn1 = [UIButton buttonWithType: UIButtonTypeCustom]; 23 | btn1.frame = CGRectMake(20, 300, 350, 100); 24 | [btn1 setTitle:@"测试KeyBoardTextView" forState:UIControlStateNormal]; 25 | [btn1 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 26 | btn1.titleLabel.font = [UIFont systemFontOfSize:30]; 27 | [btn1 addTarget:self action:@selector(KeyBoardTextView) forControlEvents:UIControlEventTouchUpInside]; 28 | [self.view addSubview:btn1]; 29 | } 30 | 31 | - (void)KeyBoardTextView 32 | { 33 | testVC *vc = [testVC new]; 34 | [self presentViewController:vc animated:YES completion:nil]; 35 | } 36 | 37 | - (void)didReceiveMemoryWarning { 38 | [super didReceiveMemoryWarning]; 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/keyboardTextView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bestmmmz/KeyBoardTextView/d318f4d24ba77ce3f54bea384c8a1d3c278750b9/KeyBoardTextView/11111111/keyboardTextView.gif -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. 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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/testVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // testVC.h 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/20. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface testVC : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111/testVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // testVC.m 3 | // 11111111 4 | // 5 | // Created by Laomeng on 16/11/20. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import "testVC.h" 10 | #import "keyboardTextView.h" 11 | 12 | @interface testVC () 13 | @property (nonatomic, strong) UIButton *sendBtn; 14 | @end 15 | 16 | @implementation testVC 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | // Do any additional setup after loading the view. 22 | 23 | keyboardTextView *kTextView = [[keyboardTextView alloc] initWithTextViewFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 49, [UIScreen mainScreen].bounds.size.width, 49)]; 24 | [kTextView setSendMesButtonClickedBlock:^(NSString *text) { 25 | UIAlertView *alertV = [[UIAlertView alloc] initWithTitle:@"Tip" 26 | message:text 27 | delegate:nil 28 | cancelButtonTitle:nil 29 | otherButtonTitles:@"OK", nil]; 30 | [alertV show]; 31 | }]; 32 | [self.view addSubview:kTextView]; 33 | } 34 | 35 | - (void)didReceiveMemoryWarning { 36 | [super didReceiveMemoryWarning]; 37 | // Dispose of any resources that can be recreated. 38 | } 39 | 40 | /* 41 | #pragma mark - Navigation 42 | 43 | // In a storyboard-based application, you will often want to do a little preparation before navigation 44 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 45 | // Get the new view controller using [segue destinationViewController]. 46 | // Pass the selected object to the new view controller. 47 | } 48 | */ 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111Tests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111Tests/_1111111Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // _1111111Tests.m 3 | // 11111111Tests 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface _1111111Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation _1111111Tests 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 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111UITests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /KeyBoardTextView/11111111UITests/_1111111UITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // _1111111UITests.m 3 | // 11111111UITests 4 | // 5 | // Created by Laomeng on 16/11/19. 6 | // Copyright © 2016年 Laomeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface _1111111UITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation _1111111UITests 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeyBoardTextView 2 | 类似微信朋友圈和内涵段子评论回复TextView自动变化高度, 使用简单 3 | 4 | 使用方法: 5 | 6 | keyboardTextView *kTextView = [[keyboardTextView alloc] initWithTextViewFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 49, [UIScreen mainScreen].bounds.size.width, 49)]; 7 | 8 | [kTextView setSendMesButtonClickedBlock:^(NSString *text) { 9 | UIAlertView *alertV = [[UIAlertView alloc] initWithTitle:@"Tip" 10 | message:text 11 | delegate:nil 12 | cancelButtonTitle:nil 13 | otherButtonTitles:@"OK", nil]; 14 | [alertV show]; 15 | 16 | }]; 17 | [self.view addSubview:kTextView]; 18 | 19 | ![image](https://github.com/bestmmmz/KeyBoardTextView/blob/master/KeyBoardTextView/11111111/keyboardTextView.gif) 20 | --------------------------------------------------------------------------------