我有一个全屏横向应用程序 (Cocos2d-x/NDK),它有一个输入字段,我在运行时设置的位置是这样的
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mInstance.mEditText.getLayoutParams();
params.topMargin = (int)newY;
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
mInstance.mEditText.setLayoutParams(params);
它在大多数设备上都运行良好,但我有一台设备,软键盘动态增长,上面有“建议”行。 那就是奇怪的事情发生的时候。
如果我的 EditText 位于屏幕顶部的某个位置,即它的矩形不与键盘相交,没有任何变化,EditText 保持原样,一切正常。 但是,如果我的 EditText 位于屏幕中间,键盘将与它重叠,它就会开始向上移动(带有动画)。
我成功地使用 SOFT_INPUT_ADJUST_PAN 来确定键盘高度(通过 getWindowVisibleDisplayFrame 调用之间的差异),所以我不能通过设置 adjustNothing 标志来禁用平移,我'我将坚持使用 adjustPan。
问题是我无法理解在调整软键盘大小时(针对建议行)我的 View 位置究竟做了什么。 在我的 onGlobalLayout 中,我试图观看:
- TextView getY(),
- TextView getTranslationY(),
- TextView RelativeLayout params (topMargin, bottomMargin),
- TextView getLocationOnScreen,
- TextView getGlobalVisibleRect top & bottom,
- Activity getWindowVisibleDisplayFrame rect top & bottom.
以上都没有改变!但是无论如何,TextView 都在向上移动。 我相信在软键盘出现后,在 View 树的某个地方应用了一些偏移量。但是为什么 getLocationOnScreen 不显示这个呢?为什么 getGlobalVisibleRect 也不知道位置变化?
我想为我的 EditText 设置准确的位置,所以即使我不能阻止它向上移动(设置 adjustPan 标志的权衡),至少我需要知道它向上移动了多少,以应用反向转换。
我尝试了一个非常 hacky 的解决方法:在我的 EditText beforeTextChanged() 方法中,我将 TextView 的布局 topMargin 设置为 0,以确保当建议行出现时,它不会移动我的 TextView,因为它是不再重叠。然后在 onGlobalLayout() 中恢复正确的 EditText 位置。它有效,但我不喜欢这种方式,而且它还会导致我的文本闪烁。
一些代码可以更好地理解我在做什么。
private void showKeyboard(final boolean show) {
final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (show) {
mEditText.requestFocus();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
imm.showSoftInput(mEditText, 0);
}
}, 50);
mVisible = true;
} else {
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
mEditText.clearFocus();
mVisible = false;
}
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.native_keyboard);
mLayout = findViewById(R.id.keyboard_layout);
mEditText = (EditText) findViewById(R.id.keyboard_input);
mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
mEditText.setInputType(mEditText.getInputType() | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS | EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE);
mInitialFrame = getVisibleFrame();
mPreviousFrame = mInitialFrame;
mLayout.getViewTreeObserver().addOnGlobalLayoutListener(new android.view.ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final int kbAssumedH = 100;
Rect currentFrame = getVisibleFrame();
final int dResize = (int) (mPreviousFrame.height() - currentFrame.height());
if (mWasShown && isVisible() && dResize != 0) {
NativeKeyboard.onKeyboardResized();
}
mPreviousFrame = currentFrame;
if (isVisible() && (mInitialFrame.height() - currentFrame.height() > kbAssumedH)) {
if (!mWasShown) {
NativeKeyboard.onKeyboardDidShow();
mWasShown = true;
}
} else {
if (mWasShown) {
NativeKeyboard.onKeyboardDidHide();
mWasShown = false;
}
}
}
});
}
这就是我如何获得不与键盘重叠的当前窗口空间:
public static synchronized android.graphics.Rect getVisibleFrame() {
View rootView = mInstance.getWindow().getDecorView();
android.graphics.Rect r = new android.graphics.Rect();
rootView.getWindowVisibleDisplayFrame(r);
return r;
}
这是我用来设置 EditText 位置的方法。 在建议行出现后,我的 EditText 在视觉上相对于我作为 Y 参数传递到这里的位置向上移动(并且移动是永久性的,即我可以用新位置调用 setRect,它也会移动)
public static synchronized void setRect(final float x, final float y, final float w, final float h) {
if (mInstance != null) {
Cocos2dxHelper.runOnUIThread(new Runnable() {
@Override
public void run() {
mInstance.mEditText.setX((int) x);
float height = mInstance.mEditText.getHeight();
mInstance.mEditText.setWidth((int) w);
float yCenter = y + h / 2;
float newY = yCenter - height / 2.f;
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mInstance.mEditText.getLayoutParams();
params.topMargin = (int)newY;
params.width = (int)w;
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
mInstance.mEditText.setLayoutParams(params);
}
});
}
}
我尝试了 4 种不同的设备(3 部手机和 1 部平板电脑),问题仅出现在 Acer Liquid Jade Z,4.4.4 上。
提前致谢。
最佳答案
好吧,我没能捕获转变本身。 相反,在我的特定情况下可行的解决方法是这样的:
添加新的不可见对话框,仅用于getWindowVisibleDisplayFrame,因此当键盘显示/隐藏时您将获得所需的一切。
...并且您现在肯定希望主(可见)对话框使用 SOFT_INPUT_ADJUST_NOTHING,如果您不再需要它的 displayFrame,为什么不呢?因此,您的 View 中的任何内容都不会出现隐藏的不明显变化。
就这么简单。 希望对您有所帮助。
关于Android,如何知道我的 View 被软键盘adjustPan移动了多少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37924410/