WindowInsetListener 将 Android R (Api 30) 中的偏移量加倍

问题描述

我编写了一个键盘动画,使控件(任何视图)跟随软键盘的滑入和滑出动画。 在 Android 10 及更低版本中,一切正常。

我从 proandroiddev 上这篇(同时)过时的文章(在 Android 11 之前编写,不幸的是用 Kotlin 编写,它也不太关心已弃用的方法)中获得了这个想法,但翻译成 Java 效果很好 -剩下的唯一问题是 Api30+

在 Android 11 中,当动画结束时,WindowInsetListener(或 delayedTransition,我不知道是什么原因导致问题)似乎使偏移量加倍(即添加键盘第二次到达视图的边界)。

看看这两个 gif 显示的差异(对不起,质量 - 我对视频录制不太了解)。

在两台设备上运行相同的代码

左侧为 Android 10,右侧为 Android 11

Android 10

Android 11

这里是监听器:

class WindowInsetsListener implements View.OnApplyWindowInsetsListener {
    private final KeyboardAnimationListener animationListener;
    private int prevIoUsOffset = 0;
    
    WindowInsetsListener(KeyboardAnimationListener animationListener) {
        this.animationListener = animationListener;
    }
    
    @Override
    public WindowInsets onApplyWindowInsets(View decorView,WindowInsets insets) {
        WindowInsets result = insets;
        int offset = insets.getSystemWindowInsetBottom() < insets.getStableInsetBottom() ?
                insets.getSystemWindowInsetBottom() :
                insets.getSystemWindowInsetBottom() - insets.getStableInsetBottom();
        
        if (offset != prevIoUsOffset && animationListener.animate(decorView,offset)) {
            prevIoUsOffset = offset;
            result = consumeBottomInset(insets);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                return WindowInsets.CONSUMED;
            }
        }
        
        return decorView.onApplyWindowInsets(result);
    }
    
    private WindowInsets consumeBottomInset(WindowInsets insets) {
        Rect insetRect = new Rect(
            insets.getSystemWindowInsetLeft(),insets.getSystemWindowInsetTop(),insets.getSystemWindowInsetRight(),Math.min(insets.getSystemWindowInsetBottom(),insets.getStableInsetBottom()));
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Insets newInsets = Insets.of(insetRect);
            
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                return new WindowInsets.Builder().
                    setInsets(WindowInsets.Type.systemBars(),newInsets).build();
            } else {
                return new WindowInsets.Builder().
                    setSystemWindowInsets(newInsets).build();
            }
        } else {
            return insets.replaceSystemWindowInsets(insetRect);
        }
    }

这是我从监听器调用的动画方法

    @Override
    public boolean animate(@NonNull View view,int offset) {
        ViewGroup group = getGroup(view); // searches the hierarchy up until it finds the group
        if (group != null) {
            TransitionManager.beginDelayedTransition(group,bounds);
            setBottomPadding(view,offset);
            return true;
        }
        return false;
    }

    protected void setBottomPadding(View view,int offset) {
        view.setPadding(
            view.getPaddingLeft(),view.getPaddingTop(),view.getPaddingRight(),offset);
    }

我试图通过版本尊重所有弃用。尤其是Android的这部分在每个版本中都发生了变化。但是,即使我去掉了 Api 29 和 30 的“新”实现,并且当我使用已弃用的 .replaceSystemWindowInsets 方法时,效果保持不变。

任何人都知道需要在 Api 30+ 中提供的其他标志或其他内容吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...