scroll to bottom even if last visible item is heigher than view

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 34 
1 file changed, 22 insertions(+), 12 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -92,7 +92,6 @@ import eu.siacs.conversations.ui.util.ScrollState;
 import eu.siacs.conversations.ui.util.SendButtonAction;
 import eu.siacs.conversations.ui.util.SendButtonTool;
 import eu.siacs.conversations.ui.widget.EditMessage;
-import eu.siacs.conversations.utils.ExceptionHelper;
 import eu.siacs.conversations.utils.MessageUtils;
 import eu.siacs.conversations.utils.NickValidityChecker;
 import eu.siacs.conversations.utils.QuickLoader;
@@ -374,7 +373,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 		@Override
 		public void onClick(View v) {
 			stopScrolling();
-			setSelection(binding.messagesView.getCount() - 1);
+			setSelection(binding.messagesView.getCount() - 1, true);
 		}
 	};
 	private OnClickListener mSendButtonListener = new OnClickListener() {
@@ -1387,7 +1386,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 				return;
 			}
 			if (!transferable.start()) {
-				Log.d(Config.LOGTAG,"type: "+transferable.getClass().getName());
+				Log.d(Config.LOGTAG, "type: " + transferable.getClass().getName());
 				Toast.makeText(getActivity(), R.string.not_connected_try_again, Toast.LENGTH_SHORT).show();
 			}
 		} else if (message.treatAsDownloadable()) {
@@ -1827,7 +1826,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 			}
 		} else if (conversation == null && activity != null && activity.xmppConnectionService != null) {
 			final String uuid = pendingConversationsUuid.pop();
-			Log.d(Config.LOGTAG,"ConversationFragment.onStart() - activity was bound but no conversation loaded. uuid="+uuid);
+			Log.d(Config.LOGTAG, "ConversationFragment.onStart() - activity was bound but no conversation loaded. uuid=" + uuid);
 			if (uuid != null) {
 				findAndReInitByUuidOrArchive(uuid);
 			}
@@ -1938,13 +1937,16 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 				final Message first = conversation.getFirstUnreadMessage();
 				final int bottom = Math.max(0, this.messageList.size() - 1);
 				final int pos;
+				final boolean jumpToBottom;
 				if (first == null) {
 					pos = bottom;
+					jumpToBottom = true;
 				} else {
 					int i = getIndexOf(first.getUuid(), this.messageList);
 					pos = i < 0 ? bottom : i;
+					jumpToBottom = false;
 				}
-				setSelection(pos);
+				setSelection(pos, jumpToBottom);
 			}
 		}
 
@@ -1969,17 +1971,25 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
 		this.binding.unreadCountCustomView.setVisibility(View.GONE);
 	}
 
-	private void setSelection(int pos) {
-		this.binding.messagesView.setSelection(pos);
-		this.binding.messagesView.post(() -> this.binding.messagesView.setSelection(pos));
+	private void setSelection(int pos, boolean jumpToBottom) {
+		setSelection(this.binding.messagesView, pos, jumpToBottom);
+		this.binding.messagesView.post(() -> setSelection(this.binding.messagesView, pos, jumpToBottom));
 		this.binding.messagesView.post(this::fireReadEvent);
 	}
 
-	private boolean scrolledToBottom() {
-		if (this.binding == null) {
-			return false;
+	private static void setSelection(final ListView listView, int pos, boolean jumpToBottom) {
+		if (jumpToBottom) {
+			final View lastChild = listView.getChildAt(listView.getChildCount() - 1);
+			if (lastChild != null) {
+				listView.setSelectionFromTop(pos, -lastChild.getHeight());
+				return;
+			}
 		}
-		return scrolledToBottom(this.binding.messagesView);
+		listView.setSelection(pos);
+	}
+
+	private boolean scrolledToBottom() {
+		return this.binding != null && scrolledToBottom(this.binding.messagesView);
 	}
 
 	private void processExtras(Bundle extras) {