diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e3b1a28..3dee57c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -27,7 +27,10 @@ - + diff --git a/android/app/src/main/java/com/hyzq/boss/BossWindowInsets.java b/android/app/src/main/java/com/hyzq/boss/BossWindowInsets.java index 8076ef1..9f87348 100644 --- a/android/app/src/main/java/com/hyzq/boss/BossWindowInsets.java +++ b/android/app/src/main/java/com/hyzq/boss/BossWindowInsets.java @@ -49,4 +49,45 @@ public final class BossWindowInsets { } }); } + + public static void applyKeyboardAvoidingInset(View view) { + if (view == null) { + return; + } + final int initialLeft = view.getPaddingLeft(); + final int initialTop = view.getPaddingTop(); + final int initialRight = view.getPaddingRight(); + final int initialBottom = view.getPaddingBottom(); + + ViewCompat.setOnApplyWindowInsetsListener(view, (target, insets) -> { + Insets navigationInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars()); + Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()); + int bottomInset = Math.max(navigationInsets.bottom, imeInsets.bottom); + target.setPadding( + initialLeft, + initialTop, + initialRight, + initialBottom + bottomInset + ); + return insets; + }); + + if (ViewCompat.isAttachedToWindow(view)) { + ViewCompat.requestApplyInsets(view); + return; + } + + view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + v.removeOnAttachStateChangeListener(this); + ViewCompat.requestApplyInsets(v); + } + + @Override + public void onViewDetachedFromWindow(View v) { + // no-op + } + }); + } } diff --git a/android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java b/android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java index 4d827a5..9a56e2d 100644 --- a/android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java +++ b/android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java @@ -178,6 +178,9 @@ public class ProjectDetailActivity extends BossScreenActivity { uri -> onAttachmentPicked(uri, "file") ); + BossWindowInsets.applyKeyboardAvoidingInset(composerRow); + BossWindowInsets.applyKeyboardAvoidingInset(multiSelectActionsLayout); + updateProjectHeader(initialProjectName == null ? "项目详情" : initialProjectName, "正在同步项目详情..."); if (composerAttachmentButton != null) { composerAttachmentButton.setOnClickListener(v -> showAttachmentEntrySheet()); diff --git a/android/app/src/test/java/com/hyzq/boss/BossWindowInsetsTest.java b/android/app/src/test/java/com/hyzq/boss/BossWindowInsetsTest.java index ef22d38..c646842 100644 --- a/android/app/src/test/java/com/hyzq/boss/BossWindowInsetsTest.java +++ b/android/app/src/test/java/com/hyzq/boss/BossWindowInsetsTest.java @@ -35,4 +35,25 @@ public class BossWindowInsetsTest { assertEquals(20, view.getPaddingBottom()); assertEquals(insets, applied); } + + @Test + public void applyKeyboardAvoidingInset_addsImeInsetToBottomPadding() { + View view = new View(RuntimeEnvironment.getApplication()); + view.setPadding(10, 12, 14, 16); + + BossWindowInsets.applyKeyboardAvoidingInset(view); + + WindowInsetsCompat insets = new WindowInsetsCompat.Builder() + .setInsets(WindowInsetsCompat.Type.navigationBars(), Insets.of(0, 0, 0, 24)) + .setInsets(WindowInsetsCompat.Type.ime(), Insets.of(0, 0, 0, 180)) + .build(); + + WindowInsetsCompat applied = androidx.core.view.ViewCompat.dispatchApplyWindowInsets(view, insets); + + assertEquals(10, view.getPaddingLeft()); + assertEquals(12, view.getPaddingTop()); + assertEquals(14, view.getPaddingRight()); + assertEquals(196, view.getPaddingBottom()); + assertEquals(insets, applied); + } }