mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 21:15:48 +00:00
Scroll date header in CFV2.
This commit is contained in:
committed by
Nicholas Tinsley
parent
5731bf023a
commit
980f4e00e2
@@ -31,6 +31,7 @@ import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TextView
|
||||
@@ -274,6 +275,7 @@ import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.BubbleUtil
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.ContextUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.Debouncer
|
||||
import org.thoughtcrime.securesms.util.DeleteDialog
|
||||
import org.thoughtcrime.securesms.util.Dialogs
|
||||
@@ -332,6 +334,9 @@ class ConversationFragment :
|
||||
private const val ACTION_PINNED_SHORTCUT = "action_pinned_shortcut"
|
||||
private const val SAVED_STATE_IS_SEARCH_REQUESTED = "is_search_requested"
|
||||
private const val EMOJI_SEARCH_FRAGMENT_TAG = "EmojiSearchFragment"
|
||||
|
||||
private const val SCROLL_HEADER_ANIMATION_DURATION: Long = 100L
|
||||
private const val SCROLL_HEADER_CLOSE_DELAY: Long = SCROLL_HEADER_ANIMATION_DURATION * 4
|
||||
}
|
||||
|
||||
private val args: ConversationIntents.Args by lazy {
|
||||
@@ -1159,6 +1164,17 @@ class ConversationFragment :
|
||||
R.color.signal_colorBackground
|
||||
}
|
||||
|
||||
binding.scrollDateHeader.setBackgroundResource(
|
||||
if (wallpaperEnabled) R.drawable.sticky_date_header_background_wallpaper else R.drawable.sticky_date_header_background
|
||||
)
|
||||
|
||||
binding.scrollDateHeader.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
requireContext(),
|
||||
if (wallpaperEnabled) R.color.sticky_header_foreground_wallpaper else R.color.signal_colorOnSurfaceVariant
|
||||
)
|
||||
)
|
||||
|
||||
WindowUtil.setNavigationBarColor(requireActivity(), ContextCompat.getColor(requireContext(), navColor))
|
||||
}
|
||||
|
||||
@@ -2019,9 +2035,63 @@ class ConversationFragment :
|
||||
return layoutManager.findFirstCompletelyVisibleItemPosition() > 4
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls animation and visibility of the scrollDateHeader.
|
||||
*/
|
||||
private inner class ScrollDateHeaderHelper {
|
||||
|
||||
private val slideIn = AnimationUtils.loadAnimation(
|
||||
requireContext(),
|
||||
R.anim.slide_from_top
|
||||
).apply {
|
||||
duration = SCROLL_HEADER_ANIMATION_DURATION
|
||||
}
|
||||
|
||||
private val slideOut = AnimationUtils.loadAnimation(
|
||||
requireContext(),
|
||||
R.anim.conversation_scroll_date_header_slide_to_top
|
||||
).apply {
|
||||
duration = SCROLL_HEADER_ANIMATION_DURATION
|
||||
}
|
||||
|
||||
private var pendingHide = false
|
||||
|
||||
fun show() {
|
||||
if (binding.scrollDateHeader.text.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (pendingHide) {
|
||||
pendingHide = false
|
||||
} else {
|
||||
ViewUtil.animateIn(binding.scrollDateHeader, slideIn)
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(message: ConversationMessage?) {
|
||||
if (message != null) {
|
||||
binding.scrollDateHeader.text = DateUtils.getConversationDateHeaderString(requireContext(), Locale.getDefault(), message.conversationTimestamp)
|
||||
} else {
|
||||
binding.scrollDateHeader.text = null
|
||||
}
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
pendingHide = true
|
||||
|
||||
binding.scrollDateHeader.postDelayed({
|
||||
if (pendingHide) {
|
||||
pendingHide = false
|
||||
ViewUtil.animateOut(binding.scrollDateHeader, slideOut)
|
||||
}
|
||||
}, SCROLL_HEADER_CLOSE_DELAY)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ScrollListener : RecyclerView.OnScrollListener() {
|
||||
|
||||
private var wasAtBottom = true
|
||||
private val scrollDateHeaderHelper = ScrollDateHeaderHelper()
|
||||
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
if (isScrolledToBottom()) {
|
||||
@@ -2032,10 +2102,21 @@ class ConversationFragment :
|
||||
|
||||
presentComposeDivider()
|
||||
|
||||
val message = adapter.getConversationMessage(layoutManager.findLastVisibleItemPosition())
|
||||
scrollDateHeaderHelper.bind(message)
|
||||
|
||||
val timestamp = MarkReadHelper.getLatestTimestamp(adapter, layoutManager)
|
||||
timestamp.ifPresent(markReadHelper::onViewsRevealed)
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
scrollDateHeaderHelper.show()
|
||||
} else {
|
||||
scrollDateHeaderHelper.hide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun presentComposeDivider() {
|
||||
val isAtBottom = isScrolledToBottom()
|
||||
if (isAtBottom && !wasAtBottom) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<alpha
|
||||
android:fromAlpha="1"
|
||||
android:toAlpha="0" />
|
||||
|
||||
<translate
|
||||
android:fromYDelta="0%"
|
||||
android:toYDelta="-100%" />
|
||||
</set>
|
||||
@@ -51,6 +51,27 @@
|
||||
tools:itemCount="20"
|
||||
tools:listitem="@layout/conversation_item_sent_text_only" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/scroll_date_header"
|
||||
style="@style/Signal.Text.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/sticky_date_header_background"
|
||||
android:elevation="9dp"
|
||||
android:gravity="center"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:textColor="@color/signal_colorOnSurfaceVariant"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/conversation_banner"
|
||||
tools:text="March 1, 2015"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/toolbar_background"
|
||||
android:layout_width="0dp"
|
||||
|
||||
Reference in New Issue
Block a user