AdjustResize with animation

 cy45vsf 发布于 2023-02-13 10:47

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



fllo.. 6

该方法setSoftInputMode(int)不能被覆盖,它的实现是在Window类内部,我认为无法用您自己的方法替换当前窗口。您也无法对此进行管理WindowManager
您可以在上创建一个侦听器,ViewGroup并在SoftKeyboard打开和关闭时捕获修改的布局。实际上,当SKB出现时,容器的布局将重新绘制并更改其高度。通过此事件,您可以设法设置一个Animationon view子级并产生平滑效果。

编辑:也可以通过在rootview上使用GlobalLayoutListener解决方案,而不是(下面显示的解决方案:)创建自定义视图组类。

您必须创建自己的视图组并将其作为布局中的父容器。它会实现,这将在UI类来处理接口(ActivityFragment,等等)。我发现此博客可检测所有版本(〜)上SKB上的事件。据此,这是处理高度变化的视图组的类:

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);
    }
}

现在,您必须在布局中添加此视图组(例如)。然后,您必须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!");
    }
});

因此,您可以管理不同的动画来处理和防止按钮直接跳到SKB上方。为了测试这一点,我尝试重现反弹效果:

我的实现如下所示:

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:最后,从30dp外到0dp(初始位置)。

PS:别忘了adjustResize在清单中使用并使内容(例如,我的测试中的edittext)above成为页脚按钮,该按钮必须alignParentBottom为true。

1 个回答
  • 该方法setSoftInputMode(int)不能被覆盖,它的实现是在Window类内部,我认为无法用您自己的方法替换当前窗口。您也无法对此进行管理WindowManager
    您可以在上创建一个侦听器,ViewGroup并在SoftKeyboard打开和关闭时捕获修改的布局。实际上,当SKB出现时,容器的布局将重新绘制并更改其高度。通过此事件,您可以设法设置一个Animationon view子级并产生平滑效果。

    编辑:也可以通过在rootview上使用GlobalLayoutListener解决方案,而不是(下面显示的解决方案:)创建自定义视图组类。

    您必须创建自己的视图组并将其作为布局中的父容器。它会实现,这将在UI类来处理接口(ActivityFragment,等等)。我发现此博客可检测所有版本(〜)上SKB上的事件。据此,这是处理高度变化的视图组的类:

    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!");
        }
    });
    

    因此,您可以管理不同的动画来处理和防止按钮直接跳到SKB上方。为了测试这一点,我尝试重现反弹效果:

    我的实现如下所示:

    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:最后,从30dp外到0dp(初始位置)。

    PS:别忘了adjustResize在清单中使用并使内容(例如,我的测试中的edittext)above成为页脚按钮,该按钮必须alignParentBottom为true。

    2023-02-13 10:50 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有