├── .gitignore ├── OpenInputMethod ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.core.runtime.prefs │ └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── ic_launcher-web.png ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ ├── ic_launcher.png │ │ ├── key_move_left.png │ │ ├── key_move_right.png │ │ └── mainbackground.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ ├── drawable │ │ ├── daxie.png │ │ ├── delete.png │ │ ├── delete_icon.png │ │ ├── dou_hao_e.png │ │ ├── g_key_bg.9.png │ │ ├── g_search_icon.png │ │ ├── ju_hao_e.png │ │ ├── key_bg_rectangle.xml │ │ ├── key_select_rectangle.xml │ │ ├── kongge.png │ │ ├── main_bg.jpg │ │ ├── quit_skb.png │ │ ├── softkey_bg_press2.png │ │ ├── softkey_bg_select2.9.png │ │ └── xiaoxie.png │ ├── layout │ │ ├── activity_settings.xml │ │ ├── skb_container.xml │ │ └── softkey_layout_view.xml │ ├── values-1280x720 │ │ └── dimens.xml │ ├── values-1920x1080 │ │ └── dimens.xml │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ ├── values-zh-rCN │ │ └── strings.xml │ ├── values │ │ ├── bool.xml │ │ ├── color.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── xml │ │ ├── method.xml │ │ ├── sbd_number.xml │ │ ├── sbd_qwerty.xml │ │ └── skb_template.xml └── src │ └── com │ └── open │ └── inputmethod │ ├── activity │ └── SettingsActivity.java │ ├── keyboard │ ├── InputModeSwitcher.java │ ├── KeyRow.java │ ├── SaveKeyEvent.java │ ├── SkbContainer.java │ ├── SkbPool.java │ ├── SoftKey.java │ ├── SoftKeyBoardListener.java │ ├── SoftKeyboard.java │ ├── SoftKeyboardView.java │ ├── ToggleSoftKey.java │ └── XmlKeyboardLoader.java │ ├── service │ └── IMEService.java │ └── utils │ ├── MeasureHelper.java │ ├── OPENLOG.java │ └── Utils.java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Intellij project files 26 | *.iml 27 | *.ipr 28 | *.iws 29 | .idea/ 30 | 31 | -------------------------------------------------------------------------------- /OpenInputMethod/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /OpenInputMethod/.settings/org.eclipse.core.runtime.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | line.separator=\n 3 | -------------------------------------------------------------------------------- /OpenInputMethod/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /OpenInputMethod/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /OpenInputMethod/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/ic_launcher-web.png -------------------------------------------------------------------------------- /OpenInputMethod/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/libs/android-support-v4.jar -------------------------------------------------------------------------------- /OpenInputMethod/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /OpenInputMethod/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-20 15 | -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-xhdpi/key_move_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-xhdpi/key_move_left.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-xhdpi/key_move_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-xhdpi/key_move_right.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-xhdpi/mainbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-xhdpi/mainbackground.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/daxie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/daxie.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/delete.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/delete_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/delete_icon.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/dou_hao_e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/dou_hao_e.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/g_key_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/g_key_bg.9.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/g_search_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/g_search_icon.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/ju_hao_e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/ju_hao_e.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/key_bg_rectangle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/key_select_rectangle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/kongge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/kongge.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/main_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/main_bg.jpg -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/quit_skb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/quit_skb.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/softkey_bg_press2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/softkey_bg_press2.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/softkey_bg_select2.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/softkey_bg_select2.9.png -------------------------------------------------------------------------------- /OpenInputMethod/res/drawable/xiaoxie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FrozenFreeFall/TVInputMethod/53f4a9030b4195a64f828069e4c83b56cd07c2f2/OpenInputMethod/res/drawable/xiaoxie.png -------------------------------------------------------------------------------- /OpenInputMethod/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /OpenInputMethod/res/layout/skb_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /OpenInputMethod/res/layout/softkey_layout_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values-1920x1080/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1.0px 4 | 2.0px 5 | 3.0px 6 | 4.0px 7 | 5.0px 8 | 6.0px 9 | 7.0px 10 | 8.0px 11 | 9.0px 12 | 10.0px 13 | 11.0px 14 | 12.0px 15 | 13.0px 16 | 14.0px 17 | 15.0px 18 | 16.0px 19 | 17.0px 20 | 18.0px 21 | 19.0px 22 | 20.0px 23 | 21.0px 24 | 22.0px 25 | 23.0px 26 | 24.0px 27 | 25.0px 28 | 26.0px 29 | 27.0px 30 | 28.0px 31 | 29.0px 32 | 30.0px 33 | 31.0px 34 | 32.0px 35 | 33.0px 36 | 34.0px 37 | 35.0px 38 | 36.0px 39 | 37.0px 40 | 38.0px 41 | 39.0px 42 | 40.0px 43 | 41.0px 44 | 42.0px 45 | 43.0px 46 | 44.0px 47 | 45.0px 48 | 46.0px 49 | 47.0px 50 | 48.0px 51 | 49.0px 52 | 50.0px 53 | 51.0px 54 | 52.0px 55 | 53.0px 56 | 54.0px 57 | 55.0px 58 | 56.0px 59 | 57.0px 60 | 58.0px 61 | 59.0px 62 | 60.0px 63 | 61.0px 64 | 62.0px 65 | 63.0px 66 | 64.0px 67 | 65.0px 68 | 66.0px 69 | 67.0px 70 | 68.0px 71 | 69.0px 72 | 70.0px 73 | 71.0px 74 | 72.0px 75 | 73.0px 76 | 74.0px 77 | 75.0px 78 | 76.0px 79 | 77.0px 80 | 78.0px 81 | 79.0px 82 | 80.0px 83 | 81.0px 84 | 82.0px 85 | 83.0px 86 | 84.0px 87 | 85.0px 88 | 86.0px 89 | 87.0px 90 | 88.0px 91 | 89.0px 92 | 90.0px 93 | 91.0px 94 | 92.0px 95 | 93.0px 96 | 94.0px 97 | 95.0px 98 | 96.0px 99 | 97.0px 100 | 98.0px 101 | 99.0px 102 | 100.0px 103 | 101.0px 104 | 102.0px 105 | 103.0px 106 | 104.0px 107 | 105.0px 108 | 106.0px 109 | 107.0px 110 | 108.0px 111 | 109.0px 112 | 110.0px 113 | 111.0px 114 | 112.0px 115 | 113.0px 116 | 114.0px 117 | 115.0px 118 | 116.0px 119 | 117.0px 120 | 118.0px 121 | 119.0px 122 | 120.0px 123 | 121.0px 124 | 122.0px 125 | 123.0px 126 | 124.0px 127 | 125.0px 128 | 126.0px 129 | 127.0px 130 | 128.0px 131 | 129.0px 132 | 130.0px 133 | 131.0px 134 | 132.0px 135 | 133.0px 136 | 134.0px 137 | 135.0px 138 | 136.0px 139 | 137.0px 140 | 138.0px 141 | 139.0px 142 | 140.0px 143 | 141.0px 144 | 142.0px 145 | 143.0px 146 | 144.0px 147 | 145.0px 148 | 146.0px 149 | 147.0px 150 | 148.0px 151 | 149.0px 152 | 150.0px 153 | 151.0px 154 | 152.0px 155 | 153.0px 156 | 154.0px 157 | 155.0px 158 | 156.0px 159 | 157.0px 160 | 158.0px 161 | 159.0px 162 | 160.0px 163 | 161.0px 164 | 162.0px 165 | 163.0px 166 | 164.0px 167 | 165.0px 168 | 166.0px 169 | 167.0px 170 | 168.0px 171 | 169.0px 172 | 170.0px 173 | 171.0px 174 | 172.0px 175 | 173.0px 176 | 174.0px 177 | 175.0px 178 | 176.0px 179 | 177.0px 180 | 178.0px 181 | 179.0px 182 | 180.0px 183 | 181.0px 184 | 182.0px 185 | 183.0px 186 | 184.0px 187 | 185.0px 188 | 186.0px 189 | 187.0px 190 | 188.0px 191 | 189.0px 192 | 190.0px 193 | 191.0px 194 | 192.0px 195 | 193.0px 196 | 194.0px 197 | 195.0px 198 | 196.0px 199 | 197.0px 200 | 198.0px 201 | 199.0px 202 | 200.0px 203 | 201.0px 204 | 202.0px 205 | 203.0px 206 | 204.0px 207 | 205.0px 208 | 206.0px 209 | 207.0px 210 | 208.0px 211 | 209.0px 212 | 210.0px 213 | 211.0px 214 | 212.0px 215 | 213.0px 216 | 214.0px 217 | 215.0px 218 | 216.0px 219 | 217.0px 220 | 218.0px 221 | 219.0px 222 | 220.0px 223 | 221.0px 224 | 222.0px 225 | 223.0px 226 | 224.0px 227 | 225.0px 228 | 226.0px 229 | 227.0px 230 | 228.0px 231 | 229.0px 232 | 230.0px 233 | 231.0px 234 | 232.0px 235 | 233.0px 236 | 234.0px 237 | 235.0px 238 | 236.0px 239 | 237.0px 240 | 238.0px 241 | 239.0px 242 | 240.0px 243 | 241.0px 244 | 242.0px 245 | 243.0px 246 | 244.0px 247 | 245.0px 248 | 246.0px 249 | 247.0px 250 | 248.0px 251 | 249.0px 252 | 250.0px 253 | 251.0px 254 | 252.0px 255 | 253.0px 256 | 254.0px 257 | 255.0px 258 | 256.0px 259 | 257.0px 260 | 258.0px 261 | 259.0px 262 | 260.0px 263 | 261.0px 264 | 262.0px 265 | 263.0px 266 | 264.0px 267 | 265.0px 268 | 266.0px 269 | 267.0px 270 | 268.0px 271 | 269.0px 272 | 270.0px 273 | 271.0px 274 | 272.0px 275 | 273.0px 276 | 274.0px 277 | 275.0px 278 | 276.0px 279 | 277.0px 280 | 278.0px 281 | 279.0px 282 | 280.0px 283 | 281.0px 284 | 282.0px 285 | 283.0px 286 | 284.0px 287 | 285.0px 288 | 286.0px 289 | 287.0px 290 | 288.0px 291 | 289.0px 292 | 290.0px 293 | 291.0px 294 | 292.0px 295 | 293.0px 296 | 294.0px 297 | 295.0px 298 | 296.0px 299 | 297.0px 300 | 298.0px 301 | 299.0px 302 | 300.0px 303 | 301.0px 304 | 302.0px 305 | 303.0px 306 | 304.0px 307 | 305.0px 308 | 306.0px 309 | 307.0px 310 | 308.0px 311 | 309.0px 312 | 310.0px 313 | 311.0px 314 | 312.0px 315 | 313.0px 316 | 314.0px 317 | 315.0px 318 | 316.0px 319 | 317.0px 320 | 318.0px 321 | 319.0px 322 | 320.0px 323 | 321.0px 324 | 322.0px 325 | 323.0px 326 | 324.0px 327 | 325.0px 328 | 326.0px 329 | 327.0px 330 | 328.0px 331 | 329.0px 332 | 330.0px 333 | 331.0px 334 | 332.0px 335 | 333.0px 336 | 334.0px 337 | 335.0px 338 | 336.0px 339 | 337.0px 340 | 338.0px 341 | 339.0px 342 | 340.0px 343 | 341.0px 344 | 342.0px 345 | 343.0px 346 | 344.0px 347 | 345.0px 348 | 346.0px 349 | 347.0px 350 | 348.0px 351 | 349.0px 352 | 350.0px 353 | 351.0px 354 | 352.0px 355 | 353.0px 356 | 354.0px 357 | 355.0px 358 | 356.0px 359 | 357.0px 360 | 358.0px 361 | 359.0px 362 | 360.0px 363 | 361.0px 364 | 362.0px 365 | 363.0px 366 | 364.0px 367 | 365.0px 368 | 366.0px 369 | 367.0px 370 | 368.0px 371 | 369.0px 372 | 370.0px 373 | 371.0px 374 | 372.0px 375 | 373.0px 376 | 374.0px 377 | 375.0px 378 | 376.0px 379 | 377.0px 380 | 378.0px 381 | 379.0px 382 | 380.0px 383 | 381.0px 384 | 382.0px 385 | 383.0px 386 | 384.0px 387 | 385.0px 388 | 386.0px 389 | 387.0px 390 | 388.0px 391 | 389.0px 392 | 390.0px 393 | 391.0px 394 | 392.0px 395 | 393.0px 396 | 394.0px 397 | 395.0px 398 | 396.0px 399 | 397.0px 400 | 398.0px 401 | 399.0px 402 | 400.0px 403 | 401.0px 404 | 402.0px 405 | 403.0px 406 | 404.0px 407 | 405.0px 408 | 406.0px 409 | 407.0px 410 | 408.0px 411 | 409.0px 412 | 410.0px 413 | 411.0px 414 | 412.0px 415 | 413.0px 416 | 414.0px 417 | 415.0px 418 | 416.0px 419 | 417.0px 420 | 418.0px 421 | 419.0px 422 | 420.0px 423 | 421.0px 424 | 422.0px 425 | 423.0px 426 | 424.0px 427 | 425.0px 428 | 426.0px 429 | 427.0px 430 | 428.0px 431 | 429.0px 432 | 430.0px 433 | 431.0px 434 | 432.0px 435 | 433.0px 436 | 434.0px 437 | 435.0px 438 | 436.0px 439 | 437.0px 440 | 438.0px 441 | 439.0px 442 | 440.0px 443 | 441.0px 444 | 442.0px 445 | 443.0px 446 | 444.0px 447 | 445.0px 448 | 446.0px 449 | 447.0px 450 | 448.0px 451 | 449.0px 452 | 450.0px 453 | 451.0px 454 | 452.0px 455 | 453.0px 456 | 454.0px 457 | 455.0px 458 | 456.0px 459 | 457.0px 460 | 458.0px 461 | 459.0px 462 | 460.0px 463 | 461.0px 464 | 462.0px 465 | 463.0px 466 | 464.0px 467 | 465.0px 468 | 466.0px 469 | 467.0px 470 | 468.0px 471 | 469.0px 472 | 470.0px 473 | 471.0px 474 | 472.0px 475 | 473.0px 476 | 474.0px 477 | 475.0px 478 | 476.0px 479 | 477.0px 480 | 478.0px 481 | 479.0px 482 | 480.0px 483 | 481.0px 484 | 482.0px 485 | 483.0px 486 | 484.0px 487 | 485.0px 488 | 486.0px 489 | 487.0px 490 | 488.0px 491 | 489.0px 492 | 490.0px 493 | 491.0px 494 | 492.0px 495 | 493.0px 496 | 494.0px 497 | 495.0px 498 | 496.0px 499 | 497.0px 500 | 498.0px 501 | 499.0px 502 | 500.0px 503 | 501.0px 504 | 502.0px 505 | 503.0px 506 | 504.0px 507 | 505.0px 508 | 506.0px 509 | 507.0px 510 | 508.0px 511 | 509.0px 512 | 510.0px 513 | 511.0px 514 | 512.0px 515 | 513.0px 516 | 514.0px 517 | 515.0px 518 | 516.0px 519 | 517.0px 520 | 518.0px 521 | 519.0px 522 | 520.0px 523 | 521.0px 524 | 522.0px 525 | 523.0px 526 | 524.0px 527 | 525.0px 528 | 526.0px 529 | 527.0px 530 | 528.0px 531 | 529.0px 532 | 530.0px 533 | 531.0px 534 | 532.0px 535 | 533.0px 536 | 534.0px 537 | 535.0px 538 | 536.0px 539 | 537.0px 540 | 538.0px 541 | 539.0px 542 | 540.0px 543 | 541.0px 544 | 542.0px 545 | 543.0px 546 | 544.0px 547 | 545.0px 548 | 546.0px 549 | 547.0px 550 | 548.0px 551 | 549.0px 552 | 550.0px 553 | 551.0px 554 | 552.0px 555 | 553.0px 556 | 554.0px 557 | 555.0px 558 | 556.0px 559 | 557.0px 560 | 558.0px 561 | 559.0px 562 | 560.0px 563 | 561.0px 564 | 562.0px 565 | 563.0px 566 | 564.0px 567 | 565.0px 568 | 566.0px 569 | 567.0px 570 | 568.0px 571 | 569.0px 572 | 570.0px 573 | 571.0px 574 | 572.0px 575 | 573.0px 576 | 574.0px 577 | 575.0px 578 | 576.0px 579 | 577.0px 580 | 578.0px 581 | 579.0px 582 | 580.0px 583 | 581.0px 584 | 582.0px 585 | 583.0px 586 | 584.0px 587 | 585.0px 588 | 586.0px 589 | 587.0px 590 | 588.0px 591 | 589.0px 592 | 590.0px 593 | 591.0px 594 | 592.0px 595 | 593.0px 596 | 594.0px 597 | 595.0px 598 | 596.0px 599 | 597.0px 600 | 598.0px 601 | 599.0px 602 | 600.0px 603 | 601.0px 604 | 602.0px 605 | 603.0px 606 | 604.0px 607 | 605.0px 608 | 606.0px 609 | 607.0px 610 | 608.0px 611 | 609.0px 612 | 610.0px 613 | 611.0px 614 | 612.0px 615 | 613.0px 616 | 614.0px 617 | 615.0px 618 | 616.0px 619 | 617.0px 620 | 618.0px 621 | 619.0px 622 | 620.0px 623 | 621.0px 624 | 622.0px 625 | 623.0px 626 | 624.0px 627 | 625.0px 628 | 626.0px 629 | 627.0px 630 | 628.0px 631 | 629.0px 632 | 630.0px 633 | 631.0px 634 | 632.0px 635 | 633.0px 636 | 634.0px 637 | 635.0px 638 | 636.0px 639 | 637.0px 640 | 638.0px 641 | 639.0px 642 | 640.0px 643 | 641.0px 644 | 642.0px 645 | 643.0px 646 | 644.0px 647 | 645.0px 648 | 646.0px 649 | 647.0px 650 | 648.0px 651 | 649.0px 652 | 650.0px 653 | 651.0px 654 | 652.0px 655 | 653.0px 656 | 654.0px 657 | 655.0px 658 | 656.0px 659 | 657.0px 660 | 658.0px 661 | 659.0px 662 | 660.0px 663 | 661.0px 664 | 662.0px 665 | 663.0px 666 | 664.0px 667 | 665.0px 668 | 666.0px 669 | 667.0px 670 | 668.0px 671 | 669.0px 672 | 670.0px 673 | 671.0px 674 | 672.0px 675 | 673.0px 676 | 674.0px 677 | 675.0px 678 | 676.0px 679 | 677.0px 680 | 678.0px 681 | 679.0px 682 | 680.0px 683 | 681.0px 684 | 682.0px 685 | 683.0px 686 | 684.0px 687 | 685.0px 688 | 686.0px 689 | 687.0px 690 | 688.0px 691 | 689.0px 692 | 690.0px 693 | 691.0px 694 | 692.0px 695 | 693.0px 696 | 694.0px 697 | 695.0px 698 | 696.0px 699 | 697.0px 700 | 698.0px 701 | 699.0px 702 | 700.0px 703 | 701.0px 704 | 702.0px 705 | 703.0px 706 | 704.0px 707 | 705.0px 708 | 706.0px 709 | 707.0px 710 | 708.0px 711 | 709.0px 712 | 710.0px 713 | 711.0px 714 | 712.0px 715 | 713.0px 716 | 714.0px 717 | 715.0px 718 | 716.0px 719 | 717.0px 720 | 718.0px 721 | 719.0px 722 | 720.0px 723 | 721.0px 724 | 722.0px 725 | 723.0px 726 | 724.0px 727 | 725.0px 728 | 726.0px 729 | 727.0px 730 | 728.0px 731 | 729.0px 732 | 730.0px 733 | 731.0px 734 | 732.0px 735 | 733.0px 736 | 734.0px 737 | 735.0px 738 | 736.0px 739 | 737.0px 740 | 738.0px 741 | 739.0px 742 | 740.0px 743 | 741.0px 744 | 742.0px 745 | 743.0px 746 | 744.0px 747 | 745.0px 748 | 746.0px 749 | 747.0px 750 | 748.0px 751 | 749.0px 752 | 750.0px 753 | 751.0px 754 | 752.0px 755 | 753.0px 756 | 754.0px 757 | 755.0px 758 | 756.0px 759 | 757.0px 760 | 758.0px 761 | 759.0px 762 | 760.0px 763 | 761.0px 764 | 762.0px 765 | 763.0px 766 | 764.0px 767 | 765.0px 768 | 766.0px 769 | 767.0px 770 | 768.0px 771 | 769.0px 772 | 770.0px 773 | 771.0px 774 | 772.0px 775 | 773.0px 776 | 774.0px 777 | 775.0px 778 | 776.0px 779 | 777.0px 780 | 778.0px 781 | 779.0px 782 | 780.0px 783 | 781.0px 784 | 782.0px 785 | 783.0px 786 | 784.0px 787 | 785.0px 788 | 786.0px 789 | 787.0px 790 | 788.0px 791 | 789.0px 792 | 790.0px 793 | 791.0px 794 | 792.0px 795 | 793.0px 796 | 794.0px 797 | 795.0px 798 | 796.0px 799 | 797.0px 800 | 798.0px 801 | 799.0px 802 | 800.0px 803 | 801.0px 804 | 802.0px 805 | 803.0px 806 | 804.0px 807 | 805.0px 808 | 806.0px 809 | 807.0px 810 | 808.0px 811 | 809.0px 812 | 810.0px 813 | 811.0px 814 | 812.0px 815 | 813.0px 816 | 814.0px 817 | 815.0px 818 | 816.0px 819 | 817.0px 820 | 818.0px 821 | 819.0px 822 | 820.0px 823 | 821.0px 824 | 822.0px 825 | 823.0px 826 | 824.0px 827 | 825.0px 828 | 826.0px 829 | 827.0px 830 | 828.0px 831 | 829.0px 832 | 830.0px 833 | 831.0px 834 | 832.0px 835 | 833.0px 836 | 834.0px 837 | 835.0px 838 | 836.0px 839 | 837.0px 840 | 838.0px 841 | 839.0px 842 | 840.0px 843 | 841.0px 844 | 842.0px 845 | 843.0px 846 | 844.0px 847 | 845.0px 848 | 846.0px 849 | 847.0px 850 | 848.0px 851 | 849.0px 852 | 850.0px 853 | 851.0px 854 | 852.0px 855 | 853.0px 856 | 854.0px 857 | 855.0px 858 | 856.0px 859 | 857.0px 860 | 858.0px 861 | 859.0px 862 | 860.0px 863 | 861.0px 864 | 862.0px 865 | 863.0px 866 | 864.0px 867 | 865.0px 868 | 866.0px 869 | 867.0px 870 | 868.0px 871 | 869.0px 872 | 870.0px 873 | 871.0px 874 | 872.0px 875 | 873.0px 876 | 874.0px 877 | 875.0px 878 | 876.0px 879 | 877.0px 880 | 878.0px 881 | 879.0px 882 | 880.0px 883 | 881.0px 884 | 882.0px 885 | 883.0px 886 | 884.0px 887 | 885.0px 888 | 886.0px 889 | 887.0px 890 | 888.0px 891 | 889.0px 892 | 890.0px 893 | 891.0px 894 | 892.0px 895 | 893.0px 896 | 894.0px 897 | 895.0px 898 | 896.0px 899 | 897.0px 900 | 898.0px 901 | 899.0px 902 | 900.0px 903 | 901.0px 904 | 902.0px 905 | 903.0px 906 | 904.0px 907 | 905.0px 908 | 906.0px 909 | 907.0px 910 | 908.0px 911 | 909.0px 912 | 910.0px 913 | 911.0px 914 | 912.0px 915 | 913.0px 916 | 914.0px 917 | 915.0px 918 | 916.0px 919 | 917.0px 920 | 918.0px 921 | 919.0px 922 | 920.0px 923 | 921.0px 924 | 922.0px 925 | 923.0px 926 | 924.0px 927 | 925.0px 928 | 926.0px 929 | 927.0px 930 | 928.0px 931 | 929.0px 932 | 930.0px 933 | 931.0px 934 | 932.0px 935 | 933.0px 936 | 934.0px 937 | 935.0px 938 | 936.0px 939 | 937.0px 940 | 938.0px 941 | 939.0px 942 | 940.0px 943 | 941.0px 944 | 942.0px 945 | 943.0px 946 | 944.0px 947 | 945.0px 948 | 946.0px 949 | 947.0px 950 | 948.0px 951 | 949.0px 952 | 950.0px 953 | 951.0px 954 | 952.0px 955 | 953.0px 956 | 954.0px 957 | 955.0px 958 | 956.0px 959 | 957.0px 960 | 958.0px 961 | 959.0px 962 | 960.0px 963 | 961.0px 964 | 962.0px 965 | 963.0px 966 | 964.0px 967 | 965.0px 968 | 966.0px 969 | 967.0px 970 | 968.0px 971 | 969.0px 972 | 970.0px 973 | 971.0px 974 | 972.0px 975 | 973.0px 976 | 974.0px 977 | 975.0px 978 | 976.0px 979 | 977.0px 980 | 978.0px 981 | 979.0px 982 | 980.0px 983 | 981.0px 984 | 982.0px 985 | 983.0px 986 | 984.0px 987 | 985.0px 988 | 986.0px 989 | 987.0px 990 | 988.0px 991 | 989.0px 992 | 990.0px 993 | 991.0px 994 | 992.0px 995 | 993.0px 996 | 994.0px 997 | 995.0px 998 | 996.0px 999 | 997.0px 1000 | 998.0px 1001 | 999.0px 1002 | 1000.0px 1003 | 1001.0px 1004 | 1002.0px 1005 | 1003.0px 1006 | 1004.0px 1007 | 1005.0px 1008 | 1006.0px 1009 | 1007.0px 1010 | 1008.0px 1011 | 1009.0px 1012 | 1010.0px 1013 | 1011.0px 1014 | 1012.0px 1015 | 1013.0px 1016 | 1014.0px 1017 | 1015.0px 1018 | 1016.0px 1019 | 1017.0px 1020 | 1018.0px 1021 | 1019.0px 1022 | 1020.0px 1023 | 1021.0px 1024 | 1022.0px 1025 | 1023.0px 1026 | 1024.0px 1027 | 1025.0px 1028 | 1026.0px 1029 | 1027.0px 1030 | 1028.0px 1031 | 1029.0px 1032 | 1030.0px 1033 | 1031.0px 1034 | 1032.0px 1035 | 1033.0px 1036 | 1034.0px 1037 | 1035.0px 1038 | 1036.0px 1039 | 1037.0px 1040 | 1038.0px 1041 | 1039.0px 1042 | 1040.0px 1043 | 1041.0px 1044 | 1042.0px 1045 | 1043.0px 1046 | 1044.0px 1047 | 1045.0px 1048 | 1046.0px 1049 | 1047.0px 1050 | 1048.0px 1051 | 1049.0px 1052 | 1050.0px 1053 | 1051.0px 1054 | 1052.0px 1055 | 1053.0px 1056 | 1054.0px 1057 | 1055.0px 1058 | 1056.0px 1059 | 1057.0px 1060 | 1058.0px 1061 | 1059.0px 1062 | 1060.0px 1063 | 1061.0px 1064 | 1062.0px 1065 | 1063.0px 1066 | 1064.0px 1067 | 1065.0px 1068 | 1066.0px 1069 | 1067.0px 1070 | 1068.0px 1071 | 1069.0px 1072 | 1070.0px 1073 | 1071.0px 1074 | 1072.0px 1075 | 1073.0px 1076 | 1074.0px 1077 | 1075.0px 1078 | 1076.0px 1079 | 1077.0px 1080 | 1078.0px 1081 | 1079.0px 1082 | 1080.0px 1083 | 1081.0px 1084 | 1082.0px 1085 | 1083.0px 1086 | 1084.0px 1087 | 1085.0px 1088 | 1086.0px 1089 | 1087.0px 1090 | 1088.0px 1091 | 1089.0px 1092 | 1090.0px 1093 | 1091.0px 1094 | 1092.0px 1095 | 1093.0px 1096 | 1094.0px 1097 | 1095.0px 1098 | 1096.0px 1099 | 1097.0px 1100 | 1098.0px 1101 | 1099.0px 1102 | 1100.0px 1103 | 1101.0px 1104 | 1102.0px 1105 | 1103.0px 1106 | 1104.0px 1107 | 1105.0px 1108 | 1106.0px 1109 | 1107.0px 1110 | 1108.0px 1111 | 1109.0px 1112 | 1110.0px 1113 | 1111.0px 1114 | 1112.0px 1115 | 1113.0px 1116 | 1114.0px 1117 | 1115.0px 1118 | 1116.0px 1119 | 1117.0px 1120 | 1118.0px 1121 | 1119.0px 1122 | 1120.0px 1123 | 1121.0px 1124 | 1122.0px 1125 | 1123.0px 1126 | 1124.0px 1127 | 1125.0px 1128 | 1126.0px 1129 | 1127.0px 1130 | 1128.0px 1131 | 1129.0px 1132 | 1130.0px 1133 | 1131.0px 1134 | 1132.0px 1135 | 1133.0px 1136 | 1134.0px 1137 | 1135.0px 1138 | 1136.0px 1139 | 1137.0px 1140 | 1138.0px 1141 | 1139.0px 1142 | 1140.0px 1143 | 1141.0px 1144 | 1142.0px 1145 | 1143.0px 1146 | 1144.0px 1147 | 1145.0px 1148 | 1146.0px 1149 | 1147.0px 1150 | 1148.0px 1151 | 1149.0px 1152 | 1150.0px 1153 | 1151.0px 1154 | 1152.0px 1155 | 1153.0px 1156 | 1154.0px 1157 | 1155.0px 1158 | 1156.0px 1159 | 1157.0px 1160 | 1158.0px 1161 | 1159.0px 1162 | 1160.0px 1163 | 1161.0px 1164 | 1162.0px 1165 | 1163.0px 1166 | 1164.0px 1167 | 1165.0px 1168 | 1166.0px 1169 | 1167.0px 1170 | 1168.0px 1171 | 1169.0px 1172 | 1170.0px 1173 | 1171.0px 1174 | 1172.0px 1175 | 1173.0px 1176 | 1174.0px 1177 | 1175.0px 1178 | 1176.0px 1179 | 1177.0px 1180 | 1178.0px 1181 | 1179.0px 1182 | 1180.0px 1183 | 1181.0px 1184 | 1182.0px 1185 | 1183.0px 1186 | 1184.0px 1187 | 1185.0px 1188 | 1186.0px 1189 | 1187.0px 1190 | 1188.0px 1191 | 1189.0px 1192 | 1190.0px 1193 | 1191.0px 1194 | 1192.0px 1195 | 1193.0px 1196 | 1194.0px 1197 | 1195.0px 1198 | 1196.0px 1199 | 1197.0px 1200 | 1198.0px 1201 | 1199.0px 1202 | 1200.0px 1203 | 1201.0px 1204 | 1202.0px 1205 | 1203.0px 1206 | 1204.0px 1207 | 1205.0px 1208 | 1206.0px 1209 | 1207.0px 1210 | 1208.0px 1211 | 1209.0px 1212 | 1210.0px 1213 | 1211.0px 1214 | 1212.0px 1215 | 1213.0px 1216 | 1214.0px 1217 | 1215.0px 1218 | 1216.0px 1219 | 1217.0px 1220 | 1218.0px 1221 | 1219.0px 1222 | 1220.0px 1223 | 1221.0px 1224 | 1222.0px 1225 | 1223.0px 1226 | 1224.0px 1227 | 1225.0px 1228 | 1226.0px 1229 | 1227.0px 1230 | 1228.0px 1231 | 1229.0px 1232 | 1230.0px 1233 | 1231.0px 1234 | 1232.0px 1235 | 1233.0px 1236 | 1234.0px 1237 | 1235.0px 1238 | 1236.0px 1239 | 1237.0px 1240 | 1238.0px 1241 | 1239.0px 1242 | 1240.0px 1243 | 1241.0px 1244 | 1242.0px 1245 | 1243.0px 1246 | 1244.0px 1247 | 1245.0px 1248 | 1246.0px 1249 | 1247.0px 1250 | 1248.0px 1251 | 1249.0px 1252 | 1250.0px 1253 | 1251.0px 1254 | 1252.0px 1255 | 1253.0px 1256 | 1254.0px 1257 | 1255.0px 1258 | 1256.0px 1259 | 1257.0px 1260 | 1258.0px 1261 | 1259.0px 1262 | 1260.0px 1263 | 1261.0px 1264 | 1262.0px 1265 | 1263.0px 1266 | 1264.0px 1267 | 1265.0px 1268 | 1266.0px 1269 | 1267.0px 1270 | 1268.0px 1271 | 1269.0px 1272 | 1270.0px 1273 | 1271.0px 1274 | 1272.0px 1275 | 1273.0px 1276 | 1274.0px 1277 | 1275.0px 1278 | 1276.0px 1279 | 1277.0px 1280 | 1278.0px 1281 | 1279.0px 1282 | 1280.0px 1283 | 1281.0px 1284 | 1282.0px 1285 | 1283.0px 1286 | 1284.0px 1287 | 1285.0px 1288 | 1286.0px 1289 | 1287.0px 1290 | 1288.0px 1291 | 1289.0px 1292 | 1290.0px 1293 | 1291.0px 1294 | 1292.0px 1295 | 1293.0px 1296 | 1294.0px 1297 | 1295.0px 1298 | 1296.0px 1299 | 1297.0px 1300 | 1298.0px 1301 | 1299.0px 1302 | 1300.0px 1303 | 1301.0px 1304 | 1302.0px 1305 | 1303.0px 1306 | 1304.0px 1307 | 1305.0px 1308 | 1306.0px 1309 | 1307.0px 1310 | 1308.0px 1311 | 1309.0px 1312 | 1310.0px 1313 | 1311.0px 1314 | 1312.0px 1315 | 1313.0px 1316 | 1314.0px 1317 | 1315.0px 1318 | 1316.0px 1319 | 1317.0px 1320 | 1318.0px 1321 | 1319.0px 1322 | 1320.0px 1323 | 1321.0px 1324 | 1322.0px 1325 | 1323.0px 1326 | 1324.0px 1327 | 1325.0px 1328 | 1326.0px 1329 | 1327.0px 1330 | 1328.0px 1331 | 1329.0px 1332 | 1330.0px 1333 | 1331.0px 1334 | 1332.0px 1335 | 1333.0px 1336 | 1334.0px 1337 | 1335.0px 1338 | 1336.0px 1339 | 1337.0px 1340 | 1338.0px 1341 | 1339.0px 1342 | 1340.0px 1343 | 1341.0px 1344 | 1342.0px 1345 | 1343.0px 1346 | 1344.0px 1347 | 1345.0px 1348 | 1346.0px 1349 | 1347.0px 1350 | 1348.0px 1351 | 1349.0px 1352 | 1350.0px 1353 | 1351.0px 1354 | 1352.0px 1355 | 1353.0px 1356 | 1354.0px 1357 | 1355.0px 1358 | 1356.0px 1359 | 1357.0px 1360 | 1358.0px 1361 | 1359.0px 1362 | 1360.0px 1363 | 1361.0px 1364 | 1362.0px 1365 | 1363.0px 1366 | 1364.0px 1367 | 1365.0px 1368 | 1366.0px 1369 | 1367.0px 1370 | 1368.0px 1371 | 1369.0px 1372 | 1370.0px 1373 | 1371.0px 1374 | 1372.0px 1375 | 1373.0px 1376 | 1374.0px 1377 | 1375.0px 1378 | 1376.0px 1379 | 1377.0px 1380 | 1378.0px 1381 | 1379.0px 1382 | 1380.0px 1383 | 1381.0px 1384 | 1382.0px 1385 | 1383.0px 1386 | 1384.0px 1387 | 1385.0px 1388 | 1386.0px 1389 | 1387.0px 1390 | 1388.0px 1391 | 1389.0px 1392 | 1390.0px 1393 | 1391.0px 1394 | 1392.0px 1395 | 1393.0px 1396 | 1394.0px 1397 | 1395.0px 1398 | 1396.0px 1399 | 1397.0px 1400 | 1398.0px 1401 | 1399.0px 1402 | 1400.0px 1403 | 1401.0px 1404 | 1402.0px 1405 | 1403.0px 1406 | 1404.0px 1407 | 1405.0px 1408 | 1406.0px 1409 | 1407.0px 1410 | 1408.0px 1411 | 1409.0px 1412 | 1410.0px 1413 | 1411.0px 1414 | 1412.0px 1415 | 1413.0px 1416 | 1414.0px 1417 | 1415.0px 1418 | 1416.0px 1419 | 1417.0px 1420 | 1418.0px 1421 | 1419.0px 1422 | 1420.0px 1423 | 1421.0px 1424 | 1422.0px 1425 | 1423.0px 1426 | 1424.0px 1427 | 1425.0px 1428 | 1426.0px 1429 | 1427.0px 1430 | 1428.0px 1431 | 1429.0px 1432 | 1430.0px 1433 | 1431.0px 1434 | 1432.0px 1435 | 1433.0px 1436 | 1434.0px 1437 | 1435.0px 1438 | 1436.0px 1439 | 1437.0px 1440 | 1438.0px 1441 | 1439.0px 1442 | 1440.0px 1443 | 1441.0px 1444 | 1442.0px 1445 | 1443.0px 1446 | 1444.0px 1447 | 1445.0px 1448 | 1446.0px 1449 | 1447.0px 1450 | 1448.0px 1451 | 1449.0px 1452 | 1450.0px 1453 | 1451.0px 1454 | 1452.0px 1455 | 1453.0px 1456 | 1454.0px 1457 | 1455.0px 1458 | 1456.0px 1459 | 1457.0px 1460 | 1458.0px 1461 | 1459.0px 1462 | 1460.0px 1463 | 1461.0px 1464 | 1462.0px 1465 | 1463.0px 1466 | 1464.0px 1467 | 1465.0px 1468 | 1466.0px 1469 | 1467.0px 1470 | 1468.0px 1471 | 1469.0px 1472 | 1470.0px 1473 | 1471.0px 1474 | 1472.0px 1475 | 1473.0px 1476 | 1474.0px 1477 | 1475.0px 1478 | 1476.0px 1479 | 1477.0px 1480 | 1478.0px 1481 | 1479.0px 1482 | 1480.0px 1483 | 1481.0px 1484 | 1482.0px 1485 | 1483.0px 1486 | 1484.0px 1487 | 1485.0px 1488 | 1486.0px 1489 | 1487.0px 1490 | 1488.0px 1491 | 1489.0px 1492 | 1490.0px 1493 | 1491.0px 1494 | 1492.0px 1495 | 1493.0px 1496 | 1494.0px 1497 | 1495.0px 1498 | 1496.0px 1499 | 1497.0px 1500 | 1498.0px 1501 | 1499.0px 1502 | 1500.0px 1503 | 1501.0px 1504 | 1502.0px 1505 | 1503.0px 1506 | 1504.0px 1507 | 1505.0px 1508 | 1506.0px 1509 | 1507.0px 1510 | 1508.0px 1511 | 1509.0px 1512 | 1510.0px 1513 | 1511.0px 1514 | 1512.0px 1515 | 1513.0px 1516 | 1514.0px 1517 | 1515.0px 1518 | 1516.0px 1519 | 1517.0px 1520 | 1518.0px 1521 | 1519.0px 1522 | 1520.0px 1523 | 1521.0px 1524 | 1522.0px 1525 | 1523.0px 1526 | 1524.0px 1527 | 1525.0px 1528 | 1526.0px 1529 | 1527.0px 1530 | 1528.0px 1531 | 1529.0px 1532 | 1530.0px 1533 | 1531.0px 1534 | 1532.0px 1535 | 1533.0px 1536 | 1534.0px 1537 | 1535.0px 1538 | 1536.0px 1539 | 1537.0px 1540 | 1538.0px 1541 | 1539.0px 1542 | 1540.0px 1543 | 1541.0px 1544 | 1542.0px 1545 | 1543.0px 1546 | 1544.0px 1547 | 1545.0px 1548 | 1546.0px 1549 | 1547.0px 1550 | 1548.0px 1551 | 1549.0px 1552 | 1550.0px 1553 | 1551.0px 1554 | 1552.0px 1555 | 1553.0px 1556 | 1554.0px 1557 | 1555.0px 1558 | 1556.0px 1559 | 1557.0px 1560 | 1558.0px 1561 | 1559.0px 1562 | 1560.0px 1563 | 1561.0px 1564 | 1562.0px 1565 | 1563.0px 1566 | 1564.0px 1567 | 1565.0px 1568 | 1566.0px 1569 | 1567.0px 1570 | 1568.0px 1571 | 1569.0px 1572 | 1570.0px 1573 | 1571.0px 1574 | 1572.0px 1575 | 1573.0px 1576 | 1574.0px 1577 | 1575.0px 1578 | 1576.0px 1579 | 1577.0px 1580 | 1578.0px 1581 | 1579.0px 1582 | 1580.0px 1583 | 1581.0px 1584 | 1582.0px 1585 | 1583.0px 1586 | 1584.0px 1587 | 1585.0px 1588 | 1586.0px 1589 | 1587.0px 1590 | 1588.0px 1591 | 1589.0px 1592 | 1590.0px 1593 | 1591.0px 1594 | 1592.0px 1595 | 1593.0px 1596 | 1594.0px 1597 | 1595.0px 1598 | 1596.0px 1599 | 1597.0px 1600 | 1598.0px 1601 | 1599.0px 1602 | 1600.0px 1603 | 1601.0px 1604 | 1602.0px 1605 | 1603.0px 1606 | 1604.0px 1607 | 1605.0px 1608 | 1606.0px 1609 | 1607.0px 1610 | 1608.0px 1611 | 1609.0px 1612 | 1610.0px 1613 | 1611.0px 1614 | 1612.0px 1615 | 1613.0px 1616 | 1614.0px 1617 | 1615.0px 1618 | 1616.0px 1619 | 1617.0px 1620 | 1618.0px 1621 | 1619.0px 1622 | 1620.0px 1623 | 1621.0px 1624 | 1622.0px 1625 | 1623.0px 1626 | 1624.0px 1627 | 1625.0px 1628 | 1626.0px 1629 | 1627.0px 1630 | 1628.0px 1631 | 1629.0px 1632 | 1630.0px 1633 | 1631.0px 1634 | 1632.0px 1635 | 1633.0px 1636 | 1634.0px 1637 | 1635.0px 1638 | 1636.0px 1639 | 1637.0px 1640 | 1638.0px 1641 | 1639.0px 1642 | 1640.0px 1643 | 1641.0px 1644 | 1642.0px 1645 | 1643.0px 1646 | 1644.0px 1647 | 1645.0px 1648 | 1646.0px 1649 | 1647.0px 1650 | 1648.0px 1651 | 1649.0px 1652 | 1650.0px 1653 | 1651.0px 1654 | 1652.0px 1655 | 1653.0px 1656 | 1654.0px 1657 | 1655.0px 1658 | 1656.0px 1659 | 1657.0px 1660 | 1658.0px 1661 | 1659.0px 1662 | 1660.0px 1663 | 1661.0px 1664 | 1662.0px 1665 | 1663.0px 1666 | 1664.0px 1667 | 1665.0px 1668 | 1666.0px 1669 | 1667.0px 1670 | 1668.0px 1671 | 1669.0px 1672 | 1670.0px 1673 | 1671.0px 1674 | 1672.0px 1675 | 1673.0px 1676 | 1674.0px 1677 | 1675.0px 1678 | 1676.0px 1679 | 1677.0px 1680 | 1678.0px 1681 | 1679.0px 1682 | 1680.0px 1683 | 1681.0px 1684 | 1682.0px 1685 | 1683.0px 1686 | 1684.0px 1687 | 1685.0px 1688 | 1686.0px 1689 | 1687.0px 1690 | 1688.0px 1691 | 1689.0px 1692 | 1690.0px 1693 | 1691.0px 1694 | 1692.0px 1695 | 1693.0px 1696 | 1694.0px 1697 | 1695.0px 1698 | 1696.0px 1699 | 1697.0px 1700 | 1698.0px 1701 | 1699.0px 1702 | 1700.0px 1703 | 1701.0px 1704 | 1702.0px 1705 | 1703.0px 1706 | 1704.0px 1707 | 1705.0px 1708 | 1706.0px 1709 | 1707.0px 1710 | 1708.0px 1711 | 1709.0px 1712 | 1710.0px 1713 | 1711.0px 1714 | 1712.0px 1715 | 1713.0px 1716 | 1714.0px 1717 | 1715.0px 1718 | 1716.0px 1719 | 1717.0px 1720 | 1718.0px 1721 | 1719.0px 1722 | 1720.0px 1723 | 1721.0px 1724 | 1722.0px 1725 | 1723.0px 1726 | 1724.0px 1727 | 1725.0px 1728 | 1726.0px 1729 | 1727.0px 1730 | 1728.0px 1731 | 1729.0px 1732 | 1730.0px 1733 | 1731.0px 1734 | 1732.0px 1735 | 1733.0px 1736 | 1734.0px 1737 | 1735.0px 1738 | 1736.0px 1739 | 1737.0px 1740 | 1738.0px 1741 | 1739.0px 1742 | 1740.0px 1743 | 1741.0px 1744 | 1742.0px 1745 | 1743.0px 1746 | 1744.0px 1747 | 1745.0px 1748 | 1746.0px 1749 | 1747.0px 1750 | 1748.0px 1751 | 1749.0px 1752 | 1750.0px 1753 | 1751.0px 1754 | 1752.0px 1755 | 1753.0px 1756 | 1754.0px 1757 | 1755.0px 1758 | 1756.0px 1759 | 1757.0px 1760 | 1758.0px 1761 | 1759.0px 1762 | 1760.0px 1763 | 1761.0px 1764 | 1762.0px 1765 | 1763.0px 1766 | 1764.0px 1767 | 1765.0px 1768 | 1766.0px 1769 | 1767.0px 1770 | 1768.0px 1771 | 1769.0px 1772 | 1770.0px 1773 | 1771.0px 1774 | 1772.0px 1775 | 1773.0px 1776 | 1774.0px 1777 | 1775.0px 1778 | 1776.0px 1779 | 1777.0px 1780 | 1778.0px 1781 | 1779.0px 1782 | 1780.0px 1783 | 1781.0px 1784 | 1782.0px 1785 | 1783.0px 1786 | 1784.0px 1787 | 1785.0px 1788 | 1786.0px 1789 | 1787.0px 1790 | 1788.0px 1791 | 1789.0px 1792 | 1790.0px 1793 | 1791.0px 1794 | 1792.0px 1795 | 1793.0px 1796 | 1794.0px 1797 | 1795.0px 1798 | 1796.0px 1799 | 1797.0px 1800 | 1798.0px 1801 | 1799.0px 1802 | 1800.0px 1803 | 1801.0px 1804 | 1802.0px 1805 | 1803.0px 1806 | 1804.0px 1807 | 1805.0px 1808 | 1806.0px 1809 | 1807.0px 1810 | 1808.0px 1811 | 1809.0px 1812 | 1810.0px 1813 | 1811.0px 1814 | 1812.0px 1815 | 1813.0px 1816 | 1814.0px 1817 | 1815.0px 1818 | 1816.0px 1819 | 1817.0px 1820 | 1818.0px 1821 | 1819.0px 1822 | 1820.0px 1823 | 1821.0px 1824 | 1822.0px 1825 | 1823.0px 1826 | 1824.0px 1827 | 1825.0px 1828 | 1826.0px 1829 | 1827.0px 1830 | 1828.0px 1831 | 1829.0px 1832 | 1830.0px 1833 | 1831.0px 1834 | 1832.0px 1835 | 1833.0px 1836 | 1834.0px 1837 | 1835.0px 1838 | 1836.0px 1839 | 1837.0px 1840 | 1838.0px 1841 | 1839.0px 1842 | 1840.0px 1843 | 1841.0px 1844 | 1842.0px 1845 | 1843.0px 1846 | 1844.0px 1847 | 1845.0px 1848 | 1846.0px 1849 | 1847.0px 1850 | 1848.0px 1851 | 1849.0px 1852 | 1850.0px 1853 | 1851.0px 1854 | 1852.0px 1855 | 1853.0px 1856 | 1854.0px 1857 | 1855.0px 1858 | 1856.0px 1859 | 1857.0px 1860 | 1858.0px 1861 | 1859.0px 1862 | 1860.0px 1863 | 1861.0px 1864 | 1862.0px 1865 | 1863.0px 1866 | 1864.0px 1867 | 1865.0px 1868 | 1866.0px 1869 | 1867.0px 1870 | 1868.0px 1871 | 1869.0px 1872 | 1870.0px 1873 | 1871.0px 1874 | 1872.0px 1875 | 1873.0px 1876 | 1874.0px 1877 | 1875.0px 1878 | 1876.0px 1879 | 1877.0px 1880 | 1878.0px 1881 | 1879.0px 1882 | 1880.0px 1883 | 1881.0px 1884 | 1882.0px 1885 | 1883.0px 1886 | 1884.0px 1887 | 1885.0px 1888 | 1886.0px 1889 | 1887.0px 1890 | 1888.0px 1891 | 1889.0px 1892 | 1890.0px 1893 | 1891.0px 1894 | 1892.0px 1895 | 1893.0px 1896 | 1894.0px 1897 | 1895.0px 1898 | 1896.0px 1899 | 1897.0px 1900 | 1898.0px 1901 | 1899.0px 1902 | 1900.0px 1903 | 1901.0px 1904 | 1902.0px 1905 | 1903.0px 1906 | 1904.0px 1907 | 1905.0px 1908 | 1906.0px 1909 | 1907.0px 1910 | 1908.0px 1911 | 1909.0px 1912 | 1910.0px 1913 | 1911.0px 1914 | 1912.0px 1915 | 1913.0px 1916 | 1914.0px 1917 | 1915.0px 1918 | 1916.0px 1919 | 1917.0px 1920 | 1918.0px 1921 | 1919.0px 1922 | 1920.0px 1923 | 1924 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TV输入法 5 | 6 | 去往 7 | 发送 8 | 下一个 9 | 完成 10 | 回车 11 | 12 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values/bool.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #00000000 5 | #FFFFFF 6 | #FFFFF0 7 | #FFFFE0 8 | #FFFF00 9 | #FFFAFA 10 | #FFFAF0 11 | #FFFACD 12 | #FFF8DC 13 | #FFF5EE 14 | #FFF0F5 15 | #FFEFD5 16 | #FFEBCD 17 | #FFE4E1 18 | #FFE4C4 19 | #FFE4B5 20 | #FFDEAD 21 | #FFDAB9 22 | #FFD700 23 | #FFC0CB 24 | #FFB6C1 25 | #FFA500 26 | #FFA07A 27 | #FF8C00 28 | #FF7F50 29 | #FF69B4 30 | #FF6347 31 | #FF4500 32 | #FF1493 33 | #FF00FF 34 | #FF0000 35 | #FDF5E6 36 | #FAFAD2 37 | #FAF0E6 38 | #FAEBD7 39 | #FA8072 40 | #F8F8FF 41 | #F5FFFA 42 | #F5F5F5 43 | #F5F5DC 44 | #F5DEB3 45 | #F4A460 46 | #F0FFFF 47 | #F0FFF0 48 | #F0F8FF 49 | #F0E68C 50 | #F08080 51 | #EEE8AA 52 | #EE82EE 53 | #E9967A 54 | #E6E6FA 55 | #E0FFFF 56 | #DEB887 57 | #DDA0DD 58 | #DCDCDC 59 | #DC143C 60 | #DB7093 61 | #DAA520 62 | #DA70D6 63 | #D8BFD8 64 | #D3D3D3 65 | #D2B48C 66 | #D2691E 67 | #CD853F 68 | #CD5C5C 69 | #C71585 70 | #C0C0C0 71 | #BDB76B 72 | #BC8F8F 73 | #BA55D3 74 | #B8860B 75 | #B22222 76 | #B0E0E6 77 | #B0C4DE 78 | #AFEEEE 79 | #ADFF2F 80 | #ADD8E6 81 | #A9A9A9 82 | #A52A2A 83 | #A0522D 84 | #9932CC 85 | #98FB98 86 | #9400D3 87 | #9370DB 88 | #90EE90 89 | #8FBC8F 90 | #8B4513 91 | #8B008B 92 | #8B0000 93 | #8A2BE2 94 | #87CEFA 95 | #87CEEB 96 | #808080 97 | #808000 98 | #800080 99 | #800000 100 | #7FFFD4 101 | #7FFF00 102 | #7CFC00 103 | #7B68EE 104 | #778899 105 | #708090 106 | #6B8E23 107 | #6A5ACD 108 | #696969 109 | #66CDAA 110 | #6495ED 111 | #5F9EA0 112 | #556B2F 113 | #4B0082 114 | #48D1CC 115 | #483D8B 116 | #4682B4 117 | #4169E1 118 | #40E0D0 119 | #3CB371 120 | #32CD32 121 | #2F4F4F 122 | #2E8B57 123 | #228B22 124 | #20B2AA 125 | #1E90FF 126 | #191970 127 | #00FFFF 128 | #00FFFF 129 | #00FF7F 130 | #00FF00 131 | #00FA9A 132 | #00CED1 133 | #00BFFF 134 | #008B8B 135 | #008080 136 | #008000 137 | #006400 138 | #0000FF 139 | #0000CD 140 | #00008B 141 | #000080 142 | #000000 143 | #99cc33 144 | #cccccc 145 | #8f8f8f 146 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | TVInputMethod 4 | 5 | 6 | -1 7 | 2 8 | 3 9 | 10 | -100 11 | 101 12 | 102 13 | 14 | 15 | -3 16 | -4 17 | -5 18 | 19 | 62 20 | 66 21 | 4 22 | 21 23 | 22 24 | 67 25 | 26 | 27 | 7 28 | 8 29 | 9 30 | 10 31 | 11 32 | 12 33 | 34 | Go 35 | Send 36 | Next 37 | Enter 38 | Enter 39 | 40 | 41 | -------------------------------------------------------------------------------- /OpenInputMethod/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /OpenInputMethod/res/xml/method.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /OpenInputMethod/res/xml/sbd_number.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | 19 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 49 | 50 | 51 | 54 | 57 | 58 | 59 | 62 | 65 | 66 | 67 | 70 | 73 | 74 | 75 | 78 | 81 | 82 | 83 | 86 | 89 | 90 | 91 | 94 | 97 | 98 | 99 | 102 | 105 | 106 | 107 | 110 | 113 | 114 | 115 | 118 | 121 | 122 | 123 | 126 | 129 | 130 | 131 | 134 | 137 | 138 | 139 | 144 | 147 | 150 | 153 | 157 | 160 | 163 | 164 | 165 | 166 | 167 | 168 | 172 | 176 | 179 | 180 | 181 | 184 | 188 | 191 | 192 | 195 | 199 | 202 | 203 | 206 | 210 | 213 | 214 | 215 | 218 | 221 | 222 | 223 | 227 | 228 | 229 | 232 | 235 | 236 | 237 | 240 | 243 | 244 | 245 | 248 | 251 | 252 | 253 | 256 | 257 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /OpenInputMethod/res/xml/sbd_qwerty.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 34 | 35 | 36 | 40 | 41 | 44 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 63 | 64 | 67 | 70 | 71 | 75 | 78 | 81 | 84 | 88 | 91 | 94 | 95 | 96 | 97 | 98 | 101 | 105 | 106 | 110 | 111 | 115 | 116 | 119 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /OpenInputMethod/res/xml/skb_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/activity/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.activity; 2 | 3 | import com.open.inputmethod.R; 4 | 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | 8 | /** 9 | * 输入法设置界面. 10 | * 11 | * @author hailong.qiu 356752238@qq.com 12 | * 13 | */ 14 | public class SettingsActivity extends Activity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_settings); 20 | finish(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/InputModeSwitcher.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.open.inputmethod.R; 7 | import com.open.inputmethod.utils.OPENLOG; 8 | 9 | import android.view.inputmethod.EditorInfo; 10 | 11 | /** 12 | * 软键盘类型切换.(英文,数字,符号键盘) 13 | * 14 | * @author hailong.qiu 356752238@qq.com 15 | * 16 | */ 17 | public class InputModeSwitcher { 18 | 19 | private static final String TAG = "InputModeSwitcher"; 20 | 21 | public static final int MAX_TOGGLE_STATES = 4; 22 | 23 | private static final int INPUT_TYPE_ALL_EN = 0; // 全英文键盘. 24 | private static final int INPUT_TYPE_NUMBER = 1; // 数字键盘 25 | private static final int INPUT_TYPE_SYM = 2; // 符号键盘. 26 | 27 | private static final int USERDEF_KEYCODE_CASE_1 = -1; // 大小写. 28 | private static final int MODE_SKB_ENGLISH_UPPER = 3; 29 | private static final int MODE_SKB_ENGLISH_LOWER = 2; 30 | 31 | private static final int USERDEF_KEYCODE_PAGE = -100; // 翻页. 32 | public static final int TOGGLE_KEYCODE_PAGE_1 = 101; 33 | private static final int TOGGLE_KEYCODE_PAGE_2 = 102; 34 | 35 | private static final int MODE_SKB_NUMBER = -3; 36 | private static final int MODE_SKB_ALL_EN = -4; 37 | private static final int MODE_SKB_ALL_SYM = -5; 38 | 39 | private static final int TOGGLE_ENTER_GO = 7; 40 | private static final int TOGGLE_ENTER_SEARCH = 8; 41 | private static final int TOGGLE_ENTER_SEND = 9; 42 | private static final int TOGGLE_ENTER_NEXT = 10; 43 | private static final int TOGGLE_ENTER_DONE = 11; 44 | public static final int TOGGLE_ENTER_MULTI_LINE_DONE = 12; 45 | 46 | private int mInputMode = INPUT_TYPE_ALL_EN; 47 | 48 | public int getInputMode() { 49 | return mInputMode; 50 | } 51 | 52 | /** 53 | * 设置软键盘类型后. 54 | * 55 | * 调用 SkbContainer 的 updateInputMode 56 | */ 57 | public void setInputMode(EditorInfo editorInfo) { 58 | mEditorInfo = editorInfo; 59 | int inputType = editorInfo.inputType & EditorInfo.TYPE_MASK_CLASS; 60 | OPENLOG.D(TAG, "inputType:" + inputType); 61 | switch (inputType) { 62 | case EditorInfo.TYPE_CLASS_NUMBER: 63 | case EditorInfo.TYPE_CLASS_DATETIME: 64 | case EditorInfo.TYPE_CLASS_PHONE: 65 | mInputMode = INPUT_TYPE_NUMBER; 66 | break; 67 | case EditorInfo.TYPE_CLASS_TEXT: 68 | mInputMode = INPUT_TYPE_ALL_EN; 69 | break; 70 | default: 71 | mInputMode = INPUT_TYPE_ALL_EN; 72 | break; 73 | } 74 | // 75 | prepareToggleStates(null); 76 | } 77 | 78 | // 获取键盘布局类型. 79 | public int getSkbLayout() { 80 | int layout = (mInputMode); 81 | switch (layout) { 82 | case INPUT_TYPE_ALL_EN: // 全英文. 83 | return R.xml.sbd_qwerty; 84 | case INPUT_TYPE_NUMBER: // 数字键盘 85 | return R.xml.sbd_number; 86 | case INPUT_TYPE_SYM: // 五笔 87 | return R.xml.sbd_qwerty; 88 | default: 89 | return R.xml.sbd_qwerty; 90 | } 91 | } 92 | 93 | /** 94 | * 自定义按键,比如 大小写转换等等. 自定义按键都必须小于0. 95 | */ 96 | public void switchModeForUserKey(SoftKey userKey) { 97 | prepareToggleStates(userKey); // 初始化状态切换值. 98 | } 99 | 100 | private ToggleStates mToggleStates = new ToggleStates(); 101 | private EditorInfo mEditorInfo; 102 | 103 | /* 104 | * 状态切换初始化. 105 | */ 106 | public void prepareToggleStates(SoftKey softKey) { 107 | int userKeyCode = (softKey != null) ? softKey.getKeyCode() : 0; 108 | // 防止数字键盘切换,上次的状态被清掉了. 109 | if (!mToggleStates.mSwitchSkb) 110 | mToggleStates.mKeyStates.clear(); 111 | List mKeyStates = mToggleStates.mKeyStates; 112 | 113 | if (mToggleStates.mQwerty && (mInputMode == INPUT_TYPE_ALL_EN) && (userKeyCode == 0)) { // 初始化英文键盘大小写. 114 | mKeyStates.add(mToggleStates.mQwertyUpperCase ? MODE_SKB_ENGLISH_UPPER : MODE_SKB_ENGLISH_LOWER); 115 | } else if ((mToggleStates.mQwerty && USERDEF_KEYCODE_CASE_1 == userKeyCode)) { // 大小写转换. 116 | mToggleStates.mQwertyUpperCase = !mToggleStates.mQwertyUpperCase; 117 | mKeyStates.add(mToggleStates.mQwertyUpperCase ? MODE_SKB_ENGLISH_UPPER : MODE_SKB_ENGLISH_LOWER); 118 | } else if (USERDEF_KEYCODE_PAGE == userKeyCode) { // 翻页. 119 | if (mToggleStates.mPageState == TOGGLE_KEYCODE_PAGE_1) { 120 | mToggleStates.mPageState = TOGGLE_KEYCODE_PAGE_2; 121 | } else { 122 | mToggleStates.mPageState = TOGGLE_KEYCODE_PAGE_1; 123 | } 124 | mKeyStates.add(mToggleStates.mPageState); 125 | } else if (MODE_SKB_NUMBER == userKeyCode) { // 切换到数字键盘. 126 | if (mInputMode == INPUT_TYPE_ALL_EN) 127 | mKeyStates.add(MODE_SKB_ALL_EN); // 状态(返回) 128 | mInputMode = INPUT_TYPE_NUMBER; 129 | mToggleStates.mSwitchSkb = true; 130 | } else if (MODE_SKB_ALL_EN == userKeyCode) { // 英文键盘. 131 | mInputMode = INPUT_TYPE_ALL_EN; 132 | } 133 | 134 | // 回车的状态处理. 135 | int action = mEditorInfo.imeOptions & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); 136 | OPENLOG.D(TAG, "prepareToggleStates action:" + action); 137 | switch (action) { 138 | case EditorInfo.IME_ACTION_GO: 139 | mKeyStates.add(TOGGLE_ENTER_GO); 140 | break; 141 | case EditorInfo.IME_ACTION_SEARCH: 142 | mKeyStates.add(TOGGLE_ENTER_SEARCH); 143 | break; 144 | case EditorInfo.IME_ACTION_SEND: 145 | mKeyStates.add(TOGGLE_ENTER_SEND); 146 | break; 147 | case EditorInfo.IME_ACTION_NEXT: 148 | int f = mEditorInfo.inputType & EditorInfo.TYPE_MASK_FLAGS; 149 | if (!isCenterMultiLine()) { 150 | mKeyStates.add(TOGGLE_ENTER_NEXT); 151 | } else { 152 | mKeyStates.add(TOGGLE_ENTER_MULTI_LINE_DONE); 153 | } 154 | break; 155 | case EditorInfo.IME_ACTION_DONE: 156 | if (!isCenterMultiLine()) { 157 | mKeyStates.add(TOGGLE_ENTER_DONE); 158 | } else { 159 | mKeyStates.add(TOGGLE_ENTER_MULTI_LINE_DONE); 160 | } 161 | default: // 暂时定为多行. 162 | mKeyStates.add(TOGGLE_ENTER_MULTI_LINE_DONE); 163 | break; 164 | } 165 | } 166 | 167 | private boolean isCenterMultiLine() { 168 | int f = mEditorInfo.inputType & EditorInfo.TYPE_MASK_FLAGS; 169 | return (f == EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); 170 | } 171 | 172 | public ToggleStates getToggleStates() { 173 | return mToggleStates; 174 | } 175 | 176 | class ToggleStates { 177 | public int mPageState = TOGGLE_KEYCODE_PAGE_1; 178 | public boolean mSwitchSkb; 179 | public boolean mQwerty; 180 | public boolean mQwertyUpperCase; 181 | public List mKeyStates = new ArrayList(); 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/KeyRow.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 按键的列数组. 8 | * 9 | * @author hailong.qiu 356752238@qq.com 10 | * 11 | */ 12 | public class KeyRow { 13 | 14 | private List mSoftKeys = new ArrayList(); 15 | 16 | public List getSoftKeys() { 17 | return mSoftKeys; 18 | } 19 | 20 | public void setSoftKeys(List mSoftKeys) { 21 | this.mSoftKeys = mSoftKeys; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SaveKeyEvent.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | /** 4 | * 保存了KEYEVENT.KEYCODE_ 的一些按键 CODE. 5 | */ 6 | public class SaveKeyEvent { 7 | /* 8 | KEYCODE_UNKNOWN=0; 9 | KEYCODE_SOFT_LEFT=1; 10 | KEYCODE_SOFT_RIGHT=2; 11 | KEYCODE_HOME=3; 12 | KEYCODE_BACK=4; 13 | KEYCODE_CALL=5; 14 | KEYCODE_ENDCALL=6; 15 | KEYCODE_0=7; 16 | KEYCODE_1=8; 17 | KEYCODE_2=9; 18 | KEYCODE_3=10; 19 | KEYCODE_4=11; 20 | KEYCODE_5=12; 21 | KEYCODE_6=13; 22 | KEYCODE_7=14; 23 | KEYCODE_8=15; 24 | KEYCODE_9=16; 25 | KEYCODE_STAR=17; 26 | KEYCODE_POUND=18; 27 | KEYCODE_DPAD_UP=19; 28 | KEYCODE_DPAD_DOWN=20; 29 | KEYCODE_DPAD_LEFT=21; 30 | KEYCODE_DPAD_RIGHT=22; 31 | KEYCODE_DPAD_CENTER=23; 32 | KEYCODE_VOLUME_UP=24; 33 | KEYCODE_VOLUME_DOWN=25; 34 | KEYCODE_POWER=26; 35 | KEYCODE_CAMERA=27; 36 | KEYCODE_CLEAR=28; 37 | KEYCODE_A=29; 38 | KEYCODE_B=30; 39 | KEYCODE_C=31; 40 | KEYCODE_D=32; 41 | KEYCODE_E=33; 42 | KEYCODE_F=34; 43 | KEYCODE_G=35; 44 | KEYCODE_H=36; 45 | KEYCODE_I=37; 46 | KEYCODE_J=38; 47 | KEYCODE_K=39; 48 | KEYCODE_L=40; 49 | KEYCODE_M=41; 50 | KEYCODE_N=42; 51 | KEYCODE_O=43; 52 | KEYCODE_P=44; 53 | KEYCODE_Q=45; 54 | KEYCODE_R=46; 55 | KEYCODE_S=47; 56 | KEYCODE_T=48; 57 | KEYCODE_U=49; 58 | KEYCODE_V=50; 59 | KEYCODE_W=51; 60 | KEYCODE_X=52; 61 | KEYCODE_Y=53; 62 | KEYCODE_Z=54; 63 | KEYCODE_COMMA=55; 64 | KEYCODE_PERIOD=56; 65 | KEYCODE_ALT_LEFT=57; 66 | KEYCODE_ALT_RIGHT=58; 67 | KEYCODE_SHIFT_LEFT=59; 68 | KEYCODE_SHIFT_RIGHT=60; 69 | KEYCODE_TAB=61; 70 | KEYCODE_SPACE=62; 71 | KEYCODE_SYM=63; 72 | KEYCODE_EXPLORER=64; 73 | KEYCODE_ENVELOPE=65; 74 | KEYCODE_ENTER=66; 75 | KEYCODE_DEL=67; 76 | KEYCODE_GRAVE=68; 77 | KEYCODE_MINUS=69; 78 | KEYCODE_EQUALS=70; 79 | KEYCODE_LEFT_BRACKET=71; 80 | KEYCODE_RIGHT_BRACKET=72; 81 | KEYCODE_BACKSLASH=73; 82 | KEYCODE_SEMICOLON=74; 83 | KEYCODE_APOSTROPHE=75; 84 | KEYCODE_SLASH=76; 85 | KEYCODE_AT=77; 86 | KEYCODE_NUM=78; 87 | KEYCODE_HEADSETHOOK=79; 88 | KEYCODE_FOCUS=80;//*Camera*focus 89 | KEYCODE_PLUS=81; 90 | KEYCODE_MENU=82; 91 | KEYCODE_NOTIFICATION=83; 92 | KEYCODE_SEARCH=84; 93 | KEYCODE_MEDIA_PLAY_PAUSE=85; 94 | KEYCODE_MEDIA_STOP=86; 95 | KEYCODE_MEDIA_NEXT=87; 96 | KEYCODE_MEDIA_PREVIOUS=88; 97 | KEYCODE_MEDIA_REWIND=89; 98 | KEYCODE_MEDIA_FAST_FORWARD=90; 99 | KEYCODE_MUTE=91 100 | */ 101 | } 102 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SkbContainer.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import com.open.inputmethod.R; 4 | import com.open.inputmethod.service.IMEService; 5 | import com.open.inputmethod.utils.MeasureHelper; 6 | import com.open.inputmethod.utils.OPENLOG; 7 | 8 | import android.content.Context; 9 | import android.os.Handler; 10 | import android.os.Message; 11 | import android.util.AttributeSet; 12 | import android.view.KeyEvent; 13 | import android.view.MotionEvent; 14 | import android.view.View; 15 | import android.widget.RelativeLayout; 16 | 17 | /** 18 | * 软键盘主容器. 19 | * 20 | * @author hailong.qiu 356752238@qq.com 21 | * 22 | */ 23 | public class SkbContainer extends RelativeLayout { 24 | 25 | private static final String TAG = "SkbContainer"; 26 | 27 | public SkbContainer(Context context) { 28 | super(context); 29 | init(context, null); 30 | } 31 | 32 | public SkbContainer(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | init(context, attrs); 35 | } 36 | 37 | public SkbContainer(Context context, AttributeSet attrs, int defStyle) { 38 | super(context, attrs, defStyle); 39 | init(context, attrs); 40 | } 41 | 42 | private InputModeSwitcher mInputModeSwitcher; 43 | private SoftKeyboardView mSoftKeyboardView; // 主要的子软键盘. 44 | private SoftKeyboardView mPopupKeyboardView; // 弹出的软键盘. 45 | private int mSkbLayout; 46 | private Context mContext; 47 | private IMEService mService; 48 | 49 | /** 50 | * 初始化. 51 | */ 52 | private void init(Context context, AttributeSet attrs) { 53 | this.mContext = context; 54 | View.inflate(context, R.layout.softkey_layout_view, this); 55 | } 56 | 57 | public void setInputModeSwitcher(InputModeSwitcher imSwitch) { 58 | mInputModeSwitcher = imSwitch; 59 | } 60 | 61 | /** 62 | */ 63 | public void setService(IMEService service) { 64 | mService = service; 65 | } 66 | 67 | /** 68 | * 更新软键盘类型. 69 | */ 70 | public void updateSoftKeyboardType() { 71 | 72 | } 73 | 74 | public void updateInputMode(SoftKey softKey) { 75 | int skbLayout = mInputModeSwitcher.getSkbLayout(); // 输入类型转换出布局XML id. 76 | // 重新加载布局(前提是不能喝前一个布局一样) 77 | if (mSkbLayout != skbLayout) { 78 | mSkbLayout = skbLayout; 79 | updateSkbLayout(); // 更新软键盘布局. 80 | requestLayout(); // 重新加载软键盘高度. 81 | setDefualtSelectKey(0, 0); // 设置默认选中的按键. 82 | } 83 | 84 | // 85 | if (mSoftKeyboardView != null) { 86 | SoftKeyboard skb = mSoftKeyboardView.getSoftKeyboard(); 87 | if (null == skb) 88 | return; 89 | // 初始化状态. 90 | skb.enableToggleStates(mInputModeSwitcher.getToggleStates(), softKey); 91 | /** 92 | * 清空原先的键盘缓存.
93 | * 比如 回车改变了状态.(onstartinputView触发)
94 | */ 95 | mSoftKeyboardView.clearCacheBitmap(); 96 | } 97 | } 98 | 99 | private void updateSkbLayout() { 100 | SkbPool skbPool = SkbPool.getInstance(); 101 | SoftKeyboard softKeyboard = null; // XML中读取保存的键值. 102 | switch (mSkbLayout) { 103 | case R.xml.sbd_qwerty: // 全英文键盘. 104 | softKeyboard = skbPool.getSoftKeyboard(mContext, R.xml.sbd_qwerty); 105 | break; 106 | case R.xml.sbd_number: // 数字键盘. 107 | softKeyboard = skbPool.getSoftKeyboard(mContext, R.xml.sbd_number); 108 | break; 109 | default: 110 | softKeyboard = skbPool.getSoftKeyboard(mContext, R.xml.sbd_qwerty); 111 | break; 112 | } 113 | // 键盘的值.(英文键盘,大小写标志位) 114 | mInputModeSwitcher.getToggleStates().mQwertyUpperCase = softKeyboard.isQwertyUpperCase(); 115 | mInputModeSwitcher.getToggleStates().mQwerty = softKeyboard.isQwerty(); 116 | mInputModeSwitcher.getToggleStates().mPageState = InputModeSwitcher.TOGGLE_KEYCODE_PAGE_1; 117 | // 这样可以用于切换.(反位) 118 | softKeyboard.setQwertyUpperCase(!softKeyboard.isQwertyUpperCase()); 119 | // 更新状态切换. 120 | mInputModeSwitcher.prepareToggleStates(null); 121 | // 122 | mSoftKeyboardView = (SoftKeyboardView) findViewById(R.id.softKeyboardView); 123 | // 重新绘制 软键盘. 124 | mSoftKeyboardView.setSoftKeyboard(softKeyboard); 125 | mInputModeSwitcher.getToggleStates().mSwitchSkb = false; 126 | } 127 | 128 | SoftKeyBoardListener mSoftKeyListener; 129 | 130 | public void setOnSoftKeyBoardListener(SoftKeyBoardListener cb) { 131 | mSoftKeyListener = cb; 132 | } 133 | 134 | public void setDefualtSelectKey(int row, int index) { 135 | if (mSoftKeyboardView != null) { 136 | SoftKeyboard softKeyboard = mSoftKeyboardView.getSoftKeyboard(); 137 | if (softKeyboard != null) 138 | softKeyboard.setOneKeySelected(row, index); 139 | } 140 | } 141 | 142 | /** 143 | * 按下按键的处理. 144 | */ 145 | private boolean setKeyCodeEnter(SoftKey softKey) { 146 | if (softKey == null) { 147 | OPENLOG.E(TAG, "setKeyCodeEnter softKey is null"); 148 | return true; 149 | } 150 | // 151 | int softKeyCode = softKey.getKeyCode(); 152 | /** 153 | * 自定义按键,比如大/小写转换, 键盘切换等等.
154 | * keyCode <= -1
155 | */ 156 | if (softKey.isUserDefKey()) { 157 | OPENLOG.D(TAG, "setKeyCodeEnter isUserKey keyCode:" + softKeyCode); 158 | mInputModeSwitcher.switchModeForUserKey(softKey); 159 | updateInputMode(softKey); // 大/小 写切换. 160 | return true; 161 | } 162 | /* 163 | * 判断是否为 A 至 Z 的字母. 164 | */ 165 | if ((softKeyCode >= KeyEvent.KEYCODE_A && softKeyCode <= KeyEvent.KEYCODE_Z) 166 | || (softKeyCode >= KeyEvent.KEYCODE_0 && softKeyCode <= KeyEvent.KEYCODE_9)) { 167 | String label = softKey.getKeyLabel(); 168 | mService.commitResultText(label); 169 | return true; 170 | } 171 | /* 172 | * 处理按键的删除,回车,空格.
光标移动. 返回. 173 | */ 174 | switch (softKeyCode) { 175 | case KeyEvent.KEYCODE_DEL: // 删除 67 176 | mService.getCurrentInputConnection().deleteSurroundingText(1, 0); 177 | break; 178 | case KeyEvent.KEYCODE_ENTER: // 回车 66 179 | if ( softKey instanceof ToggleSoftKey) { 180 | ToggleSoftKey toggleSoftKey = (ToggleSoftKey) softKey; 181 | /* 182 | * 多行文本下,只发送'\n',让文本换行. 183 | */ 184 | if (toggleSoftKey.getSaveStateId() == InputModeSwitcher.TOGGLE_ENTER_MULTI_LINE_DONE) { 185 | mService.commitResultText("\n"); 186 | } else { 187 | mService.sendKeyChar('\n'); 188 | } 189 | } 190 | break; 191 | case KeyEvent.KEYCODE_SPACE: // 空格 62 192 | mService.sendKeyChar(' '); 193 | break; 194 | case KeyEvent.KEYCODE_BACK: // 返回 195 | mService.requestHideSelf(0); // 输入法88. 196 | break; 197 | case KeyEvent.KEYCODE_DPAD_LEFT: // 光标向左移动. 198 | mService.setCursorLeftMove(); 199 | break; 200 | case KeyEvent.KEYCODE_DPAD_RIGHT: // 光标向右移动. 201 | mService.setCursorRightMove(); 202 | break; 203 | default: // 测试. 204 | String label = softKey.getKeyLabel(); 205 | mService.commitResultText(label); 206 | break; 207 | } 208 | 209 | if (mSoftKeyListener != null) { 210 | mSoftKeyListener.onCommitText(softKey); 211 | } 212 | 213 | return true; 214 | } 215 | 216 | /** 217 | * 防止输入法被重复退出. 218 | */ 219 | private boolean isBackQuit = false; 220 | 221 | /** 222 | * 处理DOWN事件. 223 | */ 224 | public boolean onSoftKeyDown(int keyCode, KeyEvent event) { 225 | switch (keyCode) { 226 | case KeyEvent.KEYCODE_ENTER: 227 | case KeyEvent.KEYCODE_DPAD_CENTER: 228 | SoftKeyboard softKeyboard = mSoftKeyboardView.getSoftKeyboard(); 229 | SoftKey softKey = softKeyboard.getSelectSoftKey(); 230 | mSoftKeyboardView.setSoftKeyPress(true); 231 | if (softKey.getKeyCode() == KeyEvent.KEYCODE_BACK) 232 | isBackQuit = true; 233 | if (softKey.getKeyCode() != KeyEvent.KEYCODE_BACK && !setKeyCodeEnter(softKey)) { 234 | return false; 235 | } 236 | break; 237 | case KeyEvent.KEYCODE_DEL: // 删除 238 | mService.getCurrentInputConnection().deleteSurroundingText(1, 0); 239 | break; 240 | case KeyEvent.KEYCODE_BACK: // 返回 241 | case KeyEvent.KEYCODE_ESCAPE: // 键盘返回. 242 | return false; 243 | case KeyEvent.KEYCODE_DPAD_LEFT: // 左 244 | case KeyEvent.KEYCODE_DPAD_RIGHT: // 右 245 | case KeyEvent.KEYCODE_DPAD_UP: // 上 246 | case KeyEvent.KEYCODE_DPAD_DOWN: // 下 247 | mSoftKeyboardView.setSoftKeyPress(false); 248 | actionForKeyEvent(keyCode); // 按键移动. 249 | break; 250 | default: 251 | // 处理键盘按键. 252 | return false; 253 | } 254 | return true; 255 | } 256 | 257 | /** 258 | * 处理UP的事件. 259 | */ 260 | public boolean onSoftKeyUp(int keyCode, KeyEvent event) { 261 | if (mSoftKeyboardView != null) 262 | mSoftKeyboardView.setSoftKeyPress(false); 263 | switch (keyCode) { 264 | case KeyEvent.KEYCODE_BACK: 265 | case KeyEvent.KEYCODE_ESCAPE: // 键盘返回. 266 | return false; 267 | case KeyEvent.KEYCODE_ENTER: 268 | case KeyEvent.KEYCODE_DPAD_CENTER: 269 | SoftKeyboard softKeyboard = mSoftKeyboardView.getSoftKeyboard(); 270 | SoftKey softKey = softKeyboard.getSelectSoftKey(); 271 | if (isBackQuit && (softKey.getKeyCode() == KeyEvent.KEYCODE_BACK) && setKeyCodeEnter(softKey)) { 272 | mService.requestHideSelf(0); // 输入法88. 273 | isBackQuit = false; 274 | } 275 | break; 276 | } 277 | return true; 278 | } 279 | 280 | /** 281 | * 根据 上,下,左,右 来绘制按键位置. 282 | */ 283 | public boolean actionForKeyEvent(int direction) { 284 | if (mSoftKeyboardView != null) { 285 | return mSoftKeyboardView.moveToNextKey(direction); 286 | } 287 | return false; 288 | } 289 | 290 | private static final int LOG_PRESS_DELAYMILLIS = 200; 291 | 292 | Handler longPressHandler = new Handler() { 293 | public void handleMessage(Message msg) { 294 | SoftKey downSKey = (SoftKey) msg.obj; 295 | if (downSKey != null) { 296 | setKeyCodeEnter(downSKey); 297 | // 长按按键.(继续发送) 知道松开按键. 298 | Message msg1 = longPressHandler.obtainMessage(); 299 | msg1.obj = downSKey; 300 | longPressHandler.sendMessageDelayed(msg1, LOG_PRESS_DELAYMILLIS); 301 | } 302 | }; 303 | }; 304 | 305 | @Override 306 | public boolean onTouchEvent(MotionEvent event) { 307 | int action = event.getAction(); 308 | int x = (int) event.getX(); 309 | int y = (int) event.getY(); 310 | 311 | switch (action) { 312 | case MotionEvent.ACTION_DOWN: 313 | SoftKey downSKey = mSoftKeyboardView.onTouchKeyPress(x, y); 314 | if (downSKey != null) { 315 | mSoftKeyboardView.getSoftKeyboard().setOneKeySelected(downSKey); 316 | mSoftKeyboardView.setSoftKeyPress(true); 317 | setKeyCodeEnter(downSKey); 318 | // 长按按键. 319 | Message msg = longPressHandler.obtainMessage(); 320 | msg.obj = downSKey; 321 | longPressHandler.sendMessageDelayed(msg, LOG_PRESS_DELAYMILLIS); 322 | } 323 | break; 324 | case MotionEvent.ACTION_UP: 325 | longPressHandler.removeCallbacksAndMessages(null); // 取消长按按键. 326 | mSoftKeyboardView.setSoftKeyPress(false); 327 | break; 328 | } 329 | return true; 330 | } 331 | 332 | /** 333 | * 定制软键盘的,高度和高度. 334 | */ 335 | @Override 336 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 337 | OPENLOG.D(TAG, "onMeasure"); 338 | MeasureHelper measureHelper = MeasureHelper.getInstance(); 339 | int measuredWidth = measureHelper.getScreenWidth(); 340 | int measuredHeight = getPaddingTop(); 341 | measuredHeight += measureHelper.getSkbHeight(); 342 | widthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY); 343 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY); 344 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 345 | } 346 | 347 | } 348 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SkbPool.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * 加载XML键盘布局文件. 7 | * 8 | * @author hailong.qiu 356752238@qq.com 9 | * 10 | */ 11 | public class SkbPool { 12 | 13 | private static final String TAG = "SkbPool"; 14 | 15 | private static SkbPool mInstance = new SkbPool(); // 单例模式. 16 | 17 | private SkbPool() { 18 | } 19 | 20 | public static final SkbPool getInstance() { 21 | return SkbPool.mInstance; 22 | } 23 | 24 | public SoftKeyboard getSoftKeyboard(Context context, int skbXmlId) { 25 | if (null != context) { 26 | XmlKeyboardLoader xkbl = new XmlKeyboardLoader(context); 27 | SoftKeyboard skb = xkbl.loadKeyboard(skbXmlId); 28 | return skb; 29 | } 30 | return null; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SoftKey.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import android.graphics.Rect; 4 | import android.graphics.RectF; 5 | import android.graphics.drawable.Drawable; 6 | 7 | /** 8 | * 按键的键值. 9 | * 10 | * @author hailong.qiu 356752238@qq.com 11 | * 12 | */ 13 | public class SoftKey { 14 | 15 | private Drawable mKeySelectDrawable; 16 | private Drawable mKeyPressDrawable; 17 | private Drawable mKeyBgDrawable; 18 | private Drawable mKeyIcon; 19 | private String mKeyLabel; 20 | private int mKeyCode; // 自定义值. 21 | 22 | private float mLeftF; 23 | private float mRightF; 24 | private float mTopF; 25 | private float mBottomF; 26 | private float mTextSize; // 字体大小. 27 | private int mTextColor; // 字体颜色. 28 | 29 | private boolean isSelected; 30 | private boolean isPressed; // 是否按下. 31 | 32 | /** 33 | * 快速定位按键. 34 | */ 35 | public class SaveSoftKey { 36 | public SoftKey key; 37 | public int row; 38 | public int index; 39 | } 40 | 41 | private SaveSoftKey mNextRightKey = new SaveSoftKey(); 42 | private SaveSoftKey mNextLeftKey = new SaveSoftKey(); 43 | private SaveSoftKey mNextTopKey = new SaveSoftKey(); 44 | private SaveSoftKey mNextBottomKey = new SaveSoftKey(); 45 | 46 | public SaveSoftKey getNextRightKey() { 47 | return mNextRightKey; 48 | } 49 | 50 | public void setNextRightKey(SoftKey nextRightKey, int row, int index) { 51 | this.mNextRightKey.key = nextRightKey; 52 | this.mNextRightKey.row = row; 53 | this.mNextRightKey.index = index; 54 | } 55 | 56 | public SaveSoftKey getNextLeftKey() { 57 | return mNextLeftKey; 58 | } 59 | 60 | public void setNextLeftKey(SoftKey nextLeftKey, int row, int index) { 61 | this.mNextLeftKey.key = nextLeftKey; 62 | this.mNextLeftKey.row = row; 63 | this.mNextLeftKey.index = index; 64 | } 65 | 66 | public SaveSoftKey getNextTopKey() { 67 | return mNextTopKey; 68 | } 69 | 70 | public void setNextTopKey(SoftKey nextTopKey, int row, int index) { 71 | this.mNextTopKey.key = nextTopKey; 72 | this.mNextTopKey.row = row; 73 | this.mNextTopKey.index = index; 74 | } 75 | 76 | public SaveSoftKey getNextBottomKey() { 77 | return mNextBottomKey; 78 | } 79 | 80 | public void setNextBottomKey(SoftKey nextBottomKey, int row, int index) { 81 | this.mNextBottomKey.key = nextBottomKey; 82 | this.mNextBottomKey.row = row; 83 | this.mNextBottomKey.index = index; 84 | } 85 | 86 | public Drawable getKeyPressDrawable() { 87 | return mKeyPressDrawable; 88 | } 89 | 90 | public void setKeyPressDrawable(Drawable keyPressDrawable) { 91 | this.mKeyPressDrawable = keyPressDrawable; 92 | } 93 | 94 | /** 95 | * 判断是否为自定义按键. 不能大于0的keycode. 96 | */ 97 | public boolean isUserDefKey() { 98 | return (mKeyCode < 0); 99 | } 100 | 101 | public boolean isKeyPressed() { 102 | return isPressed; 103 | } 104 | 105 | public void setKeyPressed(boolean isPressed) { 106 | this.isPressed = isPressed; 107 | } 108 | 109 | public int getKeyCode() { 110 | return mKeyCode; 111 | } 112 | 113 | public void setKeyCode(int keyCode) { 114 | this.mKeyCode = keyCode; 115 | } 116 | 117 | public Drawable getKeyIcon() { 118 | return mKeyIcon; 119 | } 120 | 121 | public void setKeyIcon(Drawable mKeyIcon) { 122 | this.mKeyIcon = mKeyIcon; 123 | } 124 | 125 | public int getTextColor() { 126 | return mTextColor; 127 | } 128 | 129 | public void setTextColor(int textColor) { 130 | this.mTextColor = textColor; 131 | } 132 | 133 | public float getTextSize() { 134 | return mTextSize; 135 | } 136 | 137 | public void setTextSize(float textSize) { 138 | this.mTextSize = textSize; 139 | } 140 | 141 | public Drawable getKeyBgDrawable() { 142 | return mKeyBgDrawable; 143 | } 144 | 145 | public void setKeyBgDrawable(Drawable keyBgDrawable) { 146 | this.mKeyBgDrawable = keyBgDrawable; 147 | } 148 | 149 | public void setKeySelectDrawable(Drawable d) { 150 | this.mKeySelectDrawable = d; 151 | } 152 | 153 | public Drawable getKeySelectDrawable() { 154 | return this.mKeySelectDrawable; 155 | } 156 | 157 | public RectF getRectF() { 158 | return new RectF(mLeftF, mTopF, mRightF, mBottomF); 159 | } 160 | 161 | public Rect getRect() { 162 | return new Rect((int) mLeftF, (int) mTopF, (int) mRightF, (int) mBottomF); 163 | } 164 | 165 | public float getLeftF() { 166 | return mLeftF; 167 | } 168 | 169 | public int getLeft() { 170 | return (int) this.mLeftF; 171 | } 172 | 173 | public float getRightF() { 174 | return mRightF; 175 | } 176 | 177 | public int getRight() { 178 | return (int) this.mRightF; 179 | } 180 | 181 | public float getTopF() { 182 | return mTopF; 183 | } 184 | 185 | public int getTop() { 186 | return (int) this.mTopF; 187 | } 188 | 189 | public float getBottomF() { 190 | return mBottomF; 191 | } 192 | 193 | public int getBottom() { 194 | return (int) this.mBottomF; 195 | } 196 | 197 | public float getWidth() { 198 | return mRightF - mLeftF; 199 | } 200 | 201 | public float getHeight() { 202 | return mBottomF - mTopF; 203 | } 204 | 205 | public void setKeyDimensions(float left, float top, float right, float bottom) { 206 | mLeftF = left; 207 | mTopF = top; 208 | mRightF = right; 209 | mBottomF = bottom; 210 | } 211 | 212 | public void setKeyLabel(String label) { 213 | this.mKeyLabel = label; 214 | } 215 | 216 | public String getKeyLabel() { 217 | return mKeyLabel; 218 | } 219 | 220 | /** 221 | * 是否選中. 键值要高亮. 222 | */ 223 | public void setKeySelected(boolean is) { 224 | isSelected = is; 225 | } 226 | 227 | public boolean isKeySelected() { 228 | return this.isSelected; 229 | } 230 | 231 | /** 232 | * 大小写切换. 233 | */ 234 | public void changeCase(boolean upperCase) { 235 | if (null != mKeyLabel) { 236 | if (upperCase) { // 判断是否大写字母 237 | mKeyLabel = mKeyLabel.toUpperCase(); 238 | } else { // 小写. 239 | mKeyLabel = mKeyLabel.toLowerCase(); 240 | } 241 | } 242 | } 243 | 244 | @Override 245 | public String toString() { 246 | return "SoftKey [mKeyIcon=" + mKeyIcon + ", mKeyLabel=" + mKeyLabel + ", mKeyCode=" + mKeyCode + "]"; 247 | } 248 | 249 | } 250 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SoftKeyBoardListener.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | public interface SoftKeyBoardListener { 4 | public void onCommitText(SoftKey key); 5 | } 6 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SoftKeyboard.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.open.inputmethod.keyboard.InputModeSwitcher.ToggleStates; 7 | 8 | import android.graphics.drawable.Drawable; 9 | import android.util.Log; 10 | import android.view.KeyEvent; 11 | 12 | /** 13 | * 软键盘 14 | * 15 | * @author hailong.qiu 356752238@qq.com 16 | * 17 | */ 18 | public class SoftKeyboard { 19 | 20 | private static final String TAG = "SoftKeyboard"; 21 | 22 | private List mKeyRows = new ArrayList(); 23 | private Drawable mKeyboardBg = null; // 键盘背景. 24 | private boolean mIsQwertyUpperCase; // 判断是否大写字母. 25 | private boolean mIsQwerty; // 英文键盘. 26 | private int mHeight; // 键盘高度. 27 | private boolean misLRMove; // 左右移动 28 | private boolean misTBMove; // 上下移动 29 | 30 | public void setHeight(int height) { 31 | this.mHeight = height; 32 | } 33 | 34 | public int getHeight() { 35 | return this.mHeight; 36 | } 37 | 38 | public boolean isQwertyUpperCase() { 39 | return this.mIsQwertyUpperCase; 40 | } 41 | 42 | public void setQwertyUpperCase(boolean isCase) { 43 | this.mIsQwertyUpperCase = isCase; 44 | } 45 | 46 | public boolean isQwerty() { 47 | return this.mIsQwerty; 48 | } 49 | 50 | public boolean isLRMove() { 51 | return this.misLRMove; 52 | } 53 | 54 | public boolean isTBMove() { 55 | return this.misTBMove; 56 | } 57 | 58 | /* 59 | * 设置标志位. 60 | */ 61 | public void setFlags(boolean isQwerty, boolean isQwertyUpperCase, boolean isLRMove, boolean isTBMove) { 62 | this.mIsQwerty = isQwerty; 63 | this.mIsQwertyUpperCase = isQwertyUpperCase; 64 | this.misLRMove = isLRMove; 65 | this.misTBMove = isTBMove; 66 | } 67 | 68 | public Drawable getKeyboardBg() { 69 | return this.mKeyboardBg; 70 | } 71 | 72 | public void setKeyboardBg(Drawable keyboardBg) { 73 | this.mKeyboardBg = keyboardBg; 74 | } 75 | 76 | public KeyRow getKeyRowForDisplay(int row) { 77 | return mKeyRows.get(row); 78 | } 79 | 80 | public List getKeyRows() { 81 | return mKeyRows; 82 | } 83 | 84 | public void setKeyRows(List mKeyRows) { 85 | this.mKeyRows = mKeyRows; 86 | } 87 | 88 | public int getRowNum() { 89 | if (mKeyRows != null) { 90 | return mKeyRows.size(); 91 | } 92 | return 0; 93 | } 94 | 95 | public void clear() { 96 | mKeyRows.clear(); 97 | } 98 | 99 | public void addKeyRow(KeyRow keyRow) { 100 | if (null != mKeyRows && null != keyRow) { 101 | mKeyRows.add(keyRow); 102 | } 103 | } 104 | 105 | public KeyRow getLastKeyRow() { 106 | return mKeyRows.get(mKeyRows.size() - 1); 107 | } 108 | 109 | public boolean addSoftKey(SoftKey softKey) { 110 | if (mKeyRows.isEmpty()) 111 | return false; 112 | KeyRow keyRow = mKeyRows.get(mKeyRows.size() - 1); 113 | if (null == keyRow) 114 | return false; 115 | List softKeys = keyRow.getSoftKeys(); 116 | softKeys.add(softKey); 117 | return true; 118 | } 119 | 120 | public SoftKey mapToKey(int x, int y) { 121 | int rowNum = getRowNum(); 122 | for (int row = 0; row < rowNum; row++) { 123 | KeyRow keyRow = mKeyRows.get(row); 124 | keyRow.getSoftKeys(); 125 | List softKeys = keyRow.getSoftKeys(); 126 | for (int index = 0; index < softKeys.size(); index++) { 127 | SoftKey sKey = softKeys.get(index); 128 | if (sKey.getRect().contains(x, y)) { 129 | mSelectRow = row; 130 | mSelectIndex = index; 131 | return sKey; 132 | } 133 | } 134 | } 135 | return null; 136 | } 137 | 138 | public SoftKey getSoftKey(int rIndex, int cIndex) { 139 | return null; 140 | } 141 | 142 | /** 143 | * 设置按键被选中的状态.
144 | * onkeyDown, onKeyUp的移动效果. 145 | */ 146 | 147 | private SoftKey mSelectSoftKey = null; 148 | private int mSelectRow = 0; 149 | private int mSelectIndex = 0; 150 | 151 | public SoftKey getSelectSoftKey() { 152 | return this.mSelectSoftKey; 153 | } 154 | 155 | public int getSelectRow() { 156 | return this.mSelectRow; 157 | } 158 | 159 | public void setSelectRow(int selectRow) { 160 | this.mSelectRow = selectRow; 161 | } 162 | 163 | public int getSelectIndex() { 164 | return this.mSelectIndex; 165 | } 166 | 167 | public void setSelectIndex(int selectIndex) { 168 | this.mSelectIndex = selectIndex; 169 | } 170 | 171 | /** 172 | * 设置选中的按键.(高亮) 173 | */ 174 | public boolean setOneKeySelected(SoftKey softKey) { 175 | if (mSelectSoftKey != null) 176 | mSelectSoftKey.setKeySelected(false); 177 | softKey.setKeySelected(true); 178 | mSelectSoftKey = softKey; // 保存被选中的按键. 179 | return true; 180 | } 181 | 182 | public SoftKey getMoveLeftSoftKey(int startRow, int endRow) { 183 | SoftKey selectKey = getSelectSoftKey(); 184 | for (int row = startRow; row >= endRow; row--) { 185 | KeyRow keyRow = getKeyRowForDisplay(row); 186 | List softKeys = keyRow.getSoftKeys(); 187 | for (int index = 0; index < softKeys.size(); index++) { 188 | SoftKey key = softKeys.get(index); 189 | // 能向右移动的按键,高度都比原来的按键要高. 190 | if (key.getHeight() > selectKey.getHeight()) { 191 | if (key.getLeft() >= selectKey.getLeft() || key.getRight() >= selectKey.getRight()) { 192 | mSelectIndex = index; 193 | mSelectRow = row; 194 | return key; 195 | } 196 | } 197 | } 198 | } 199 | return null; 200 | } 201 | 202 | public SoftKey getMoveRightSoftKey(int startRow, int endRow) { 203 | SoftKey selectKey = getSelectSoftKey(); 204 | for (int row = startRow; row >= endRow; row--) { 205 | KeyRow keyRow = getKeyRowForDisplay(row); 206 | List softKeys = keyRow.getSoftKeys(); 207 | for (int index = (softKeys.size() - 1); index >= 0; index--) { 208 | SoftKey key = softKeys.get(index); 209 | // 能向右移动的按键,高度都比原来的按键要高. 210 | if (key.getHeight() > selectKey.getHeight()) { 211 | if (key.getLeft() >= selectKey.getLeft() || key.getRight() >= selectKey.getRight()) { 212 | mSelectIndex = index; 213 | mSelectRow = row; 214 | return key; 215 | } 216 | } 217 | } 218 | } 219 | return null; 220 | } 221 | 222 | public SoftKey getMoveDownSoftKey(int startRow, int endRow) { 223 | SoftKey selectKey = getSelectSoftKey(); 224 | for (int row = startRow; row < endRow; row++) { 225 | KeyRow keyRow = getKeyRowForDisplay(row); 226 | List softKeys = keyRow.getSoftKeys(); 227 | for (int index = 0; index < softKeys.size(); index++) { 228 | SoftKey key = softKeys.get(index); 229 | if (key.getLeft() >= selectKey.getLeft() || key.getRight() >= selectKey.getRight()) { 230 | mSelectIndex = index; 231 | mSelectRow = row; 232 | return key; 233 | } 234 | } 235 | } 236 | return null; 237 | } 238 | 239 | public SoftKey getMoveUpSoftKey(int startRow, int endRow) { 240 | SoftKey selectKey = getSelectSoftKey(); 241 | for (int row = startRow; row >= endRow; row--) { 242 | KeyRow keyRow = getKeyRowForDisplay(row); 243 | List softKeys = keyRow.getSoftKeys(); 244 | for (int index = 0; index < softKeys.size(); index++) { 245 | SoftKey key = softKeys.get(index); 246 | if (key.getLeft() >= selectKey.getLeft() || key.getRight() >= selectKey.getRight()) { 247 | mSelectIndex = index; 248 | mSelectRow = row; 249 | return key; 250 | } 251 | } 252 | } 253 | return null; 254 | } 255 | 256 | public boolean setOneKeySelected(int row, int index) { 257 | if (mKeyRows == null) 258 | return false; 259 | row = Math.max(Math.min(row, (mKeyRows.size() - 1)), 0); 260 | if (mKeyRows.get(row).getSoftKeys() == null) 261 | return false; 262 | List softKeys = mKeyRows.get(row).getSoftKeys(); 263 | index = Math.max(Math.min(row, (softKeys.size() - 1)), 0); 264 | SoftKey softKey = softKeys.get(index); 265 | if (softKey != null) { 266 | mSelectRow = row; 267 | mSelectIndex = index; 268 | setOneKeySelected(softKey); 269 | } 270 | return true; 271 | } 272 | 273 | /** 274 | * 状态切换. 275 | */ 276 | public void enableToggleStates(ToggleStates toggleStates, SoftKey key) { 277 | boolean isQwertyUpperCase = toggleStates.mQwertyUpperCase; // 获取大写字母标志位. 278 | boolean isNendCase = (mIsQwerty && (toggleStates.mQwertyUpperCase != mIsQwertyUpperCase)); 279 | int rowNum = getRowNum(); 280 | 281 | for (int row = 0; row < rowNum; row++) { 282 | KeyRow keyRow = mKeyRows.get(row); 283 | List softKeys = keyRow.getSoftKeys(); 284 | int keyNum = softKeys.size(); 285 | for (int keyPos = 0; keyPos < keyNum; keyPos++) { 286 | SoftKey sKey = softKeys.get(keyPos); 287 | if (sKey instanceof ToggleSoftKey) { 288 | for (int stateId : toggleStates.mKeyStates) { 289 | ((ToggleSoftKey) sKey).enableToggleState(stateId); 290 | } 291 | } 292 | /* 293 | * 大小写切换. 294 | */ 295 | if (isNendCase && isLetter(sKey)) { 296 | sKey.changeCase(isQwertyUpperCase); 297 | } 298 | } 299 | } 300 | mIsQwertyUpperCase = isQwertyUpperCase; 301 | } 302 | 303 | /** 304 | * 判断是否为字母 305 | */ 306 | private boolean isLetter(SoftKey sKey) { 307 | return ((sKey.getKeyCode() >= KeyEvent.KEYCODE_A) && (sKey.getKeyCode() <= KeyEvent.KEYCODE_Z)); 308 | } 309 | 310 | } 311 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/SoftKeyboardView.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.util.List; 4 | 5 | import com.open.inputmethod.keyboard.SoftKey.SaveSoftKey; 6 | import com.open.inputmethod.utils.OPENLOG; 7 | 8 | import android.content.Context; 9 | import android.graphics.Bitmap; 10 | import android.graphics.Canvas; 11 | import android.graphics.Paint; 12 | import android.graphics.Paint.FontMetricsInt; 13 | import android.graphics.Rect; 14 | import android.graphics.drawable.Drawable; 15 | import android.text.TextUtils; 16 | import android.util.AttributeSet; 17 | import android.view.KeyEvent; 18 | import android.view.View; 19 | 20 | /** 21 | * 软键盘绘制控件.(主软键盘,弹出键盘) 22 | * 23 | * @author hailong.qiu 356752238@qq.com 24 | * 25 | */ 26 | public class SoftKeyboardView extends View { 27 | 28 | private static final String TAG = "SoftKeyboardView"; 29 | 30 | public SoftKeyboardView(Context context) { 31 | super(context); 32 | init(context, null); 33 | } 34 | 35 | public SoftKeyboardView(Context context, AttributeSet attrs) { 36 | super(context, attrs); 37 | init(context, attrs); 38 | } 39 | 40 | public SoftKeyboardView(Context context, AttributeSet attrs, int defStyle) { 41 | super(context, attrs, defStyle); 42 | init(context, attrs); 43 | } 44 | 45 | private void init(Context context, AttributeSet attrs) { 46 | mPaint = new Paint(); 47 | mPaint.setAntiAlias(true); 48 | mFmi = mPaint.getFontMetricsInt(); 49 | } 50 | 51 | private SoftKeyboard mSoftKeyboard; 52 | private Bitmap mCacheBitmap; 53 | 54 | /* 55 | * 传入需要绘制的键盘(从XML读取出来的). 56 | */ 57 | public void setSoftKeyboard(SoftKeyboard softSkb) { 58 | this.mSoftKeyboard = softSkb; 59 | clearCacheBitmap(); 60 | } 61 | 62 | public void clearCacheBitmap() { 63 | mCacheBitmap = null; 64 | invalidate(); 65 | } 66 | 67 | @Override 68 | protected void onDraw(Canvas rootCanvas) { 69 | if (mSoftKeyboard == null) 70 | return; 71 | if (mCacheBitmap == null) { 72 | OPENLOG.D(TAG, "onDraw mCacheBitmap:" + mCacheBitmap); 73 | mCacheBitmap = createCacheBitmap(); 74 | Canvas canvas = new Canvas(mCacheBitmap); 75 | // 绘制键盘背景. 76 | drawKeyboardBg(canvas); 77 | // 绘制键盘的按键. 78 | int rowNum = this.mSoftKeyboard.getRowNum(); 79 | for (int row = 0; row < rowNum; row++) { 80 | KeyRow keyRow = this.mSoftKeyboard.getKeyRowForDisplay(row); 81 | if (keyRow == null) 82 | continue; 83 | List softKeys = keyRow.getSoftKeys(); 84 | int keyNum = softKeys.size(); 85 | for (int i = 0; i < keyNum; i++) { 86 | SoftKey softKey = softKeys.get(i); 87 | drawSoftKey(canvas, softKey, false); 88 | } 89 | } 90 | } 91 | // 绘制缓存. 92 | drawCacheBitmap(rootCanvas); 93 | // 绘制按键. 94 | SoftKey key = mSoftKeyboard.getSelectSoftKey(); 95 | drawSoftKey(rootCanvas, key, true); 96 | } 97 | 98 | /** 99 | * Bitmap.Config ARGB_8888:
100 | * 每个像素占四位,即A=8,R=8,G=8,B=8,
101 | * 那么一个像素点占8+8+8+8=32位
102 | */ 103 | private Bitmap createCacheBitmap() { 104 | return Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 105 | } 106 | 107 | private void drawCacheBitmap(Canvas rootCanvas) { 108 | if (mCacheBitmap != null) { 109 | Paint paint = new Paint(); 110 | paint.setAntiAlias(true); 111 | rootCanvas.drawBitmap(mCacheBitmap, 0, 0, paint); 112 | } 113 | } 114 | 115 | private Paint mPaint; 116 | 117 | /** 118 | * 绘制键盘的背景. 119 | */ 120 | private void drawKeyboardBg(Canvas canvas) { 121 | Drawable bg = mSoftKeyboard.getKeyboardBg(); 122 | Rect rect = new Rect(0, 0, getWidth(), getHeight()); 123 | if (bg != null) { 124 | bg.setBounds(rect); 125 | bg.draw(canvas); 126 | } else { 127 | Paint paint = new Paint(); 128 | canvas.drawRect(rect, paint); 129 | } 130 | } 131 | 132 | /** 133 | * 绘制键值. 134 | */ 135 | private void drawSoftKey(Canvas canvas, SoftKey softKey, boolean isDrawState) { 136 | // 绘制按键背景. 137 | drawSoftKeyBg(canvas, softKey); 138 | // 绘制选中状态. 139 | if (isDrawState) { 140 | if (softKey.isKeySelected()) { 141 | drawSoftKeySelectState(canvas, softKey); 142 | } 143 | if (softKey.isKeyPressed()) { 144 | drawSoftKeyPressState(canvas, softKey); 145 | } 146 | } 147 | // 绘制按键内容. 148 | String keyLabel = softKey.getKeyLabel(); 149 | Drawable keyIcon = softKey.getKeyIcon(); 150 | if (keyIcon != null) { 151 | drawSoftKeyIcon(canvas, softKey, keyIcon); 152 | } else if (!TextUtils.isEmpty(keyLabel)) { 153 | drawSoftKeyText(canvas, softKey, keyLabel); 154 | } 155 | } 156 | 157 | /** 158 | * 绘制按键的图片. 159 | */ 160 | private void drawSoftKeyIcon(Canvas canvas, SoftKey softKey, Drawable keyIcon) { 161 | int marginLeft = (int) ((softKey.getWidth() - keyIcon.getIntrinsicWidth()) / 2); 162 | int marginRight = (int) (softKey.getWidth() - keyIcon.getIntrinsicWidth() - marginLeft); 163 | int marginTop = (int) ((softKey.getHeight() - keyIcon.getIntrinsicHeight()) / 2); 164 | int marginBottom = (int) (softKey.getHeight() - keyIcon.getIntrinsicHeight() - marginTop); 165 | keyIcon.setBounds(softKey.getLeft() + marginLeft, softKey.getTop() + marginTop, 166 | softKey.getRight() - marginRight, softKey.getBottom() - marginBottom); 167 | keyIcon.draw(canvas); 168 | } 169 | 170 | private FontMetricsInt mFmi; 171 | 172 | /** 173 | * 绘制按键的文本字符. 174 | */ 175 | private void drawSoftKeyText(Canvas canvas, SoftKey softKey, String keyLabel) { 176 | mPaint.setTextSize(softKey.getTextSize()); // 文本大小. 177 | mPaint.setColor(softKey.getTextColor()); // 文本颜色. 178 | mFmi = mPaint.getFontMetricsInt(); 179 | int fontHeight = mFmi.bottom - mFmi.top; // 字體的高度. 180 | float fontWidth = mPaint.measureText(keyLabel); 181 | float marginX = (softKey.getWidth() - fontWidth) / 2.0f; 182 | float marginY = (softKey.getHeight() - fontHeight) / 2.0f; 183 | float x = softKey.getLeftF() + marginX; 184 | // float y = softKey.getTopF() - (mFmi.top) + marginY; 185 | /** 186 | * +1,绘制文字的地方才不会出现问题。 187 | */ 188 | float y = softKey.getTopF() - (mFmi.top + 1) + marginY; 189 | canvas.drawText(keyLabel, x, y, mPaint); 190 | } 191 | 192 | /** 193 | * 绘制按键背景. 194 | */ 195 | private void drawSoftKeyBg(Canvas canvas, SoftKey softKey) { 196 | Drawable bgDrawable = softKey.getKeyBgDrawable(); 197 | if (bgDrawable != null) { 198 | bgDrawable.setBounds(softKey.getRect()); 199 | bgDrawable.draw(canvas); 200 | } 201 | } 202 | 203 | /** 204 | * 绘制按键的选中状态. 205 | */ 206 | private void drawSoftKeySelectState(Canvas canvas, SoftKey softKey) { 207 | Drawable selectDrawable = softKey.getKeySelectDrawable(); 208 | if (selectDrawable != null) { 209 | selectDrawable.setBounds(softKey.getRect()); 210 | selectDrawable.draw(canvas); 211 | } 212 | } 213 | 214 | /** 215 | * 绘制按下的状态. 216 | */ 217 | private void drawSoftKeyPressState(Canvas canvas, SoftKey softKey) { 218 | Drawable pressDrawable = softKey.getKeyPressDrawable(); 219 | if (pressDrawable != null) { 220 | pressDrawable.setBounds(softKey.getRect()); 221 | pressDrawable.draw(canvas); 222 | } 223 | } 224 | 225 | public SoftKeyboard getSoftKeyboard() { 226 | return mSoftKeyboard; 227 | } 228 | 229 | public void setSoftKeyPress(boolean isPress) { 230 | if (mSoftKeyboard == null) { 231 | OPENLOG.E(TAG, "setSoftKeyPress isPress:" + isPress); 232 | return; 233 | } 234 | SoftKey softKey = mSoftKeyboard.getSelectSoftKey(); 235 | if (softKey != null) { 236 | softKey.setKeyPressed(isPress); 237 | invalidate(); 238 | } 239 | } 240 | 241 | public SoftKey onTouchKeyPress(int x, int y) { 242 | SoftKey softKey = mSoftKeyboard.mapToKey(x, y); 243 | return softKey; 244 | } 245 | 246 | /** 247 | * 按键移动.
248 | * 感觉按照left,top,right,bottom区域
249 | * 来查找按键,会影响效率.
250 | * 所以使用了最简单的 行,列概念.
251 | * 总比谷歌英文输入法(ASOP)的一维好. 252 | */ 253 | public boolean moveToNextKey(int direction) { 254 | if (mSoftKeyboard == null) { 255 | OPENLOG.E(TAG, "moveToNextKey mSoftKeyboard is null"); 256 | return false; 257 | } 258 | 259 | int currentRow = mSoftKeyboard.getSelectRow(); 260 | int currentIndex = mSoftKeyboard.getSelectIndex(); 261 | 262 | KeyRow keyRow = mSoftKeyboard.getKeyRowForDisplay(currentRow); 263 | if (keyRow == null) { 264 | OPENLOG.E(TAG, "moveToNextKey keyRow is null"); 265 | return false; 266 | } 267 | 268 | List softKeys = keyRow.getSoftKeys(); 269 | if (softKeys == null) { 270 | OPENLOG.E(TAG, "moveToNextKey keyRow -> softKeys is null"); 271 | return false; 272 | } 273 | SoftKey softKey = null; 274 | SoftKey selectKey = mSoftKeyboard.getSelectSoftKey(); 275 | 276 | switch (direction) { 277 | case KeyEvent.KEYCODE_DPAD_LEFT: 278 | // 快速查询按键. 279 | SaveSoftKey saveLSoftKey = selectKey.getNextLeftKey(); 280 | softKey = saveLSoftKey.key; 281 | // 282 | if (softKey != null) { 283 | currentIndex = saveLSoftKey.index; 284 | currentRow = saveLSoftKey.row; 285 | } else { 286 | currentIndex--; 287 | if (currentIndex < 0) { 288 | // 判断是否可以左右移动(第一个向左移动到最后一个) 289 | if (mSoftKeyboard.isLRMove()) { 290 | softKey = mSoftKeyboard.getMoveLeftSoftKey(mSoftKeyboard.getSelectRow() - 1, 0); 291 | currentIndex = mSoftKeyboard.getSelectIndex(); 292 | currentRow = mSoftKeyboard.getSelectRow(); 293 | if (softKey == null) { 294 | currentIndex = softKeys.size() - 1; 295 | } 296 | } else { 297 | currentIndex = 0; 298 | } 299 | } 300 | // 防止重复刷新. 301 | if (softKey == null && currentIndex != mSoftKeyboard.getSelectIndex()) { 302 | softKey = softKeys.get(currentIndex); 303 | } 304 | // 保存下个方向的按键. 305 | if (softKey != null) { 306 | selectKey.setNextLeftKey(softKey, currentRow, currentIndex); 307 | } 308 | } 309 | break; 310 | case KeyEvent.KEYCODE_DPAD_RIGHT: 311 | // 快速查询按键. 312 | SaveSoftKey saveRSoftKey = selectKey.getNextRightKey(); 313 | softKey = saveRSoftKey.key; 314 | if (softKey != null) { 315 | currentIndex = saveRSoftKey.index; 316 | currentRow = saveRSoftKey.row; 317 | } else { 318 | currentIndex++; 319 | if (currentIndex > (softKeys.size() - 1)) { 320 | if (mSoftKeyboard.isLRMove()) { 321 | softKey = mSoftKeyboard.getMoveRightSoftKey(mSoftKeyboard.getSelectRow() - 1, 0); 322 | currentIndex = mSoftKeyboard.getSelectIndex(); 323 | currentRow = mSoftKeyboard.getSelectRow(); 324 | // 如果区域查找,右边没有高度很高的按键,则跳到第一个. 325 | if (softKey == null) 326 | currentIndex = 0; 327 | } else { 328 | currentIndex = (softKeys.size() - 1); 329 | } 330 | } 331 | // 防止重复刷新. 332 | if (softKey == null && currentIndex != mSoftKeyboard.getSelectIndex()) { 333 | softKey = softKeys.get(currentIndex); 334 | } 335 | // 保存下个方向的按键. 336 | if (softKey != null) { 337 | selectKey.setNextRightKey(softKey, currentRow, currentIndex); 338 | } 339 | } 340 | break; 341 | case KeyEvent.KEYCODE_DPAD_DOWN: 342 | // 快速查询按键. 343 | SaveSoftKey saveBSoftKey = selectKey.getNextBottomKey(); 344 | softKey = saveBSoftKey.key; 345 | if (softKey != null) { 346 | currentIndex = saveBSoftKey.index; 347 | currentRow = saveBSoftKey.row; 348 | } else { 349 | softKey = mSoftKeyboard.getMoveDownSoftKey(mSoftKeyboard.getSelectRow() + 1, mSoftKeyboard.getRowNum()); 350 | currentIndex = mSoftKeyboard.getSelectIndex(); 351 | currentRow = mSoftKeyboard.getSelectRow(); 352 | 353 | if (mSoftKeyboard.isTBMove() && softKey == null) { 354 | softKey = mSoftKeyboard.getMoveDownSoftKey(0, mSoftKeyboard.getSelectRow()); 355 | currentIndex = mSoftKeyboard.getSelectIndex(); 356 | currentRow = mSoftKeyboard.getSelectRow(); 357 | } 358 | /** 359 | * 区域查找,没有查找到的话
360 | * 根据行,列查找. 361 | */ 362 | if (softKey == null) { 363 | currentRow++; 364 | if (currentRow > (mSoftKeyboard.getRowNum() - 1)) { 365 | // 判断是否可以上下(最后一个是否可以向下移动到第一个). 366 | if (mSoftKeyboard.isTBMove()) { 367 | currentRow = 0; 368 | } else { 369 | currentRow = (mSoftKeyboard.getRowNum() - 1); 370 | } 371 | } 372 | // 防止重复刷新. 373 | if (softKey == null && currentRow != mSoftKeyboard.getSelectRow()) { 374 | keyRow = mSoftKeyboard.getKeyRowForDisplay(currentRow); 375 | softKeys = keyRow.getSoftKeys(); 376 | currentIndex = Math.max(Math.min(currentIndex, softKeys.size() - 1), 0); 377 | softKey = softKeys.get(currentIndex); 378 | } 379 | } 380 | // 保存下个方向的按键. 381 | if (softKey != null) { 382 | selectKey.setNextBottomKey(softKey, currentRow, currentIndex); 383 | } 384 | } 385 | break; 386 | case KeyEvent.KEYCODE_DPAD_UP: 387 | // 快速查询按键. 388 | SaveSoftKey saveTSoftKey = selectKey.getNextTopKey(); 389 | softKey = saveTSoftKey.key; 390 | if (softKey != null) { 391 | currentIndex = saveTSoftKey.index; 392 | currentRow = saveTSoftKey.row; 393 | } else { 394 | softKey = mSoftKeyboard.getMoveUpSoftKey(mSoftKeyboard.getSelectRow() - 1, 0); 395 | currentIndex = mSoftKeyboard.getSelectIndex(); 396 | currentRow = mSoftKeyboard.getSelectRow(); 397 | 398 | if (mSoftKeyboard.isTBMove() && softKey == null) { 399 | softKey = mSoftKeyboard.getMoveUpSoftKey(mSoftKeyboard.getRowNum() - 1, 400 | mSoftKeyboard.getSelectRow() + 1); 401 | currentIndex = mSoftKeyboard.getSelectIndex(); 402 | currentRow = mSoftKeyboard.getSelectRow(); 403 | /** 404 | * 区域查找未找到的情况下. 405 | */ 406 | if (softKey == null) { 407 | currentRow--; 408 | if (currentRow < 0) { 409 | if (mSoftKeyboard.isTBMove()) { 410 | currentRow = (mSoftKeyboard.getRowNum() - 1); 411 | } else { 412 | currentRow = 0; 413 | } 414 | } 415 | // 防止重复刷新. 416 | if (softKey == null && currentRow != mSoftKeyboard.getSelectRow()) { 417 | keyRow = mSoftKeyboard.getKeyRowForDisplay(currentRow); 418 | softKeys = keyRow.getSoftKeys(); 419 | currentIndex = Math.max(Math.min(currentIndex, softKeys.size() - 1), 0); 420 | softKey = softKeys.get(currentIndex); 421 | } 422 | } 423 | } 424 | // 保存下个方向的按键. 425 | if (softKey != null) { 426 | selectKey.setNextTopKey(softKey, currentRow, currentIndex); 427 | } 428 | } 429 | break; 430 | default: 431 | break; 432 | } 433 | // 刷新移动的位置. 434 | if (softKey != null) { 435 | mSoftKeyboard.setOneKeySelected(softKey); 436 | mSoftKeyboard.setSelectRow(currentRow); 437 | mSoftKeyboard.setSelectIndex(currentIndex); 438 | invalidate(softKey.getRect()); // 优化绘制区域. 439 | } 440 | return true; 441 | } 442 | 443 | } 444 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/ToggleSoftKey.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.open.inputmethod.utils.OPENLOG; 7 | 8 | import android.graphics.drawable.Drawable; 9 | 10 | /** 11 | * 状态切换按键. 比如大小写切换. 12 | * 13 | * @author hailong.qiu 356752238@qq.com 14 | * 15 | */ 16 | public class ToggleSoftKey extends SoftKey { 17 | 18 | private static final String TAG = "ToggleSoftKey"; 19 | 20 | private int mStateId; // 状态按键的状态ID. 21 | private int mSaveStateId; // 保存的状态ID. 22 | 23 | List mStateKeyList = new ArrayList(); // 保存状态. 24 | 25 | public void addStateKey(ToggleSoftKey stateKey) { 26 | mStateKeyList.add(stateKey); 27 | } 28 | 29 | public List getStateKeyList() { 30 | return mStateKeyList; 31 | } 32 | 33 | public void saveStateId(int stateId) { 34 | mSaveStateId = stateId; 35 | } 36 | 37 | public int getSaveStateId() { 38 | return this.mSaveStateId; 39 | } 40 | 41 | public int getStateId() { 42 | return mStateId; 43 | } 44 | 45 | public void setStateId(int stateId) { 46 | this.mStateId = stateId; 47 | } 48 | 49 | /** 50 | * 会根据现有状态ID返回. 51 | */ 52 | @Override 53 | public String getKeyLabel() { 54 | ToggleSoftKey toggleSoftKey = getToggleState(); 55 | if (toggleSoftKey != null) 56 | return toggleSoftKey.getKeyLabel(); 57 | return super.getKeyLabel(); 58 | } 59 | 60 | @Override 61 | public float getTextSize() { 62 | ToggleSoftKey toggleSoftKey = getToggleState(); 63 | if (toggleSoftKey != null) 64 | return toggleSoftKey.getTextSize(); 65 | return super.getTextSize(); 66 | } 67 | 68 | /** 69 | * 根据状态的颜色. 70 | */ 71 | @Override 72 | public int getTextColor() { 73 | ToggleSoftKey toggleSoftKey = getToggleState(); 74 | if (toggleSoftKey != null) 75 | return toggleSoftKey.getTextColor(); 76 | return super.getTextColor(); 77 | } 78 | 79 | /** 80 | * 会根据现有状态ID返回. 81 | */ 82 | @Override 83 | public Drawable getKeyIcon() { 84 | ToggleSoftKey toggleSoftKey = getToggleState(); 85 | if (toggleSoftKey != null) 86 | return toggleSoftKey.getKeyIcon(); 87 | return super.getKeyIcon(); 88 | } 89 | 90 | public ToggleSoftKey getToggleState() { 91 | for (ToggleSoftKey toggleSoftKey : mStateKeyList) { 92 | if (toggleSoftKey.getStateId() == mSaveStateId) { // 根据保存的状态. 93 | return toggleSoftKey; 94 | } 95 | } 96 | return null; 97 | } 98 | 99 | /** 100 | * 改变状态按键的状态. 101 | */ 102 | public boolean enableToggleState(int stateId) { 103 | int tempStateId = getSaveStateId(); 104 | saveStateId(stateId); 105 | // 检查是否存在. 106 | if (getToggleState() == null) { 107 | saveStateId(tempStateId); // 恢复. 108 | return false; 109 | } 110 | return true; 111 | } 112 | 113 | public void showStateListTest() { 114 | for (ToggleSoftKey stateKey : mStateKeyList) { 115 | OPENLOG.D(TAG, stateKey.toString()); 116 | } 117 | } 118 | 119 | @Override 120 | public String toString() { 121 | return "ToggleSoftKey [stateId=" + mStateId + "]" + "[keyCode=" + getKeyCode() + "]" + "[keyLabel=" 122 | + getKeyLabel() + "]"; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/keyboard/XmlKeyboardLoader.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.keyboard; 2 | 3 | import java.io.IOException; 4 | import java.util.regex.Pattern; 5 | 6 | import org.xmlpull.v1.XmlPullParserException; 7 | 8 | import com.open.inputmethod.utils.MeasureHelper; 9 | import com.open.inputmethod.utils.OPENLOG; 10 | 11 | import android.content.Context; 12 | import android.content.res.Resources; 13 | import android.content.res.XmlResourceParser; 14 | import android.graphics.Color; 15 | import android.graphics.drawable.Drawable; 16 | import android.text.TextUtils; 17 | import android.util.Log; 18 | 19 | /** 20 | * XML 键盘 布局加载. 21 | * 22 | * @author hailong.qiu 356752238@qq.com 23 | */ 24 | public class XmlKeyboardLoader { 25 | 26 | private static final String TAG = "XmlKeyboardLoader"; 27 | 28 | private Context mContext; 29 | private Resources mResources; 30 | private int mXmlEventType; 31 | 32 | /** 33 | * 首先是读取 键盘类型(InputType).
34 | * 类型分别为 全英文,数字,符号 键盘. 35 | */ 36 | public XmlKeyboardLoader(final Context context) { 37 | this.mContext = context; 38 | if (this.mContext == null) 39 | throw new AssertionError("mContext not found."); 40 | this.mResources = context.getResources(); 41 | if (this.mResources == null) 42 | throw new AssertionError("mContext not found."); 43 | } 44 | 45 | private static final String XMLATTR_START_POS_X = "start_pos_x"; 46 | private static final String XMLATTR_START_POS_Y = "start_pos_y"; 47 | 48 | /** 49 | * XML键值. 50 | */ 51 | private static final String XMLTAG_KEYBOARD = "keyboard"; 52 | private static final String XMLTAG_ROW = "row"; 53 | private static final String XMLTAG_KEYS = "keys"; 54 | private static final String XMLTAG_KEY = "key"; 55 | private static final String XMLTAG_TOGGLE_KEY = "toggle_key"; 56 | private static final String XMLTAG_STATE = "state"; 57 | 58 | // keyboard 59 | private static final String XMLATTR_KEYBOARD_BG = "bg_res"; // 键盘界面. 60 | private static final String XMLATTR_KEYBOARD_HEIGHT = "height"; // 键盘界面. 61 | private static final String XMLATTR_QWERTY_UPPERCASE = "qwerty_uppercase"; // 大小写默认 62 | private static final String XMLATTR_QWERTY = "qwerty"; // 字母键盘. 63 | private static final String XMLATTR_LEFT_RIGHT_MOVE = "left_right_move"; // 左右按键移动.(最后一个,第一个) 64 | private static final String XMLATTR_TOP_BOTTOM_MOVE = "top_bottom_move"; // 上下按键移动.(最后一个,第一个) 65 | 66 | // Kyes. 67 | private static final String XMLATTR_KEY_LABELS = "labels"; 68 | private static final String XMLATTR_KEY_CODES = "codes"; 69 | private static final String XMLATTR_KEY_SPLITTER = "splitter"; 70 | 71 | // key. 72 | private static final String XMLATTR_KEY_LABEL = "key_label"; 73 | private static final String XMLATTR_KEY_ICON = "key_icon"; 74 | private static final String XMLATTR_KEY_CODE = "key_code"; 75 | 76 | private static final String XMLATTR_TEXT_SIZE = "key_text_size"; 77 | private static final String XMLATTR_TEXT_COLOR = "key_text_color"; // 文本颜色. 78 | private static final String XMLATTR_KEY_WIDTH = "key_width"; 79 | private static final String XMLATTR_KEY_HEIGHT = "key_height"; 80 | 81 | private static final String XMLATTR_KEY_BG = "key_bg_res"; // 键盘按键背景图片. 82 | private static final String XMLATTR_KEY_SELECT_RES = "key_select_res"; // 键盘按键选中状态图片. 83 | private static final String XMLATTR_KEY_PRESS_RES = "key_press_res"; // 键盘按键按下. 84 | 85 | /** 86 | * 键值的间距. 87 | */ 88 | private static final String XMLATTR_KEY_LEFT_PADDING = "key_left_padding"; 89 | private static final String XMLATTR_KEY_TOP_PADDING = "key_top_padding"; 90 | private static final String XMLATTR_KEY_BOTTOM_PADDING = "key_bottom_padding"; 91 | private static final String XMLATTR_KEY_RIGHT_PADDING = "key_right_padding"; 92 | 93 | // toggle_key. 94 | private static final String XMLATTR_TOGGLE_KEY_STATE_ID = "state_id"; // 状态ID. 95 | 96 | float mSaveKeyXPos; // 保存键值的X位置. 97 | float mSaveKeyYPos; // 保存键值的Y位置. 98 | boolean isStartPosY = true; // 用于自动排列. 99 | 100 | /** 101 | * 解析XML键盘文件. 102 | * 103 | * 保存数据到 SoftKeyboard 中去. 104 | */ 105 | public SoftKeyboard loadKeyboard(int resourceId) { 106 | OPENLOG.D(TAG, "loadKeyboard loading ... ..."); 107 | SoftKeyboard softKeyboard = null; 108 | SoftKey softKey = null; 109 | ToggleSoftKey toggleSoftKey = null; 110 | int skbHeight = -1; 111 | // 112 | XmlResourceParser xrp = mResources.getXml(resourceId); 113 | // 114 | KeyCommonAttributes attrDef = new KeyCommonAttributes(xrp); 115 | KeyCommonAttributes attrSkb = new KeyCommonAttributes(xrp); 116 | KeyCommonAttributes attrRow = new KeyCommonAttributes(xrp); 117 | KeyCommonAttributes attrKeys = new KeyCommonAttributes(xrp); 118 | KeyCommonAttributes attrKey = new KeyCommonAttributes(xrp); 119 | KeyCommonAttributes attrToggleKey = new KeyCommonAttributes(xrp); 120 | KeyCommonAttributes attrStateKey = new KeyCommonAttributes(xrp); 121 | 122 | // 123 | try { 124 | mXmlEventType = xrp.next(); 125 | while (mXmlEventType != XmlResourceParser.END_DOCUMENT) { 126 | if (mXmlEventType == XmlResourceParser.START_TAG) { 127 | String attr = xrp.getName(); 128 | // 转换XML值为小写. 129 | if (!TextUtils.isEmpty(attr)) { 130 | attr = attr.toLowerCase(); 131 | } 132 | if (XMLTAG_KEYBOARD.compareTo(attr) == 0) { // keyboard 133 | if (!attrSkb.getAttributes(attrDef)) 134 | return null; 135 | Drawable bg = getDrawable(xrp, XMLATTR_KEYBOARD_BG, null); // 获取键盘背景. 136 | boolean isQwertyUpperCase = getBoolean(xrp, XMLATTR_QWERTY_UPPERCASE, false); // 大小写初始化值. 137 | boolean isQwerty = getBoolean(xrp, XMLATTR_QWERTY, false); // 英文键盘 138 | boolean isLRMove = getBoolean(xrp, XMLATTR_LEFT_RIGHT_MOVE, true); // 左右移动 139 | boolean isTBMove = getBoolean(xrp, XMLATTR_TOP_BOTTOM_MOVE, true); // 上下移动 140 | skbHeight = (int) getFloat(xrp, XMLATTR_KEYBOARD_HEIGHT, -1f); 141 | softKeyboard = new SoftKeyboard(); 142 | softKeyboard.setKeyboardBg(bg); 143 | softKeyboard.setHeight(skbHeight); // 键盘高度. 144 | softKeyboard.setFlags(isQwerty, isQwertyUpperCase, isLRMove, isTBMove); 145 | mSaveKeyYPos = 0; 146 | } else if (XMLTAG_ROW.compareTo(attr) == 0) { // row 列. 147 | if (softKeyboard == null) { 148 | OPENLOG.E(TAG, "XMLTAG_ROW softKeyboard null"); 149 | return null; 150 | } 151 | if (!attrRow.getAttributes(attrSkb)) { 152 | return null; 153 | } 154 | // 155 | KeyRow keyRow = new KeyRow(); 156 | isStartPosY = getFloat(xrp, XMLATTR_START_POS_Y, -1.0f) != -1.0f ? true : false; 157 | softKeyboard.addKeyRow(keyRow); 158 | mSaveKeyXPos = 0; 159 | } else if (XMLTAG_KEYS.compareTo(attr) == 0) { // keys. 160 | if (!attrKeys.getAttributes(attrRow)) { 161 | return null; 162 | } 163 | // 164 | String splitter = xrp.getAttributeValue(null, XMLATTR_KEY_SPLITTER); 165 | splitter = Pattern.quote(splitter); 166 | String labels = xrp.getAttributeValue(null, XMLATTR_KEY_LABELS); 167 | String codes = xrp.getAttributeValue(null, XMLATTR_KEY_CODES); // 后续加入. 168 | if (null == splitter || null == labels) { 169 | OPENLOG.E(TAG, "XMLTAG_KEYS splitter or labels null"); 170 | return null; 171 | } 172 | String labelArr[] = labels.split(splitter); 173 | String codeArr[] = null; 174 | if (null != codes) { 175 | codeArr = codes.split(splitter); 176 | if (labelArr.length != codeArr.length) { 177 | return null; 178 | } 179 | } 180 | // 添加KEYS中的键值. 181 | for (int i = 0; i < labelArr.length; i++) { 182 | int keyCode = 0; 183 | if (null != codeArr) { 184 | keyCode = Integer.valueOf(codeArr[i]); 185 | } 186 | softKey = getSoftKey(xrp, attrKeys); 187 | softKey.setKeyLabel(labelArr[i]); // 设置 label. 188 | softKey.setKeyCode(keyCode); 189 | softKeyboard.addSoftKey(softKey); 190 | mSaveKeyXPos += softKey.getWidth() + attrKeys.mKeyLeftPadding; 191 | } 192 | } else if (XMLTAG_KEY.compareTo(attr) == 0) { // key 193 | if (null == softKeyboard) { 194 | OPENLOG.E(TAG, "XMLTAG_KEY softKeyboard null"); 195 | return null; 196 | } 197 | if (!attrKey.getAttributes(attrRow)) { 198 | return null; 199 | } 200 | softKey = getSoftKey(xrp, attrKey); 201 | softKeyboard.addSoftKey(softKey); 202 | mSaveKeyXPos += softKey.getWidth() + attrKey.mKeyLeftPadding; 203 | } else if (XMLTAG_TOGGLE_KEY.compareTo(attr) == 0) { // toggle_key 204 | if (null == softKeyboard) { 205 | OPENLOG.E(TAG, "XMLTAG_TOGGLE_KEY softKeyboard null"); 206 | return null; 207 | } 208 | if (!attrToggleKey.getAttributes(attrRow)) { 209 | return null; 210 | } 211 | toggleSoftKey = getStateKey(xrp, attrToggleKey); // 状态切换按键. 212 | mSaveKeyXPos += toggleSoftKey.getWidth() + attrToggleKey.mKeyLeftPadding; 213 | } else if (XMLTAG_STATE.compareTo(attr) == 0) { // state 状态. 214 | if (null == softKeyboard || toggleSoftKey == null) { 215 | OPENLOG.E(TAG, "XMLTAG_STATE softKeyboard or toggleSoftKey null"); 216 | return null; 217 | } 218 | if (!attrStateKey.getAttributes(attrToggleKey)) { 219 | return null; 220 | } 221 | // 222 | ToggleSoftKey stateKey = getStateKey(xrp, attrStateKey); 223 | // 添加状态到状态按键. 224 | toggleSoftKey.addStateKey(stateKey); 225 | } 226 | } else if (mXmlEventType == XmlResourceParser.END_TAG) { 227 | // 判断是否为 228 | String attr = xrp.getName(); 229 | if (XMLTAG_ROW.compareTo(attr) == 0) { 230 | mSaveKeyYPos += attrRow.keyHeight + attrRow.mKeyTopPadding + attrRow.mkeyBottomPadding; 231 | } 232 | // 233 | if (XMLTAG_TOGGLE_KEY.compareTo(attr) == 0) { 234 | softKeyboard.addSoftKey(toggleSoftKey); 235 | toggleSoftKey = null; 236 | // toggleSoftKey.showStateListTest(); 237 | } 238 | } 239 | mXmlEventType = xrp.next(); 240 | } 241 | xrp.close(); 242 | /* 243 | * 如果没有设置软键盘的高度,
默认根据键值的所有高度来设置.
建议在XML布局中自定义高度. 244 | */ 245 | if (skbHeight == -1) { 246 | int height = (int) ((mSaveKeyYPos)); // + (2 * attrSkb.mKeyTopPadding)); 247 | softKeyboard.setHeight(height); 248 | } 249 | MeasureHelper.getInstance().setSkbHeight(softKeyboard.getHeight()); 250 | OPENLOG.D(TAG, "loadKeyboard load over"); 251 | return softKeyboard; 252 | } catch (XmlPullParserException e) { 253 | e.printStackTrace(); 254 | Log.e(TAG, "loadKeyboard XmlPullParserException " + e.getMessage()); 255 | } catch (IOException e) { 256 | e.printStackTrace(); 257 | Log.e(TAG, "loadKeyboard IOException " + e.getMessage()); 258 | } finally { 259 | if (xrp != null) 260 | xrp.close(); 261 | } 262 | return null; 263 | } 264 | 265 | /** 266 | * 获取按键中的状态. 267 | */ 268 | private ToggleSoftKey getStateKey(XmlResourceParser xrp, KeyCommonAttributes attrKey) { 269 | ToggleSoftKey stateKey = getToggleSoftKey(xrp, attrKey); 270 | int stateId = getInteger(xrp, XMLATTR_TOGGLE_KEY_STATE_ID, 0); 271 | stateKey.setStateId(stateId); 272 | return stateKey; 273 | } 274 | 275 | private ToggleSoftKey getToggleSoftKey(XmlResourceParser xrp, KeyCommonAttributes attrKey) { 276 | int keyCode = getInteger(xrp, XMLATTR_KEY_CODE, 0); // key_code 277 | Drawable keyIcon = getDrawable(xrp, XMLATTR_KEY_ICON, null); // key_icon 278 | String keyLabel = getString(xrp, XMLATTR_KEY_LABEL, null); // key_label 279 | float textSize = getFloat(xrp, XMLATTR_TEXT_SIZE, attrKey.mTextSize); // 按键文本字体大小 280 | int textColor = getColor(xrp, XMLATTR_TEXT_COLOR, attrKey.mTextColor); // 按键文本颜色. 281 | // 282 | float left, right, top = 0, bottom; 283 | left = mSaveKeyXPos + attrKey.mKeyXPos + attrKey.mKeyLeftPadding; 284 | right = left + attrKey.keyWidth; 285 | // 判断是否 75 | * 其他的一些系统设置改变也可以触发,比如打开或者隐藏键盘。
76 | * 2. 屏幕方向发生改变时
77 | * TV版本,暂时不处理关于屏幕旋转的傻B问题. 78 | */ 79 | @Override 80 | public void onConfigurationChanged(Configuration newConfig) { 81 | OPENLOG.D(TAG, "onConfigurationChanged newConfig:" + newConfig); 82 | MeasureHelper measureHelper = MeasureHelper.getInstance(); 83 | measureHelper.onConfigurationChanged(newConfig, this); 84 | super.onConfigurationChanged(newConfig); 85 | } 86 | 87 | /** 88 | * 发送字符到编辑框(EditText) 89 | */ 90 | public void commitResultText(String resultText) { 91 | OPENLOG.D(TAG, "commitResultText resultText:" + resultText); 92 | InputConnection ic = getCurrentInputConnection(); 93 | if (null != ic && !TextUtils.isEmpty(resultText)) { 94 | ic.commitText(resultText, 1); 95 | } 96 | } 97 | 98 | public static final int MAX_INT = Integer.MAX_VALUE / 2 - 1; 99 | 100 | public void setCursorRightMove() { 101 | int cursorPos = getSelectionStart(); 102 | cursorPos++; 103 | getCurrentInputConnection().setSelection(cursorPos, cursorPos); 104 | } 105 | 106 | public void setCursorLeftMove() { 107 | int cursorPos = getSelectionStart(); 108 | cursorPos -= 1; 109 | if (cursorPos < 0) 110 | cursorPos = 0; 111 | getCurrentInputConnection().setSelection(cursorPos, cursorPos); 112 | } 113 | 114 | private int getSelectionStart() { 115 | return getCurrentInputConnection().getTextBeforeCursor(MAX_INT, 0).length(); 116 | } 117 | 118 | @Override 119 | public boolean onKeyDown(int keyCode, KeyEvent event) { 120 | // 防止输入法退出还在监听事件. 121 | if (isImeServiceStop()) { 122 | OPENLOG.D(TAG, "onKeyDown isImeServiceStop keyCode:" + keyCode); 123 | return super.onKeyDown(keyCode, event); 124 | } 125 | OPENLOG.D(TAG, "onKeyDown keyCode:" + keyCode); 126 | if (mSkbContainer.onSoftKeyDown(keyCode, event)) { 127 | return true; 128 | } 129 | return super.onKeyDown(keyCode, event); 130 | } 131 | 132 | @Override 133 | public boolean onKeyUp(int keyCode, KeyEvent event) { 134 | // 防止输入法退出还在监听事件. 135 | if (isImeServiceStop()) { 136 | OPENLOG.D(TAG, "onKeyUp isImeServiceStop keyCode:" + keyCode); 137 | return super.onKeyDown(keyCode, event); 138 | } 139 | OPENLOG.D(TAG, "onKeyUp keyCode:" + keyCode); 140 | if (mSkbContainer != null && mSkbContainer.onSoftKeyUp(keyCode, event)) { 141 | return true; 142 | } 143 | return super.onKeyUp(keyCode, event); 144 | } 145 | 146 | /** 147 | * 防止输入法退出还在监听事件. 148 | */ 149 | public boolean isImeServiceStop() { 150 | return ((mSkbContainer == null) || !isInputViewShown()); 151 | } 152 | 153 | /** 154 | * 防止全屏. 155 | */ 156 | @Override 157 | public boolean onEvaluateFullscreenMode() { 158 | return false; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/utils/MeasureHelper.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.view.Display; 6 | import android.view.WindowManager; 7 | 8 | /** 9 | * 10 | * @author hailong.qiu 356752238@qq.com 11 | * 12 | */ 13 | public class MeasureHelper { 14 | 15 | private static MeasureHelper mInstance = new MeasureHelper(); 16 | 17 | private MeasureHelper() { 18 | } 19 | 20 | public static MeasureHelper getInstance() { 21 | return mInstance; 22 | } 23 | 24 | private int mScreenWidth; 25 | private int mScreenHeight; 26 | 27 | /* 28 | * 获取屏幕的高度和宽度. 29 | */ 30 | public void onConfigurationChanged(Configuration config, Context context) { 31 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 32 | Display d = wm.getDefaultDisplay(); 33 | mScreenWidth = d.getWidth(); 34 | } 35 | 36 | /* 37 | * 软键盘的宽度. 38 | */ 39 | public int getScreenWidth() { 40 | return mScreenWidth; 41 | } 42 | 43 | public void setSkbHeight(int height) { 44 | this.mScreenHeight = height; 45 | } 46 | 47 | /* 48 | * 软键盘的高度. 49 | */ 50 | public int getSkbHeight() { 51 | return mScreenHeight; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/utils/OPENLOG.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.utils; 2 | 3 | import android.util.Log; 4 | 5 | public class OPENLOG { 6 | private static final boolean IS_DEBUG = true; 7 | private static final String SEARCH_KEYWORK = " hailongqiu "; 8 | 9 | public static void D(String tag, String msg) { 10 | if (IS_DEBUG) 11 | Log.d(tag, SEARCH_KEYWORK + msg); 12 | } 13 | 14 | public static void E(String tag, String msg) { 15 | if (IS_DEBUG) 16 | Log.e(tag, SEARCH_KEYWORK + msg); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /OpenInputMethod/src/com/open/inputmethod/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.open.inputmethod.utils; 2 | 3 | /** 4 | * @author hailong.qiu 356752238@qq.com 5 | */ 6 | public class Utils { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android TV 输入法. 2 | 3 | 欢迎加入android TV开发群,一起进步,一起学习. 4 | 5 | ![输入图片说明](http://git.oschina.net/uploads/images/2016/0321/214557_bc6d2d45_111902.png "在这里输入图片标题") 6 | 7 | 加班加点,支持点噢!~! 8 | 9 | ![输入图片说明](http://git.oschina.net/uploads/images/2016/0321/214630_cf91c358_111902.png "在这里输入图片标题") 10 | 11 | 12 | 运行效果图 13 | 14 | 15 | ![输入图片说明](http://git.oschina.net/uploads/images/2016/0321/214146_c65a16eb_111902.png "在这里输入图片标题") 16 | 17 | ![输入图片说明](http://git.oschina.net/uploads/images/2016/0321/214153_38260cde_111902.png "在这里输入图片标题") 18 | 19 | ![输入图片说明](http://git.oschina.net/uploads/images/2016/0321/214200_079fd75c_111902.png "在这里输入图片标题") 20 | 21 | 【大小写状态按键】 22 | 23 | ``` 24 | -1 25 | 2 26 | 3 27 | 28 | 30 | 34 | 38 | 39 | ``` 40 | 41 | 【切换到数字键盘】 42 | 43 | ``` 44 | -3 45 | -4 46 | -5 47 | 48 | 52 | ``` 53 | 54 | 【回车按键】 55 | 56 | ``` 57 | 66 58 | 59 | 7 60 | 8 61 | 9 62 | 10 63 | 11 64 | 12 65 | 66 | 70 | 73 | 76 | 79 | 83 | 86 | 89 | 90 | ``` 91 | 92 | 【空格按键】 93 | 94 | ``` 95 | 62 96 | 97 | 101 | ``` 102 | 103 | 【光标移动】 104 | 105 | ``` 106 | 21 107 | 22 108 | 109 | 112 | 115 | ``` 116 | 117 | 【删除按键】 118 | 119 | ``` 120 | 67 121 | 122 | 125 | ``` 126 | 127 | 【返回-退出输入法】 128 | 129 | ``` 130 | 4 131 | 132 | 135 | ``` 136 | 137 | 【翻页按键】 138 | 139 | ``` 140 | -100 141 | 101 142 | 102 143 | 144 | 148 | 149 | 会根据翻页切换的状态改变字符,比如: 150 | 151 | 154 | 158 | 161 | 162 | ``` 163 | 164 | 165 | 【后续加入】 166 | 167 | 模板支持. 168 | 169 | T9键盘支持. 170 | 171 | 中文词库. 172 | --------------------------------------------------------------------------------