mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Fix wacky layout while scrolling in thread.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.animation.LayoutTransition
|
||||
import android.view.View
|
||||
import android.view.View.OnAttachStateChangeListener
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
/**
|
||||
* Helps manage layout transition state inside a RecyclerView.
|
||||
*
|
||||
* Because of how RecyclerViews scroll, we need to be very careful about LayoutTransition
|
||||
* usage inside of them. This class helps wrap up the pattern of finding and listening to
|
||||
* the scroll events of a parent recycler view, so that we don't need to manually wire
|
||||
* the scroll state in everywhere.
|
||||
*/
|
||||
class RecyclerViewParentTransitionController(
|
||||
private val child: ViewGroup,
|
||||
private val transition: LayoutTransition = LayoutTransition()
|
||||
) : RecyclerView.OnScrollListener(), OnAttachStateChangeListener {
|
||||
|
||||
private var recyclerViewParent: RecyclerView? = null
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
child.layoutTransition = transition
|
||||
} else {
|
||||
child.layoutTransition = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(v: View) {
|
||||
val parent = findRecyclerParent()
|
||||
|
||||
if (parent != null) {
|
||||
onScrollStateChanged(parent, parent.scrollState)
|
||||
}
|
||||
|
||||
parent?.addOnScrollListener(this)
|
||||
recyclerViewParent = parent
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(v: View) {
|
||||
recyclerViewParent?.removeOnScrollListener(this)
|
||||
child.layoutTransition = null
|
||||
}
|
||||
|
||||
private fun findRecyclerParent(): RecyclerView? {
|
||||
var target: ViewGroup? = child.parent as? ViewGroup
|
||||
while (target != null) {
|
||||
if (target is RecyclerView) {
|
||||
return target
|
||||
}
|
||||
|
||||
target = target.parent as? ViewGroup
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.components.transfercontrols
|
||||
|
||||
import android.animation.LayoutTransition
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
@@ -23,6 +22,7 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.components.RecyclerViewParentTransitionController
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.databinding.TransferControlsViewBinding
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent
|
||||
@@ -45,10 +45,11 @@ class TransferControlView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
binding = TransferControlsViewBinding.inflate(LayoutInflater.from(context), this)
|
||||
visibility = GONE
|
||||
isLongClickable = false
|
||||
layoutTransition = LayoutTransition()
|
||||
disposables += store.stateFlowable.distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()).subscribe {
|
||||
applyState(it)
|
||||
}
|
||||
|
||||
addOnAttachStateChangeListener(RecyclerViewParentTransitionController(child = this))
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
|
||||
Reference in New Issue
Block a user