Add animations to camera toggle.

fork-5.53.8
Alex Hart 2022-03-24 09:01:05 -03:00 zatwierdzone przez Greyson Parrelli
rodzic e9160c2449
commit f6f4e6fde7
6 zmienionych plików z 165 dodań i 95 usunięć

Wyświetl plik

@ -1,18 +1,24 @@
package org.thoughtcrime.securesms.mediasend.v2 package org.thoughtcrime.securesms.mediasend.v2
import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.widget.TextView
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.transition.AutoTransition
import androidx.transition.TransitionManager
import com.google.android.material.animation.ArgbEvaluatorCompat
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.PassphraseRequiredActivity import org.thoughtcrime.securesms.PassphraseRequiredActivity
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
@ -43,6 +49,11 @@ class MediaSelectionActivity :
EmojiSearchFragment.Callback, EmojiSearchFragment.Callback,
SearchConfigurationProvider { SearchConfigurationProvider {
private var animateInShadowLayerValueAnimator: ValueAnimator? = null
private var animateInTextColorValueAnimator: ValueAnimator? = null
private var animateOutShadowLayerValueAnimator: ValueAnimator? = null
private var animateOutTextColorValueAnimator: ValueAnimator? = null
lateinit var viewModel: MediaSelectionViewModel lateinit var viewModel: MediaSelectionViewModel
private val textViewModel: TextStoryPostCreationViewModel by viewModels() private val textViewModel: TextStoryPostCreationViewModel by viewModels()
@ -69,9 +80,16 @@ class MediaSelectionActivity :
val factory = MediaSelectionViewModel.Factory(destination, transportOption, initialMedia, message, isReply, MediaSelectionRepository(this)) val factory = MediaSelectionViewModel.Factory(destination, transportOption, initialMedia, message, isReply, MediaSelectionRepository(this))
viewModel = ViewModelProvider(this, factory)[MediaSelectionViewModel::class.java] viewModel = ViewModelProvider(this, factory)[MediaSelectionViewModel::class.java]
val textStoryToggle: ViewGroup = findViewById(R.id.switch_widget) val textStoryToggle: ConstraintLayout = findViewById(R.id.switch_widget)
val textSwitch: View = findViewById(R.id.text_switch) val cameraSelectedConstraintSet = ConstraintSet().apply {
val cameraSwitch: View = findViewById(R.id.camera_switch) clone(textStoryToggle)
}
val textSelectedConstraintSet = ConstraintSet().apply {
clone(this@MediaSelectionActivity, R.layout.media_selection_activity_text_selected_constraints)
}
val textSwitch: TextView = findViewById(R.id.text_switch)
val cameraSwitch: TextView = findViewById(R.id.camera_switch)
textSwitch.setOnClickListener { textSwitch.setOnClickListener {
viewModel.sendCommand(HudCommand.GoToText) viewModel.sendCommand(HudCommand.GoToText)
@ -101,13 +119,17 @@ class MediaSelectionActivity :
when (d.id) { when (d.id) {
R.id.mediaCaptureFragment -> { R.id.mediaCaptureFragment -> {
textStoryToggle.visible = canDisplayStorySwitch() textStoryToggle.visible = canDisplayStorySwitch()
textSwitch.isSelected = false
cameraSwitch.isSelected = true animateTextStyling(cameraSwitch, textSwitch, 200)
TransitionManager.beginDelayedTransition(textStoryToggle, AutoTransition().setDuration(200))
cameraSelectedConstraintSet.applyTo(textStoryToggle)
} }
R.id.textStoryPostCreationFragment -> { R.id.textStoryPostCreationFragment -> {
textStoryToggle.visible = canDisplayStorySwitch() textStoryToggle.visible = canDisplayStorySwitch()
textSwitch.isSelected = true
cameraSwitch.isSelected = false animateTextStyling(textSwitch, cameraSwitch, 200)
TransitionManager.beginDelayedTransition(textStoryToggle, AutoTransition().setDuration(200))
textSelectedConstraintSet.applyTo(textStoryToggle)
} }
else -> textStoryToggle.visible = false else -> textStoryToggle.visible = false
} }
@ -116,6 +138,36 @@ class MediaSelectionActivity :
onBackPressedDispatcher.addCallback(OnBackPressed()) onBackPressedDispatcher.addCallback(OnBackPressed())
} }
private fun animateTextStyling(selectedSwitch: TextView, unselectedSwitch: TextView, duration: Long) {
animateInShadowLayerValueAnimator?.cancel()
animateInTextColorValueAnimator?.cancel()
animateOutShadowLayerValueAnimator?.cancel()
animateOutTextColorValueAnimator?.cancel()
animateInShadowLayerValueAnimator = ValueAnimator.ofFloat(selectedSwitch.shadowRadius, 0f).apply {
this.duration = duration
addUpdateListener { selectedSwitch.setShadowLayer(it.animatedValue as Float, 0f, 0f, Color.BLACK) }
start()
}
animateInTextColorValueAnimator = ValueAnimator.ofInt(selectedSwitch.currentTextColor, Color.BLACK).apply {
setEvaluator(ArgbEvaluatorCompat.getInstance())
this.duration = duration
addUpdateListener { selectedSwitch.setTextColor(it.animatedValue as Int) }
start()
}
animateOutShadowLayerValueAnimator = ValueAnimator.ofFloat(unselectedSwitch.shadowRadius, 3f).apply {
this.duration = duration
addUpdateListener { unselectedSwitch.setShadowLayer(it.animatedValue as Float, 0f, 0f, Color.BLACK) }
start()
}
animateOutTextColorValueAnimator = ValueAnimator.ofInt(unselectedSwitch.currentTextColor, Color.WHITE).apply {
setEvaluator(ArgbEvaluatorCompat.getInstance())
this.duration = duration
addUpdateListener { unselectedSwitch.setTextColor(it.animatedValue as Int) }
start()
}
}
private fun canDisplayStorySwitch(): Boolean { private fun canDisplayStorySwitch(): Boolean {
return Stories.isFeatureEnabled() && return Stories.isFeatureEnabled() &&
FeatureFlags.storiesTextPosts() && FeatureFlags.storiesTextPosts() &&

Wyświetl plik

@ -1,12 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape
android:shape="rectangle">
<solid android:color="@color/white" /> <shape xmlns:android="http://schemas.android.com/apk/res/android"
<corners android:radius="42dp" /> android:shape="rectangle">
</shape> <solid android:color="@color/white" />
</item> <corners android:radius="42dp" />
</selector>
</shape>

Wyświetl plik

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/transparent_black_40" />
<corners android:radius="52dp" />
</shape>

Wyświetl plik

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -11,82 +12,54 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/switch_widget" android:id="@+id/switch_widget"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="48dp"
android:layout_gravity="bottom|center_horizontal" android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp">
android:background="@drawable/story_pill_toggle_background">
<FrameLayout <View
android:id="@+id/text_switch" android:id="@+id/selected_pill"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="0dp"
android:background="@drawable/story_pill_button_background" android:background="@drawable/story_pill_button_background"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="@id/camera_switch"
app:layout_constraintEnd_toStartOf="@id/camera_switch" app:layout_constraintEnd_toEndOf="@id/camera_switch"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="@id/camera_switch"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="@id/camera_switch" />
<TextView <TextView
android:id="@+id/camera_switch_mirror"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_gravity="center"
android:gravity="center"
android:paddingHorizontal="18dp"
android:text="@string/MediaSelectionActivity__camera"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color"
android:visibility="invisible" />
<TextView
android:id="@+id/text_switch_actual"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_gravity="center"
android:gravity="center"
android:paddingHorizontal="18dp"
android:text="@string/MediaSelectionActivity__text"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color" />
</FrameLayout>
<FrameLayout
android:id="@+id/camera_switch" android:id="@+id/camera_switch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="36sp"
android:layout_marginStart="2dp" android:gravity="center"
android:layout_marginTop="2dp" android:paddingHorizontal="18dp"
android:layout_marginBottom="2dp" android:shadowColor="@color/black"
android:background="@drawable/story_pill_button_background" android:text="@string/MediaSelectionActivity__camera"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/text_switch" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:background="@color/red" />
<TextView <TextView
android:id="@+id/text_switch_mirror" android:id="@+id/text_switch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="36dp" android:layout_height="36sp"
android:layout_gravity="center" android:gravity="center"
android:gravity="center" android:paddingHorizontal="18dp"
android:paddingHorizontal="18dp" android:shadowColor="@color/black"
android:text="@string/MediaSelectionActivity__text" android:shadowRadius="3"
android:textAppearance="@style/TextAppearance.Signal.Body2" android:text="@string/MediaSelectionActivity__text"
android:textColor="@color/story_pill_text_color" android:textAppearance="@style/TextAppearance.Signal.Body2"
android:visibility="invisible" /> android:textColor="@color/story_pill_text_color"
app:layout_constraintBottom_toBottomOf="parent"
<TextView app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/camera_switch_actual" app:layout_constraintHorizontal_bias="0"
android:layout_width="wrap_content" app:layout_constraintStart_toEndOf="@id/camera_switch"
android:layout_height="36dp" app:layout_constraintTop_toTopOf="parent"
android:layout_gravity="center" tools:background="@color/green" />
android:gravity="center"
android:paddingHorizontal="18dp"
android:text="@string/MediaSelectionActivity__camera"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>

Wyświetl plik

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/switch_widget"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="8dp">
<View
android:id="@+id/selected_pill"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="@id/text_switch"
app:layout_constraintEnd_toEndOf="@id/text_switch"
app:layout_constraintStart_toStartOf="@id/text_switch"
app:layout_constraintTop_toTopOf="@id/text_switch" />
<TextView
android:id="@+id/camera_switch"
android:layout_width="wrap_content"
android:layout_height="36sp"
android:gravity="center"
android:paddingHorizontal="18dp"
android:text="@string/MediaSelectionActivity__camera"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/text_switch"
app:layout_constraintHorizontal_bias="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="@color/red" />
<TextView
android:id="@+id/text_switch"
android:layout_width="wrap_content"
android:layout_height="36sp"
android:gravity="center"
android:paddingHorizontal="18dp"
android:text="@string/MediaSelectionActivity__text"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/story_pill_text_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="@color/green" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -15,7 +15,11 @@
app:destination="@id/mediaGalleryFragment" /> app:destination="@id/mediaGalleryFragment" />
<action <action
android:id="@+id/action_mediaCaptureFragment_to_textStoryPostCreationFragment" android:id="@+id/action_mediaCaptureFragment_to_textStoryPostCreationFragment"
app:destination="@id/textStoryPostCreationFragment" /> app:destination="@id/textStoryPostCreationFragment"
app:enterAnim="@anim/slide_from_end"
app:exitAnim="@null"
app:popEnterAnim="@null"
app:popExitAnim="@anim/slide_to_end" />
</fragment> </fragment>
<fragment <fragment
@ -43,7 +47,7 @@
android:id="@+id/textStoryPostCreationFragment" android:id="@+id/textStoryPostCreationFragment"
android:name="org.thoughtcrime.securesms.mediasend.v2.text.TextStoryPostCreationFragment" android:name="org.thoughtcrime.securesms.mediasend.v2.text.TextStoryPostCreationFragment"
android:label="text_story_post_creation_fragment" android:label="text_story_post_creation_fragment"
tools:layout="@layout/stories_text_post_creation_fragment" > tools:layout="@layout/stories_text_post_creation_fragment">
<action <action
android:id="@+id/action_textStoryPostCreationFragment_to_textStoryPostSendFragment" android:id="@+id/action_textStoryPostCreationFragment_to_textStoryPostSendFragment"
app:destination="@id/textStoryPostSendFragment" /> app:destination="@id/textStoryPostSendFragment" />