kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add animations to camera toggle.
rodzic
e9160c2449
commit
f6f4e6fde7
|
@ -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() &&
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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" />
|
||||||
|
|
Ładowanie…
Reference in New Issue