AdjustResize with animation

时间:2013-12-03 15:26:04

标签: android android-animation android-softkeyboard

我在清单中使用了 android:windowSoftInputMode =“adjustResize”来阻止键盘隐藏活动按钮。它可以工作,但是当键盘打开时,我的按钮会向上移动。它有点跳跃,我想知道 - 我可以有任何动画来顺利过渡吗?

<activity
        android:name=".Activity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize">
</activity>

1 个答案:

答案 0 :(得分:4)

方法setSoftInputMode(int)无法覆盖,其实施位于Window级内,我不认为可以用您自己的方式替换当前窗口。您也无法从WindowManager进行管理 您可以在ViewGroup上创建一个监听器,并在SoftKeyboard打开和关闭时捕获修改的布局。实际上,当SKB出现时,容器的布局会重新绘制并改变其高度。通过此活动,您可以设法在视图子项上设置Animation并实现平滑效果。

编辑:解决方案by using a GlobalLayoutListener on the rootview也可以代替(下面介绍的解决方案:)创建自定义视图组类。

您必须创建自己的视图组并将其作为布局中的父容器。它将实现一个接口,该接口将在UI类(ActivityFragment,无论如何)中处理。我找到了this blog to detect the events on SKB for (~)all versions。根据它,这里是视图组的类来处理高度的变化:

public class ContainerViewHandler extends RelativeLayout {

    private boolean isKeyboardShown;
    private onKeyboardStateChange listener;

    public ContainerViewHandler(Context context) {
        super(context);
    }

    public ContainerViewHandler(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ContainerViewHandler(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setKeyboardStateListener(onKeyboardStateChange listener) {
        this.listener = listener;
    }

    // Callbacks
    public interface onKeyboardStateChange {
        void onKeyboardShow();
        void onKeyboardHide();
    }

    @Override
    public boolean dispatchKeyEventPreIme(@NonNull KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            // Keyboard is hiding
            if (isKeyboardShown) {
                isKeyboardShown = false;
                listener.onKeyboardHide();
            }
        }
        return super.dispatchKeyEventPreIme(event);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int proposedHeight = MeasureSpec.getSize(heightMeasureSpec);
        final int actualHeight = getHeight();
        if (actualHeight > proposedHeight) {
            // Keyboard is showing
            if (!isKeyboardShown) {
                isKeyboardShown = true;
                listener.onKeyboardShow();
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

现在,您已在布局中添加此视图组(例如<com.package.name.ContainerViewHandler .../>)。然后,您必须在活动中实现上述接口setKeyboardStateListener,如下所示:

ContainerViewHandler containerView = 
          (ContainerViewHandler) findViewById(R.id.container_view);
containerView.setKeyboardStateListener(new ContainerHandler.onKeyboardStateChange() {
    @Override
    public void onKeyboardShow() {
        Log.v("onKeyboardShow()", "SoftKeyboard is showing. Hello!");
    }

    @Override
    public void onKeyboardHide() {
        Log.v("onKeyboardHide()", "SoftKeyboard is hiding, Bye bye!");
    }
});

因此,您可以管理不同的动画来处理和阻止按钮跳转&#34;直接位于SKB上方。为了测试这一点,我尝试重现一个反弹效果:

Sample anitmation on button with AdjustResize

我的实现如下:

containerView.setKeyboardStateListener(new ContainerViewHandler.onKeyboardStateChange() {
    @Override
    public void onKeyboardShow() {
        setAnimationUp();
    }

    @Override
    public void onKeyboardHide() {
        setAnimationDown();
    }
});

private void setAnimationUp() {
    footerButton.setVisibility(View.GONE);
    float dpY = AppUtils.convertPxToDp(20, this); // custom conversion method

    Animation a1 = new TranslateAnimation(0, 0, footerButton.getHeight() * 4, -(dpY));
    a1.setDuration(250);
    a1.setFillAfter(true);

    final Animation a2 = new TranslateAnimation(0, 0, -(dpY), 0);
    a2.setDuration(320);
    a2.setFillAfter(true);

    a1.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            footerButton.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            footerButton.startAnimation(a2);
        }

        @Override
        public void onAnimationRepeat(Animation animation) { }
    });

    footerButton.startAnimation(a1);
}

private void setAnimationDown() {
    float dpY = AppUtils.convertPxToDp(30, this); // custom conversion method
    Animation b1 = new TranslateAnimation(0, 0, -(dpY), dpY);
    b1.setDuration(300);
    b1.setFillAfter(true);

    final Animation b2 = new TranslateAnimation(0, 0, dpY, 0);
    b2.setDuration(320);
    b2.setFillAfter(true);

    b1.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) { }

        @Override
        public void onAnimationEnd(Animation animation) {
            footerButton.startAnimation(b2);
        }

        @Override
        public void onAnimationRepeat(Animation animation) { }
    });

    footerButton.startAnimation(b1);
}

我首先在第一个回调中设置两个动画(a1,a2):

  • a1 :从SKB(约4xbutton's height)下面(后面)开始,然后在20dp之上,
  • a2 :从20dp开始并返回0dp(正常位置)。

第二个回调中还有另外两个(b1,b2):

  • b1 :从顶部的30dp开始,到父容器外的30dp
  • b2 :最终,从30dp0dp(初始位置)。

PS:不要忘记在清单中使用adjustResize并制作内容(例如我的测试中的edittexts)above页脚按钮alignParentBottom为真