【问题标题】:Android, how to know how much my view is shifted by soft keyboard adjustPanAndroid,如何知道我的视图被软键盘adjustPan转移了多少
【发布时间】:2023-03-07 11:55:02
【问题描述】:

我有一个全屏横向应用程序 (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 位于屏幕顶部的某个位置,即它的 rect 不与键盘相交,则没有任何变化,EditText 保持原样,一切正常。 但是,如果我的 EditText 位于屏幕中间,因此键盘将与它重叠,它就会开始向上移动(带有动画)。

我已成功使用 SOFT_INPUT_ADJUST_PAN 确定键盘高度(通过 getWindowVisibleDisplayFrame 调用之间的差异),所以我不能通过设置 adjustNothing 标志来禁用平移,我'我会坚持adjustPan

问题是我无法理解在调整软键盘大小时我的视图位置到底做了什么(对于建议行)。 在我的 onGlobalLayout 我试图观看:

- TextView getY(),
- TextView getTranslationY(),
- TextView RelativeLayout params (topMargin, bottomMargin),
- TextView getLocationOnScreen,
- TextView getGlobalVisibleRect top & bottom,
- Activity getWindowVisibleDisplayFrame rect top & bottom.

以上没有任何改变!但是 TextView 无论如何都在向上移动。 我相信在软键盘出现后,在视图树的某个地方应用了一些偏移量。但是为什么 getLocationOnScreen 不显示呢?为什么 getGlobalVisibleRect 也不知道位置变化?

我想为我的 EditText 设置准确的位置,所以即使我不能阻止它向上移动(权衡设置 adjustPan 标志),至少我需要知道向上移动了多少,以应用反向转换

我尝试了一个非常老套的解决方法:在我的 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 出现问题。

提前致谢。

【问题讨论】:

    标签: android android-layout keyboard


    【解决方案1】:

    嗯,我没能抓住过渡本身。 相反,在我的特定情况下可行的解决方法是这样的:

    添加新的不可见对话框,用于getWindowVisibleDisplayFrame,因此当键盘显示/隐藏时,您将获得所需的一切。

    ...而且您现在肯定需要 SOFT_INPUT_ADJUST_NOTHING 作为您的主(可见)对话框,如果您不再需要它的 displayFrame,为什么不呢?因此,没有隐藏的不明显变化应用于您视图中的任何内容。

    就这么简单。 希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-05-14
      • 2013-08-10
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      相关资源
      最近更新 更多