コントロール (任意のビュー) がソフトキーボードのスライドインおよびスライドアウト アニメーションに従うように、キーボード アニメーションを作成しました。Android 10 以下では、すべて正常に動作します。
私はproandroiddevのこの(その間の)時代遅れの記事(Android 11より前に書かれ、残念ながらKotlinで書かれており、廃止されたメソッドについてもあまり気にしません)からアイデアを取りましたが、Javaへの変換はうまくいきました-残っている唯一の問題はApi30+にあります
Android 11 では、アニメーションが終了すると、WindowInsetListener
(または、delayedTransition
問題の原因がわからない) がオフセットを 2 倍にしているように見えます (つまり、ビューの境界にもう一度ソフトキーボードの高さ全体を追加します)。
違いを示すこれらの 2 つの gif を参照してください (品質については申し訳ありません - 私はビデオ録画にあまり詳しくありません)。
両方のデバイスで同じコードが実行されています。
左が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+ で提供する必要がある何かについて考えている人はいますか?