窗口布局变化动画化

6
我有一个DialogFragment,通常位于屏幕中央,我正在尝试将其移开以避免挡住屏幕键盘(如果有),因为当有未使用的屏幕空间时,键盘覆盖窗口的部分区域不是良好的用户体验。
假设我已经解决了检测键盘出现或消失的问题,例如如何在Android中检查软件键盘的可见性?
目前,我通过执行以下操作来将窗口移开:
...
final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
params.gravity = Gravity.TOP;
params.verticalMargin = .1f;  //or whatever
dialog.getWindow().setAttributes(params);
...

这个工作正常,但窗口突然跳到位,这不是一个愉快的UX体验。所涉及的窗口有成功的进入和退出动画,即使在窗口布局更改后也适当地工作。如何在WindowManager.LayoutParams更改时进一步动画化窗口?
(如果可能的话,我更喜欢在布局方面继续工作/在http://developer.android.com/reference/android/view/Window.html中而不是将DialogFragment强制放入我的Activity布局中并从那里进行动画处理)。

1
在你的 AndroidManifest 中,你尝试过在 activity 标签中添加 android:windowSoftInputMode="stateHidden|adjustPan" 吗?这可能能够自动保持活动视图显示。我倾向于在其他功能中使用它,但还没有尝试过在 DialogFragment 中使用。 - Anonsage
1
我之前曾尝试过这个,为了确保我又试了一次。它似乎只影响Activity的根视图(DecorView),而不是其他窗口及其视图。我看到Activity在后台调整了键盘(而且还没有动画),但窗口仍然漂浮在那里没有改变。此外,如果有人想建议,是的,我也在DialogFragment中尝试了"window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);"。 - jdowdell
@jdowdell 使用DialogFragment代替。 - S.D.
1个回答

2

由于我没有时间等待悬赏期满,所以我编写了以下临时解决方案,直到我能找到更好的解决方案。如果能帮助其他人或者给他们提供一个值得悬赏的答案的思路,那就太好了。但是,我怀疑这个方法非常低效,因为我认为它在每个动画帧中强制进行窗口重新布局,而不仅仅是在屏幕上滚动位图。当然,这还不是全部内容,只是其中关键的部分:

// Not shown: setting currentVerticalMargin, targetVerticalMargin, or calling this method
private synchronized void restartVerticalMarginAnimator() {
    if (verticalMarginAnimator != null) {
        return;
    }
    final Dialog dialog = this.getDialog();
    if (dialog == null) {
        return;
    }
    final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
    verticalMarginAnimator = new TimeAnimator();
    verticalMarginAnimator.setTimeListener(new TimeListener() {
        @Override
        public void onTimeUpdate(TimeAnimator a, long totalTime, long deltaTime) {
            float stretch = targetVerticalMargin - currentVerticalMargin;
            float distance = WINDOW_ANIMATION_SPEED * deltaTime / 1000L;
            boolean finished = false;

            // Adjust distance so it's capped at "going all the way to target" and no further,
            // and has the right sign if we're animating upward.
            if (distance > Math.abs(stretch)) {
                distance = stretch;
                finished = true;
            } else if (stretch < 0) {
                distance *= -1f;
            }

            // Move.
            currentVerticalMargin += distance;
            if (finished) {
                verticalMarginAnimator.end();
                verticalMarginAnimator = null;
            }
            params.verticalMargin = currentVerticalMargin;
            dialog.getWindow().setAttributes(params);
        }
    });
    verticalMarginAnimator.start();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接