fix: keep chat composer above ime on android

This commit is contained in:
kris
2026-03-31 16:12:31 +08:00
parent f417fe1955
commit 70494fc15b
4 changed files with 69 additions and 1 deletions

View File

@@ -27,7 +27,10 @@
</activity>
<activity android:name=".ProjectDetailActivity" android:exported="false" />
<activity
android:name=".ProjectDetailActivity"
android:exported="false"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".ConversationFolderActivity" android:exported="false" />
<activity android:name=".ProjectGoalsActivity" android:exported="false" />
<activity android:name=".ProjectVersionsActivity" android:exported="false" />

View File

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

View File

@@ -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());

View File

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