动画窗口布局更改

时间:2014-10-15 04:43:51

标签: android android-layout

我有一个DialogFragment,通常以屏幕为中心,我试图移开屏幕键盘,如果有任何应该出现,因为它不是键盘覆盖窗户部分的良好用户体验,当完全未使用的屏幕空间更远时。

假设我已经解决了检测到键盘出现或消失的问题,例如How to check visibility of software keyboard in Android?

目前我通过做这样的事情来移开窗口:

...
final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
params.gravity = Gravity.TOP;
params.verticalMargin = .1f;  //or whatever
dialog.getWindow().setAttributes(params);
...

这很好用,但是窗口突然变成了一个位置,这不是一个愉快的用户体验。有问题的窗口有一个成功的进入和退出动画 - 这些甚至可以在窗口布局更改后正常工作。如何在WindowManager.LayoutParams更改之间进一步设置窗口动画?

(我希望尽可能继续按照} {{}} http://developer.android.com/reference/android/view/Window.html的布局工作,而不是强迫DialogFragment进入我的活动的布局和从那里开始制作动画。)

1 个答案:

答案 0 :(得分: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();
}