Suppress LayoutTransition during scroll events.

This commit is contained in:
Alex Hart
2023-09-07 11:26:45 -03:00
committed by GitHub
parent b410756dfd
commit 454b1f69ed
8 changed files with 71 additions and 5 deletions

View File

@@ -217,6 +217,7 @@ class V2ConversationItemShapeTest {
override val isMessageRequestAccepted: Boolean = true
override val searchQuery: String? = null
override val glideRequests: GlideRequests = mockk()
override val isParentInScroll: Boolean = false
override fun onStartExpirationTimeout(messageRecord: MessageRecord) = Unit

View File

@@ -57,6 +57,10 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
void setEventListener(@Nullable EventListener listener);
default void setParentScrolling(boolean isParentScrolling) {
// Intentionally Blank.
}
default void updateTimestamps() {
// Intentionally Blank.
}

View File

@@ -16,6 +16,7 @@ interface ConversationAdapterBridge {
const val PAYLOAD_TIMESTAMP = 0
const val PAYLOAD_NAME_COLORS = 1
const val PAYLOAD_SELECTED = 2
const val PAYLOAD_PARENT_SCROLLING = 3
}
fun hasNoConversationMessages(): Boolean

View File

@@ -418,6 +418,11 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
this.conversationRecipient.observeForever(this);
}
@Override
public void setParentScrolling(boolean isParentScrolling) {
bodyBubble.setParentScrolling(isParentScrolling);
}
@Override
public void updateSelectedState() {
setHasBeenQuoted(conversationMessage);

View File

@@ -12,6 +12,7 @@ import androidx.annotation.Nullable;
import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.Outliner;
import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.util.Util;
@@ -30,19 +31,33 @@ public class ConversationItemBodyBubble extends LinearLayout {
private Projection quoteViewProjection;
private Projection videoPlayerProjection;
private final BodyBubbleLayoutTransition bodyBubbleLayoutTransition = new BodyBubbleLayoutTransition();
public ConversationItemBodyBubble(Context context) {
super(context);
setLayoutTransition(new BodyBubbleLayoutTransition());
init();
}
public ConversationItemBodyBubble(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setLayoutTransition(new BodyBubbleLayoutTransition());
init();
}
public ConversationItemBodyBubble(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setLayoutTransition(new BodyBubbleLayoutTransition());
init();
}
private void init() {
setLayoutTransition(bodyBubbleLayoutTransition);
}
public void setParentScrolling(boolean isParentScrolling) {
if (isParentScrolling) {
setLayoutTransition(null);
} else {
setLayoutTransition(bodyBubbleLayoutTransition);
}
}
public void setOutliners(@NonNull List<Outliner> outliners) {

View File

@@ -90,6 +90,10 @@ class ConversationAdapterV2(
override var isMessageRequestAccepted: Boolean = false
override var isParentInScroll: Boolean = false
private val onScrollStateChangedListener = OnScrollStateChangedListener()
init {
registerFactory(ThreadHeader::class.java, ::ThreadHeaderViewHolder, R.layout.conversation_item_thread_header)
@@ -162,6 +166,8 @@ class ConversationAdapterV2(
recyclerView.recycledViewPool.setMaxRecycledViews(type, count)
}
}
recyclerView.addOnScrollListener(onScrollStateChangedListener)
}
override fun onViewRecycled(holder: MappingViewHolder<*>) {
@@ -176,6 +182,8 @@ class ConversationAdapterV2(
.children
.filterIsInstance<Unbindable>()
.forEach { it.unbind() }
recyclerView.removeOnScrollListener(onScrollStateChangedListener)
}
override val displayMode: ConversationItemDisplayMode
@@ -498,6 +506,11 @@ class ConversationAdapterV2(
fun bindPayloadsIfAvailable(): Boolean {
var payloadApplied = false
bindable.setParentScrolling(isParentInScroll)
if (payload.contains(ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING)) {
payloadApplied = true
}
if (payload.contains(ConversationAdapterBridge.PAYLOAD_TIMESTAMP)) {
bindable.updateTimestamps()
payloadApplied = true
@@ -627,4 +640,14 @@ class ConversationAdapterV2(
}
}
}
private inner class OnScrollStateChangedListener : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
val oldState = isParentInScroll
isParentInScroll = newState != RecyclerView.SCROLL_STATE_IDLE
if (isParentInScroll != oldState) {
notifyItemRangeChanged(0, itemCount, ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING)
}
}
}
}

View File

@@ -23,6 +23,7 @@ interface V2ConversationContext {
val selectedItems: Set<MultiselectPart>
val isMessageRequestAccepted: Boolean
val searchQuery: String?
val isParentInScroll: Boolean
fun onStartExpirationTimeout(messageRecord: MessageRecord)

View File

@@ -100,6 +100,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
private val bodyBubbleDrawable = ChatColorsDrawable()
private val footerDrawable = ChatColorsDrawable()
private val bodyBubbleLayoutTransition = BodyBubbleLayoutTransition()
protected lateinit var shape: V2ConversationItemShape.MessageShape
@@ -155,7 +156,7 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
}
binding.conversationItemBodyWrapper.background = bodyBubbleDrawable
binding.conversationItemBodyWrapper.layoutTransition = BodyBubbleLayoutTransition()
binding.conversationItemBodyWrapper.layoutTransition = bodyBubbleLayoutTransition
binding.conversationItemFooterBackground.background = footerDrawable
}
@@ -166,6 +167,22 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
}
override fun bind(model: Model) {
var hasProcessedSupportedPayload = false
binding.conversationItemBodyWrapper.layoutTransition = if (conversationContext.isParentInScroll) {
null
} else {
bodyBubbleLayoutTransition
}
if (ConversationAdapterBridge.PAYLOAD_PARENT_SCROLLING in payload) {
if (payload.size == 1) {
return
} else {
hasProcessedSupportedPayload = true
}
}
check(model is ConversationMessageElement)
conversationMessage = model.conversationMessage
@@ -176,7 +193,6 @@ open class V2ConversationItemTextOnlyViewHolder<Model : MappingModel<Model>>(
adapterPosition = bindingAdapterPosition
)
var hasProcessedSupportedPayload = false
if (ConversationAdapterBridge.PAYLOAD_TIMESTAMP in payload) {
presentDate()
hasProcessedSupportedPayload = true