Handle specific case when leaving group; also move floating button to avoid overaapping with system bar

This commit is contained in:
wch423
2026-02-04 18:04:34 +01:00
parent f319ba2b83
commit b66bc1f863
4 changed files with 80 additions and 23 deletions
@@ -995,10 +995,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if(chatId == DcChat.DC_CHAT_NO_CHAT)
throw new IllegalStateException("can't display a conversation for no chat.");
dcChat = DcHelper.getContext(context).getChat(chatId);
if (!dcChat.canSend()) {
ViewUtil.applyWindowInsets(findViewById(R.id.root_layout), true, false, true, false);
fragment.handleAdjustBottomLayout();
}
recipient = new Recipient(this, dcChat);
glideRequests = GlideApp.with(this);
@@ -1010,10 +1006,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (dcChat.canSend()) {
composePanel.setVisibility(View.VISIBLE);
attachmentManager.setHidden(false);
ViewUtil.forceApplyWindowInsets(findViewById(R.id.root_layout), true, false, true, true);
fragment.handleRemoveBottomInsets();
} else {
composePanel.setVisibility(View.GONE);
attachmentManager.setHidden(true);
hideSoftKeyboard();
ViewUtil.forceApplyWindowInsets(findViewById(R.id.root_layout), true, false, true, false);
fragment.handleAddBottomInsets();
}
}
@@ -108,7 +108,8 @@ public class ConversationFragment extends MessageSelectorFragment
public boolean isPaused;
private Debouncer markseenDebouncer;
private Rpc rpc;
private boolean pendingAdjustBottomLayout;
private boolean pendingAddBottomInsets;
private boolean pendingRemoveBottomInsets;
@Override
public void onCreate(Bundle icicle) {
@@ -161,10 +162,18 @@ public class ConversationFragment extends MessageSelectorFragment
// with hardware layers, drawing may result in errors as "OpenGLRenderer: Path too large to be rendered into a texture"
list.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
if (pendingAdjustBottomLayout) {
if (pendingAddBottomInsets) {
bottomDivider.setVisibility(View.GONE);
ViewUtil.applyWindowInsets(list, false, true, false, true);
pendingAdjustBottomLayout = false;
ViewUtil.forceApplyWindowInsetsAsMargin(scrollToBottomButton, true, true, true, true);
pendingAddBottomInsets = false;
}
if (pendingRemoveBottomInsets) {
bottomDivider.setVisibility(View.VISIBLE);
ViewUtil.applyWindowInsets(list, false, true, false, false);
ViewUtil.forceApplyWindowInsetsAsMargin(scrollToBottomButton, true, true, true, false);
pendingRemoveBottomInsets = false;
}
return view;
@@ -205,14 +214,25 @@ public class ConversationFragment extends MessageSelectorFragment
}
}
public void handleAdjustBottomLayout() {
public void handleAddBottomInsets() {
if (bottomDivider != null) {
bottomDivider.setVisibility(View.GONE);
ViewUtil.applyWindowInsets(list, false, true, false, true);
pendingAdjustBottomLayout = false;
ViewUtil.forceApplyWindowInsetsAsMargin(scrollToBottomButton, false, false, false, true);
pendingAddBottomInsets = false;
} else {
pendingAddBottomInsets = true;
}
else {
pendingAdjustBottomLayout = true;
}
public void handleRemoveBottomInsets() {
if (bottomDivider != null) {
bottomDivider.setVisibility(View.VISIBLE);
ViewUtil.applyWindowInsets(list, false, true, false, false);
ViewUtil.forceApplyWindowInsetsAsMargin(scrollToBottomButton, false, false, false, false);
pendingRemoveBottomInsets = false;
} else {
pendingRemoveBottomInsets = true;
}
}
@@ -77,7 +77,7 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
findViewById(R.id.status_bar_background).setBackgroundResource(R.drawable.search_toolbar_shadow);
} else {
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container), true, true, true, true, true);
ViewUtil.applyWindowInsets(findViewById(R.id.content_container), true, true, true, true, true, false);
}
webView.setWebViewClient(new WebViewClient() {
@@ -323,7 +323,15 @@ public class ViewUtil {
* @param view The view to apply insets to
*/
public static void applyWindowInsetsAsMargin(@NonNull View view) {
applyWindowInsetsAsMargin(view, true, true, true, true);
applyWindowInsetsAsMargin(view, true, true, true, true, false);
}
public static void applyWindowInsetsAsMargin(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
applyWindowInsetsAsMargin(view, left, top, right, bottom, false);
}
public static void forceApplyWindowInsetsAsMargin(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
applyWindowInsetsAsMargin(view, left, top, right, bottom, true);
}
/**
@@ -337,8 +345,9 @@ public class ViewUtil {
* @param top Whether to apply top inset
* @param right Whether to apply right inset
* @param bottom Whether to apply bottom inset
* @param forceDispatch Whether to force application of insets
*/
public static void applyWindowInsetsAsMargin(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
public static void applyWindowInsetsAsMargin(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom, boolean forceDispatch) {
// Only enable on API 30+ where WindowInsets APIs work correctly
if (!isEdgeToEdgeSupported()) return;
@@ -371,10 +380,10 @@ public class ViewUtil {
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) layoutParams;
marginParams.leftMargin = baseMarginLeft + insets.left;
marginParams.topMargin = baseMarginTop + insets.top;
marginParams.rightMargin = baseMarginRight + insets.right;
marginParams.bottomMargin = baseMarginBottom + insets.bottom;
marginParams.leftMargin = left ? baseMarginLeft + insets.left : baseMarginLeft;
marginParams.topMargin = top ? baseMarginTop + insets.top : baseMarginTop;
marginParams.rightMargin = right ? baseMarginRight + insets.right : baseMarginRight;
marginParams.bottomMargin = bottom ? baseMarginBottom + insets.bottom : baseMarginBottom;
v.setLayoutParams(marginParams);
}
@@ -383,7 +392,14 @@ public class ViewUtil {
// Request the initial insets to be dispatched if the view is attached
if (view.isAttachedToWindow()) {
ViewCompat.requestApplyInsets(view);
if (forceDispatch) {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view);
if (insets != null) {
ViewCompat.dispatchApplyWindowInsets(view, insets);
}
} else {
ViewCompat.requestApplyInsets(view);
}
}
}
@@ -395,7 +411,7 @@ public class ViewUtil {
* @param view The view to apply insets to
*/
public static void applyWindowInsets(@NonNull View view) {
applyWindowInsets(view, true, true, true, true, false);
applyWindowInsets(view, true, true, true, true, false, false);
}
/**
@@ -410,7 +426,20 @@ public class ViewUtil {
* @param bottom Whether to apply bottom inset
*/
public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
applyWindowInsets(view, left, top, right, bottom, false);
applyWindowInsets(view, left, top, right, bottom, false, false);
}
/**
* Force applying window insets to a view by adding padding to avoid drawing elements behind system bars.
*
* @param view The view to apply insets to
* @param left Whether to apply left inset
* @param top Whether to apply top inset
* @param right Whether to apply right inset
* @param bottom Whether to apply bottom inset
*/
public static void forceApplyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
applyWindowInsets(view, left, top, right, bottom, false, true);
}
/**
@@ -425,8 +454,9 @@ public class ViewUtil {
* @param right Whether to apply right inset
* @param bottom Whether to apply bottom inset
* @param consumeImeInsets Whether to consume IME insets so they don't propagate to child views
* @param forceDispatch Force application of Insets, regardless if system think it shall dispatch
*/
public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom, boolean consumeImeInsets) {
public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom, boolean consumeImeInsets, boolean forceDispatch) {
// Only enable on API 30+ where WindowInsets APIs work correctly
if (!isEdgeToEdgeSupported()) return;
@@ -469,7 +499,14 @@ public class ViewUtil {
// Request the initial insets to be dispatched if the view is attached
if (view.isAttachedToWindow()) {
ViewCompat.requestApplyInsets(view);
if (forceDispatch) {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view);
if (insets != null) {
ViewCompat.dispatchApplyWindowInsets(view, insets);
}
} else {
ViewCompat.requestApplyInsets(view);
}
}
}