版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/cuckoochun/article/details/78799112
前几天接到个任务,让android原生的输入法支持物理按键,同时在状态栏体现。
一开始直接在拉丁输入法LatinIME.java类中处理,然后客户要求不能在输入法中处理,于是对InputMethodService.java进行处理。
/*begin add by csc*/
private long timeDown,timeUp;
private int count,typeCount ;
private String input;
private int lastKeyCode;
private boolean isLongPressed = false;
private boolean isDown = false;
private static final long DELAY_TIME = 700;
private boolean isInput = true;
InputConnection inputConnection;// add by csc
/*end add by csc*/
public boolean onKeyDown(int keyCode, KeyEvent event) {
/*begin add by csc*/
if(Settings.Global.getInt(getApplicationContext().getContentResolver(), "aa_key_switch_case_function_enabled",0)==1) {
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei.inputType != 524289 && ei.inputType != InputType.TYPE_NULL && ei.inputType != InputType.TYPE_CLASS_NUMBER && ei.inputType != InputType.TYPE_NUMBER_FLAG_SIGNED && ei.inputType != InputType.TYPE_NUMBER_FLAG_DECIMAL && ei.inputType != InputType.TYPE_CLASS_PHONE) {
if (isInput && keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9 || keyCode == KeyEvent.KEYCODE_STAR || keyCode == KeyEvent.KEYCODE_F3 || keyCode == KeyEvent.KEYCODE_POUND) {
handler.removeCallbacks(runnableUp);
if (typeCount != 0) {
if (!isLongPressed) {
timeDown = System.currentTimeMillis();
if (/*keyCode == KeyEvent.KEYCODE_F3||*/lastKeyCode != 0 && lastKeyCode != keyCode && timeDown - timeUp < DELAY_TIME && lastKeyCode != KeyEvent.KEYCODE_0 && !isDown) {
if (typeCount == 2) {
input = input.toUpperCase();
}
if (DEBUG)
Log.d("chenshichun", " " + this.getClass().getCanonicalName() + " :::::input::::" + input);
inputConnection.commitText(input, 1);
count = 0;
}
if (!isDown && keyCode != KeyEvent.KEYCODE_F3)
handler.postDelayed(runnableDown, DELAY_TIME);
isDown = true;
switch (keyCode) {
case KeyEvent.KEYCODE_0:
input = "0";
return true;
case KeyEvent.KEYCODE_1:
input = "1";
return true;
case KeyEvent.KEYCODE_2:
input = "2";
return true;
case KeyEvent.KEYCODE_3:
input = "3";
return true;
case KeyEvent.KEYCODE_4:
input = "4";
return true;
case KeyEvent.KEYCODE_5:
input = "5";
return true;
case KeyEvent.KEYCODE_6:
input = "6";
return true;
case KeyEvent.KEYCODE_7:
input = "7";
return true;
case KeyEvent.KEYCODE_8:
input = "8";
return true;
case KeyEvent.KEYCODE_9:
input = "9";
return true;
case KeyEvent.KEYCODE_STAR:
input = "*";
return true;
case KeyEvent.KEYCODE_POUND:
input = "#";
return true;
}
} else {
return true;
}
}
if (keyCode == KeyEvent.KEYCODE_F3) {
return true;
}
}
}
}
/*end add by csc*/
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (handleBack(false)) {
event.startTracking();
return true;
}
return false;
}
return doMovementKey(keyCode, event, MOVEMENT_DOWN);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
/*begin add by csc*/
if(Settings.Global.getInt(getApplicationContext().getContentResolver(), "aa_key_switch_case_function_enabled",0)==1) {
final EditorInfo ei = getCurrentInputEditorInfo();
if (ei.inputType != 524289 && ei.inputType != InputType.TYPE_NULL && ei.inputType != InputType.TYPE_CLASS_NUMBER && ei.inputType != InputType.TYPE_NUMBER_FLAG_SIGNED && ei.inputType != InputType.TYPE_NUMBER_FLAG_DECIMAL && ei.inputType != InputType.TYPE_CLASS_PHONE) {
if (isInput) {
isDown = false;
if (typeCount != 0 && /*keyCode != KeyEvent.KEYCODE_POUND && */keyCode != KeyEvent.KEYCODE_F3 &&
(keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9 || keyCode == KeyEvent.KEYCODE_STAR || keyCode == KeyEvent.KEYCODE_POUND)) {
long nowTime = System.currentTimeMillis();
inputConnection = getCurrentInputConnection();
if (isLongPressed) {
isLongPressed = false;
} else {
handler.removeCallbacks(runnableDown);
switch (keyCode) {
case KeyEvent.KEYCODE_0:
if (nowTime - timeDown < DELAY_TIME) {
handler.removeCallbacks(runnableDown);
input = " ";
inputConnection.commitText(input, 1);
}
break;
case KeyEvent.KEYCODE_1:
switch (count % 3) {
case 0:
input = ",";
break;
case 1:
input = ".";
break;
case 2:
input = "@";
break;
}
break;
case KeyEvent.KEYCODE_2:
switch (count % 3) {
case 0:
input = "a";
break;
case 1:
input = "b";
break;
case 2:
input = "c";
break;
}
break;
case KeyEvent.KEYCODE_3:
switch (count % 3) {
case 0:
input = "d";
break;
case 1:
input = "e";
break;
case 2:
input = "f";
break;
}
break;
case KeyEvent.KEYCODE_4:
switch (count % 3) {
case 0:
input = "g";
break;
case 1:
input = "h";
break;
case 2:
input = "i";
break;
}
break;
case KeyEvent.KEYCODE_5:
switch (count % 3) {
case 0:
input = "j";
break;
case 1:
input = "k";
break;
case 2:
input = "l";
break;
}
break;
case KeyEvent.KEYCODE_6:
switch (count % 3) {
case 0:
input = "m";
break;
case 1:
input = "n";
break;
case 2:
input = "o";
break;
}
break;
case KeyEvent.KEYCODE_7:
switch (count % 4) {
case 0:
input = "p";
break;
case 1:
input = "q";
break;
case 2:
input = "r";
break;
case 3:
input = "s";
break;
}
break;
case KeyEvent.KEYCODE_8:
switch (count % 3) {
case 0:
input = "t";
break;
case 1:
input = "u";
break;
case 2:
input = "v";
break;
}
break;
case KeyEvent.KEYCODE_9:
switch (count % 4) {
case 0:
input = "w";
break;
case 1:
input = "x";
break;
case 2:
input = "y";
break;
case 3:
input = "z";
break;
}
break;
case KeyEvent.KEYCODE_STAR:
switch (count % 2) {
case 0:
input = ".";
break;
case 1:
input = ",";
break;
}
break;
case KeyEvent.KEYCODE_POUND:
input = "#";
break;
}
if (typeCount == 2) {
input = input.toUpperCase();
}
inputConnection.setComposingText(input, 1);
handler.removeCallbacks(runnableUp);
handler.postDelayed(runnableUp, DELAY_TIME);
count++;
isLongPressed = false;
timeUp = System.currentTimeMillis();
lastKeyCode = keyCode;
}
}
if (keyCode == KeyEvent.KEYCODE_F3) {
switch (typeCount) {
case 0:
typeCount = 1;
break;
case 1:
typeCount = 2;
break;
case 2:
typeCount = 0;
break;
}
input = "";
Intent intent = new Intent("INPUT_STATUS_CHANGE");
intent.putExtra("INPUT_STATUS", typeCount);
sendBroadcast(intent);
}
}
}
}
/*end add by csc*/
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.isTracking()
&& !event.isCanceled()) {
return handleBack(true);
}
return doMovementKey(keyCode, event, MOVEMENT_UP);
}
/*begin add by csc*/
Handler handler = new Handler();
Runnable runnableDown = new Runnable() {
@Override
public void run() {
try {
inputConnection.commitText(input, 1);
if(DEBUG)Log.d("chenshichun"," "+this.getClass().getCanonicalName()+" :::::runnableDown::::"+input);
isLongPressed = true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("exception...");
}
}
};
Runnable runnableUp = new Runnable() {
@Override
public void run() {
try {
if(typeCount==2){
input = input.toUpperCase();
}
inputConnection.commitText(input, 1);
if(DEBUG)Log.d("chenshichun"," "+this.getClass().getCanonicalName()+" :::::runnableUp::::"+input);
count = 0;
} catch (Exception e) {
e.printStackTrace();
System.out.println("exception...");
}
}
};
/*end add by csc*/
因为监听不到长按事件,所以在每次down的时候都当长按处理,handler.postDelayed(runnableDown, DELAY_TIME); 每次up的时候先handler.removeCallbacks(runnableDown);这时候如果抬手时间大于DELAY_TIME就会当长按处理,在电话,计算器等只需要输入数字的界面就将该功能屏蔽,通过输入类型来判断即可,这里524289是计算器读出来的类型,源码中找不到就直接写数值了。
ei.inputType != 524289 && ei.inputType != InputType.TYPE_NULL && ei.inputType != InputType.TYPE_CLASS_NUMBER && ei.inputType != InputType.TYPE_NUMBER_FLAG_SIGNED && ei.inputType != InputType.TYPE_NUMBER_FLAG_DECIMAL && ei.inputType != InputType.TYPE_CLASS_PHONE
当切换大小写的时候在PhoneStatusBar.java接受广播
else if("INPUT_STATUS_CHANGE".equals(action)){// add by csc
int inputStatus = intent.getIntExtra("INPUT_STATUS",0);
switch (inputStatus){
case 0:
mInputStatus.setText("");
break;
case 1:
mInputStatus.setText(R.string.input_lower);
break;
case 2:
mInputStatus.setText(R.string.input_case);
break;
}
}else if ("INPUT_ON_OR_FALSE".equals(action)){// add by csc
boolean putStatusOn = intent.getBooleanExtra("INPUT_STATUS_ON",false);
mInputStatus.setVisibility(putStatusOn?View.VISIBLE:View.GONE);
}
其中INPUT_ON_OR_FALSE这个广播是设置里面发出的,设置里面加了一个这个功能是否启用的开关,对应
Settings.Global.getInt(getApplicationContext().getContentResolver(), "aa_key_switch_case_function_enabled",0)==1
还需要在statusbar.xml里面加一个控件
<TextView
android:id="@+id/input_status"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="@string/input_case"
android:visibility="gone"
/>
后面发现在短信界面联想功能会乱,于是实体按键的时候就把联想功能去掉:
在拉丁输入法LatinIME.java里面修改:
if (!/*latinIme.mSettings.getCurrent().isSuggestionsEnabledPerUserSettings()*/false) {// mod by csc
return;
}