Add animation when switching from chats to calls.

This commit is contained in:
Alex Hart
2023-05-02 13:09:44 -03:00
parent 3c343af562
commit 6791d2d46e
4 changed files with 79 additions and 24 deletions

View File

@@ -11,14 +11,18 @@ import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.SharedElementCallback
import androidx.core.view.MenuProvider
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.transition.TransitionInflater
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.kotlin.Flowables
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.util.DimensionUnit
@@ -52,6 +56,7 @@ import org.thoughtcrime.securesms.util.doAfterNextLayout
import org.thoughtcrime.securesms.util.fragments.requireListener
import org.thoughtcrime.securesms.util.visible
import java.util.Objects
import java.util.concurrent.TimeUnit
/**
* Call Log tab.
@@ -94,6 +99,7 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
requireActivity().addMenuProvider(menuProvider, viewLifecycleOwner)
initializeSharedElementTransition()
val adapter = CallLogAdapter(this)
disposables.bindTo(viewLifecycleOwner)
@@ -181,6 +187,26 @@ class CallLogFragment : Fragment(R.layout.call_log_fragment), CallLogAdapter.Cal
viewModel.markAllCallEventsRead()
}
private fun initializeSharedElementTransition() {
ViewCompat.setTransitionName(binding.fab, "new_convo_fab")
ViewCompat.setTransitionName(binding.fabSharedElementTarget, "camera_fab")
sharedElementEnterTransition = TransitionInflater.from(requireContext()).inflateTransition(R.transition.change_transform_fabs)
setEnterSharedElementCallback(object : SharedElementCallback() {
override fun onSharedElementStart(sharedElementNames: MutableList<String>?, sharedElements: MutableList<View>?, sharedElementSnapshots: MutableList<View>?) {
if (sharedElementNames?.contains("camera_fab") == true) {
this@CallLogFragment.binding.fab.setImageResource(R.drawable.symbol_edit_24)
disposables += Single.timer(200, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy {
this@CallLogFragment.binding.fab.setImageResource(R.drawable.symbol_phone_plus_24)
this@CallLogFragment.binding.fabSharedElementTarget.alpha = 0f
}
}
}
})
}
private fun initializeTapToScrollToTop(scrollToPositionDelegate: ScrollToPositionDelegate) {
disposables += tabsViewModel.tabClickEvents
.filter { it == ConversationListTab.CALLS }

View File

@@ -112,7 +112,7 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
private fun goToStateFromConversationList(state: ConversationListTabsState, navController: NavController) {
if (state.tab == ConversationListTab.CHATS) {
return
} else if (state.tab == ConversationListTab.STORIES) {
} else {
val cameraFab = requireView().findViewById<View>(R.id.camera_fab)
val newConvoFab = requireView().findViewById<View>(R.id.fab)
@@ -128,19 +128,18 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
)
}
val destination = if (state.tab == ConversationListTab.STORIES) {
R.id.action_conversationListFragment_to_storiesLandingFragment
} else {
R.id.action_conversationListFragment_to_callLogFragment
}
navController.navigate(
R.id.action_conversationListFragment_to_storiesLandingFragment,
destination,
null,
null,
extras
)
} else {
navController.navigate(
R.id.action_conversationListFragment_to_callLogFragment,
null,
null,
null
)
}
}
@@ -350,14 +349,17 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
conversationListTabsViewModel.isShowingArchived(false)
presentToolbarForConversationListFragment()
}
R.id.conversationListArchiveFragment -> {
conversationListTabsViewModel.isShowingArchived(true)
presentToolbarForConversationListArchiveFragment()
}
R.id.storiesLandingFragment -> {
conversationListTabsViewModel.isShowingArchived(false)
presentToolbarForStoriesLandingFragment()
}
R.id.callLogFragment -> {
conversationListTabsViewModel.isShowingArchived(false)
presentToolbarForCallLogFragment()

View File

@@ -88,7 +88,7 @@ class ConversationListTabsViewModel(repository: ConversationListTabRepository) :
}
}
private fun <T: Any> performStoreUpdate(flowable: Flowable<T>, fn: (T, ConversationListTabsState) -> ConversationListTabsState): Disposable {
private fun <T : Any> performStoreUpdate(flowable: Flowable<T>, fn: (T, ConversationListTabsState) -> ConversationListTabsState): Disposable {
return store.update(flowable) { t, state ->
fn(t, state.copy(prevTab = state.tab))
}

View File

@@ -66,21 +66,48 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:contentDescription="@string/CallLogFragment__start_a_new_call"
android:focusable="true"
android:theme="@style/Widget.Material3.FloatingActionButton.Secondary"
android:transitionName="new_convo_fab"
app:backgroundTint="@color/signal_colorPrimaryContainer"
app:shapeAppearanceOverlay="@style/Signal.ShapeOverlay.Rounded.Fab"
app:srcCompat="@drawable/symbol_phone_plus_24"
app:tint="@color/signal_colorOnSurface" />
android:layout_gravity="bottom"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_behavior="org.thoughtcrime.securesms.util.views.SlideUpWithSnackbarBehavior">
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
android:id="@+id/fab_shared_element_target"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:focusable="true"
android:theme="@style/Widget.Material3.FloatingActionButton.Secondary"
android:transitionName="camera_fab"
app:shapeAppearanceOverlay="@style/Signal.ShapeOverlay.Rounded.Fab"
app:backgroundTint="@color/signal_colorSurfaceVariant"
app:elevation="0dp"
app:srcCompat="@drawable/ic_camera_outline_24"
app:tint="@color/signal_colorOnSurface" />
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:contentDescription="@string/CallLogFragment__start_a_new_call"
android:focusable="true"
android:theme="@style/Widget.Material3.FloatingActionButton.Secondary"
android:transitionName="new_convo_fab"
app:backgroundTint="@color/signal_colorPrimaryContainer"
app:shapeAppearanceOverlay="@style/Signal.ShapeOverlay.Rounded.Fab"
app:srcCompat="@drawable/symbol_phone_plus_24"
app:tint="@color/signal_colorOnSurface" />
</FrameLayout>
<org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
android:id="@+id/bottom_action_bar"