本文讨论以下几个方面的问题以及解决办法
1,Edittext,获取焦点但是禁止软键盘的弹出,
2,光标的产生原理
3,activity是如何在输入法弹出后调整窗口大小的
1.Edittext,获取焦点但是禁止软键盘的弹出
Android api21 放开了TextView的setShowSoftInputOnFocus方法可以设置在获取焦点的时候不显示软键盘,但是在Android api21以下该方法是隐藏的
api 21以上
/**
* Sets whether the soft input method will be made visible when this
* TextView gets focused. The default is true.
*/
@android.view.RemotableViewMethod
public final void setShowSoftInputOnFocus(boolean show) {
createEditorIfNeeded();
mEditor.mShowSoftInputOnFocus = show;
}
api21以下
/**
* Sets whether the soft input method will be made visible when this
* TextView gets focused. The default is true.
* @hide
*/
@android.view.RemotableViewMethod
public final void setShowSoftInputOnFocus(boolean show) {
createEditorIfNeeded();
mEditor.mShowSoftInputOnFocus = show;
}
因此解决办法是当api小于21的时候使用反射调用setShowSoftInputOnFocus方法
如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
editText.setShowSoftInputOnFocus(false);
}else {
//这里采用反射调用被隐藏方法
setShowSoftInputOnFocus(editText,false);
}
private void setShowSoftInputOnFocus(EditText editText,boolean show) {
try {
Class cls = EditText.class;
Method setShowSoftInputOnFocus;
setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus",
boolean.class);
setShowSoftInputOnFocus.setAccessible(true);
setShowSoftInputOnFocus.invoke(editText, show);
} catch (Exception e) {
e.printStackTrace();
}
}
2.光标的产生原理
是在textView的绘制过程中,如果当前textView是Edittext多绘制一个drawable 再每500ms刷新一次绘制流程 造成光标闪烁的效果
在textView的ondraw()方法中有如下代码
Path highlight = getUpdatedHighlightPath();
if (mEditor != null) {
mEditor.onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);
} else {
layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
}
判断当前的mEditor是否为空 不为空则调用他的ondraw方法,
这里先看下 Editor类的介绍
/**
* Helper class used by TextView to handle editable text views.
*
* @hide
*/
public class Editor {
这个是TextView操纵可编辑Text视图的工具类(可编辑text视图可不就是Edittext)
再看看这个mEditor初始化
/**
* An Editor should be created as soon as any of the editable-specific fields (grouped
* inside the Editor object) is assigned to a non-default value.
* This method will create the Editor if needed.
*
* A standard TextView (as well as buttons, checkboxes...) should not qualify and hence will
* have a null Editor, unlike an EditText. Inconsistent in-between states will have an
* Editor for backward compatibility, as soon as one of these fields is assigned.
*
* Also note that for performance reasons, the mEditor is created when needed, but not
* reset when no more edit-specific fields are needed.
*/
private void createEditorIfNeeded() {
if (mEditor == null) {
mEditor = new Editor(this);
}
}
也就是说只有当可编辑的特殊的字段需要的时候但是未初始化的时候 mEditor便会被创建,但是对于标准的textview 如buttons不会被调用 只有Edittext才会被调用
Edittext的调用流程如下:
TextView初始化调用->setText(text, bufferType);->Edittext重写setText如下:
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, BufferType.EDITABLE);
}
->调用createEditorIfNeeded()方法
setText()方法中有如下代码
...
if (type == BufferType.EDITABLE || getKeyListener() != null
|| needEditableForNotification) {
//此处type == BufferType.EDITABLE所以会调用 createEditorIfNeeded();
createEditorIfNeeded();
mEditor.forgetUndoRedo();
Editable t = mEditableFactory.newEditable(text);
text = t;
setFilters(t, mFilters);
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) imm.restartInput(this);
} else if (type == BufferType.SPANNABLE || mMovement != null) {
text = mSpannableFactory.newSpannable(text);
} else if (!(text instanceof CharWrapper)) {
text = TextUtils.stringOrSpannedString(text);
}
...
好了接下来再继续光标的绘制流程
Editor的onDraw()方法如下:
....
if (highlight != null && selectionStart == selectionEnd && mCursorCount > 0) {
drawCursor(canvas, cursorOffsetVertical);
// Rely on the drawable entirely, do not draw the cursor line.
// Has to be done after the IMM