Add animation

This commit is contained in:
Niels Andriesse 2021-06-16 15:49:39 +10:00
parent 5ae201b81b
commit bdc5a0e5d9
4 changed files with 132 additions and 61 deletions

View File

@ -1,5 +1,7 @@
package org.thoughtcrime.securesms.conversation.v2 package org.thoughtcrime.securesms.conversation.v2
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.database.Cursor import android.database.Cursor
import android.os.Bundle import android.os.Bundle
import android.view.ActionMode import android.view.ActionMode
@ -20,6 +22,7 @@ import org.thoughtcrime.securesms.conversation.v2.menus.ConversationActionModeCa
import org.thoughtcrime.securesms.conversation.v2.menus.ConversationMenuHelper import org.thoughtcrime.securesms.conversation.v2.menus.ConversationMenuHelper
import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetView
import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideApp
class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate { class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDelegate {
@ -115,7 +118,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} }
override fun showVoiceMessageUI() { override fun showVoiceMessageUI() {
inputBarRecordingView.isVisible = true inputBarRecordingView.show()
} }
// endregion // endregion

View File

@ -1,10 +1,19 @@
package org.thoughtcrime.securesms.conversation.v2.input_bar package org.thoughtcrime.securesms.conversation.v2.input_bar
import android.animation.Animator
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
import network.loki.messenger.R import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.animateSizeChange
import org.thoughtcrime.securesms.loki.utilities.toPx
import kotlin.math.roundToInt
class InputBarRecordingView : RelativeLayout { class InputBarRecordingView : RelativeLayout {
@ -15,4 +24,29 @@ class InputBarRecordingView : RelativeLayout {
private fun initialize() { private fun initialize() {
LayoutInflater.from(context).inflate(R.layout.view_input_bar_recording, this) LayoutInflater.from(context).inflate(R.layout.view_input_bar_recording, this)
} }
fun show() {
isVisible = true
alpha = 0.0f
val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.0f, 1.0f)
animation.duration = 250L
animation.addUpdateListener { animator ->
alpha = animator.animatedValue as Float
}
animation.start()
pulse()
}
private fun pulse() {
val collapsedSize = toPx(80.0f, resources)
val expandedSize = toPx(104.0f, resources)
pulseView.animateSizeChange(collapsedSize, expandedSize, 1000)
val animation = ValueAnimator.ofObject(FloatEvaluator(), 0.5, 0.0f)
animation.duration = 1000L
animation.addUpdateListener { animator ->
pulseView.alpha = animator.animatedValue as Float
if (animator.animatedFraction == 1.0f) { pulse() }
}
animation.start()
}
} }

View File

@ -21,9 +21,13 @@ val View.hitRect: Rect
} }
fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) { fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) {
val layoutParams = this.layoutParams
val startSize = resources.getDimension(startSizeID) val startSize = resources.getDimension(startSizeID)
val endSize = resources.getDimension(endSizeID) val endSize = resources.getDimension(endSizeID)
animateSizeChange(startSize, endSize)
}
fun View.animateSizeChange(startSize: Float, endSize: Float, animationDuration: Long = 250) {
val layoutParams = this.layoutParams
val animation = ValueAnimator.ofObject(FloatEvaluator(), startSize, endSize) val animation = ValueAnimator.ofObject(FloatEvaluator(), startSize, endSize)
animation.duration = animationDuration animation.duration = animationDuration
animation.addUpdateListener { animator -> animation.addUpdateListener { animator ->

View File

@ -3,93 +3,123 @@
xmlns:android="http://schemas.android.com/apk/res/android" 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"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp"> android:layout_height="92dp">
<!-- The height of the fake input bar below is 68 dp <!-- The fake input bar -->
because the input bar is 56 dp but we have to
account for the fact that this whole view has a
negative bottom margin of 12 dp -->
<LinearLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="68dp" android:layout_height="@dimen/input_bar_height"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_marginBottom="12dp"
android:orientation="vertical"> android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/separator" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/input_bar_background" /> android:background="@color/input_bar_background" />
</LinearLayout> <!-- The left content (dot view + duration) -->
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/medium_spacing" android:layout_marginStart="@dimen/medium_spacing"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<View
android:layout_width="16dp"
android:layout_height="16dp"
android:background="@drawable/circle_tintable"
android:backgroundTint="@color/destructive" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_spacing"
android:text="00:00"
android:textSize="@dimen/small_font_size"
android:textColor="@color/text" />
</LinearLayout>
<!-- The middle content (left arrow + slide to cancel) -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_keyboard_arrow_left_grey600_24dp"
android:layout_marginTop="1dp"
app:tint="@color/text"
android:alpha="0.6" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:text="@string/conversation_input_panel__slide_to_cancel"
android:textSize="@dimen/very_small_font_size"
android:textColor="@color/text"
android:alpha="0.6" />
</LinearLayout>
<!-- Separator -->
<View <View
android:layout_width="16dp" android:layout_width="match_parent"
android:layout_height="16dp" android:layout_height="1px"
android:layout_alignParentTop="true"
android:background="@color/separator" />
</RelativeLayout>
<!-- The pulse view -->
<RelativeLayout
android:layout_width="104dp"
android:layout_height="104dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="-20dp"
android:layout_marginBottom="-12dp">
<View
android:id="@+id/pulseView"
android:layout_width="80dp"
android:layout_height="80dp"
android:alpha="0.5"
android:layout_centerInParent="true"
android:background="@drawable/circle_tintable" android:background="@drawable/circle_tintable"
android:backgroundTint="@color/destructive" /> android:backgroundTint="@color/destructive" />
<TextView </RelativeLayout>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/small_spacing"
android:text="00:00"
android:textSize="@dimen/small_font_size"
android:textColor="@color/text" />
</LinearLayout> <!-- The actual record button overlay -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_keyboard_arrow_left_grey600_24dp"
android:layout_marginTop="1dp"
app:tint="@color/text"
android:alpha="0.6" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:text="@string/conversation_input_panel__slide_to_cancel"
android:textSize="@dimen/very_small_font_size"
android:textColor="@color/text"
android:alpha="0.6" />
</LinearLayout>
<RelativeLayout <RelativeLayout
android:layout_width="80dp" android:layout_width="80dp"
android:layout_height="80dp" android:layout_height="80dp"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="-8dp" android:layout_marginEnd="-8dp"
android:layout_marginBottom="0dp"
android:background="@drawable/circle_tintable" android:background="@drawable/circle_tintable"
android:backgroundTint="@color/destructive" > android:backgroundTint="@color/destructive" >
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="16dp"
android:layout_height="24dp" android:layout_height="16dp"
app:tint="@color/white" app:tint="@color/white"
android:scaleType="centerInside" android:scaleType="centerInside"
android:layout_centerInParent="true" android:layout_centerInParent="true"